From a0a31da8011af07c0fb8545e205052bef574b230 Mon Sep 17 00:00:00 2001 From: Julio Montoya Date: Thu, 28 May 2020 15:13:21 +0200 Subject: [PATCH] Update from 1.11.x --- public/main/inc/lib/exercise.lib.php | 139 +- public/main/inc/lib/extra_field.lib.php | 2557 +++++++++-------- .../main/inc/lib/extra_field_option.lib.php | 44 +- public/main/inc/lib/extra_field_value.lib.php | 81 +- public/main/inc/lib/glossary.lib.php | 35 +- public/main/inc/lib/groupmanager.lib.php | 60 +- public/main/inc/lib/image.lib.php | 2 + public/main/inc/lib/legal.lib.php | 3 +- public/main/inc/lib/message.lib.php | 179 +- public/main/inc/lib/myspace.lib.php | 95 +- public/main/inc/lib/sessionmanager.lib.php | 362 ++- public/main/inc/lib/sortable_table.class.php | 29 +- public/main/inc/lib/text.lib.php | 2 + public/main/inc/lib/tracking.lib.php | 385 ++- public/main/inc/lib/usergroup.lib.php | 62 +- public/main/inc/lib/usermanager.lib.php | 11 +- public/main/inc/lib/webservices/Rest.php | 19 +- src/CoreBundle/Controller/IndexController.php | 1 - .../Controller/SecurityController.php | 1 - src/CoreBundle/Entity/User.php | 2 - src/CoreBundle/EventListener/TwigListener.php | 1 + .../Security/LoginFormAuthenticator.php | 2 +- 22 files changed, 2488 insertions(+), 1584 deletions(-) diff --git a/public/main/inc/lib/exercise.lib.php b/public/main/inc/lib/exercise.lib.php index 6189f320a0..d4645c2f0e 100644 --- a/public/main/inc/lib/exercise.lib.php +++ b/public/main/inc/lib/exercise.lib.php @@ -930,7 +930,12 @@ class ExerciseLib WHERE exe_id = $exe_id AND question_id= $questionId"; $rsLastAttempt = Database::query($sql); $rowLastAttempt = Database::fetch_array($rsLastAttempt); - $answer = $rowLastAttempt['answer']; + + $answer = null; + if (isset($rowLastAttempt['answer'])) { + $answer = $rowLastAttempt['answer']; + } + if (empty($answer)) { $_SESSION['calculatedAnswerId'][$questionId] = mt_rand( 1, @@ -1277,7 +1282,7 @@ HTML; $s .= " "; - return $extra_data; + return $html; } /** - * @param string $field_type + * @param string $variable + * @param string $text * - * @return array + * @return string */ - public function get_all_extra_field_by_type($field_type) + public static function getLocalizationInput($variable, $text) { - // all the information of the field - $sql = "SELECT * FROM {$this->table} - WHERE - field_type = '".Database::escape_string($field_type)."' AND - extra_field_type = $this->extraFieldType - "; - $result = Database::query($sql); - - $return = []; - while ($row = Database::fetch_array($result)) { - $return[] = $row['id']; - } + $html = ' +
+ +
+ + +
+
+
+ +
+
+
+
+
+ '; - return $return; + return $html; } /** - * @return array + * @return int */ - public function get_field_types() + public function get_count() { - return $this->get_extra_fields_by_handler($this->type); + $em = Database::getManager(); + $query = $em->getRepository('ChamiloCoreBundle:ExtraField')->createQueryBuilder('e'); + $query->select('count(e.id)'); + $query->where('e.extraFieldType = :type'); + $query->setParameter('type', $this->getExtraFieldType()); + + return $query->getQuery()->getSingleScalarResult(); } /** - * @param int $id + * @return int */ - public function get_field_type_by_id($id) + public function getExtraFieldType() { - $types = $this->get_field_types(); - if (isset($types[$id])) { - return $types[$id]; - } - - return null; + return (int) $this->extraFieldType; } /** - * Converts a string like this: - * France:Paris;Bretagne;Marseille;Lyon|Belgique:Bruxelles;Namur;Liège;Bruges|Peru:Lima;Piura; - * into - * array( - * 'France' => - * array('Paris', 'Bretagne', 'Marseille'), - * 'Belgique' => - * array('Namur', 'Liège') - * ), etc. - * - * @param string $string + * @param string $sidx + * @param string $sord + * @param int $start + * @param int $limit * * @return array */ - public static function extra_field_double_select_convert_string_to_array($string) + public function getAllGrid($sidx, $sord, $start, $limit) { - $options = explode('|', $string); - $options_parsed = []; - $id = 0; - - if (!empty($options)) { - foreach ($options as $sub_options) { - $options = explode(':', $sub_options); - $sub_sub_options = isset($options[1]) ? explode(';', $options[1]) : []; - $options_parsed[$id] = [ - 'label' => $options[0], - 'options' => $sub_sub_options, - ]; - $id++; - } + switch ($sidx) { + case 'field_order': + $sidx = 'e.fieldOrder'; + break; + case 'variable': + $sidx = 'e.variable'; + break; + case 'display_text': + $sidx = 'e.displayText'; + break; + case 'changeable': + $sidx = 'e.changeable'; + break; + case 'visible_to_self': + $sidx = 'e.visibleToSelf'; + break; + case 'visible_to_others': + $sidx = 'e.visibleToOthers'; + break; + case 'filter': + $sidx = 'e.filter'; + break; } + $em = Database::getManager(); + $query = $em->getRepository('ChamiloCoreBundle:ExtraField')->createQueryBuilder('e'); + $query->select('e') + ->where('e.extraFieldType = :type') + ->setParameter('type', $this->getExtraFieldType()) + ->orderBy($sidx, $sord) + ->setFirstResult($start) + ->setMaxResults($limit); - return $options_parsed; + return $query->getQuery()->getArrayResult(); } /** - * @param $string + * Get all the field info for tags. * - * @return array + * @param string $variable + * + * @return array|bool */ - public static function tripleSelectConvertStringToArray($string) + public function get_handler_field_info_by_tags($variable) { - $options = []; - - foreach (explode('|', $string) as $i => $item0) { - $level1 = explode('\\', $item0); - - foreach ($level1 as $j => $item1) { - if (0 === $j) { - $options[] = ['label' => $item1, 'options' => []]; + $variable = Database::escape_string($variable); + $sql = "SELECT * FROM {$this->table} + WHERE + variable = '$variable' AND + extra_field_type = $this->extraFieldType"; + $result = Database::query($sql); + if (Database::num_rows($result)) { + $row = Database::fetch_array($result, 'ASSOC'); + $row['display_text'] = $this->translateDisplayName( + $row['variable'], + $row['display_text'] + ); - continue; + // All the options of the field + $sql = "SELECT * FROM $this->table_field_tag + WHERE field_id='".intval($row['id'])."' + ORDER BY id ASC"; + $result = Database::query($sql); + while ($option = Database::fetch_array($result, 'ASSOC')) { + $row['options'][$option['id']] = $option; } - foreach (explode(':', $item1) as $k => $item2) { - if (0 === $k) { - $options[$i]['options'][] = ['label' => $item2, 'options' => []]; - - continue; - } - - $options[$i]['options'][$j - 1]['options'][] = explode(';', $item2); - } + return $row; + } else { + return false; } } - array_walk_recursive($options, function (&$item) { - $item = trim($item); - }); - - return $options; - } - /** - * @param array $options + * Translate the display text for a extra field. * - * @return array + * @param string $variable + * @param string $defaultDisplayText + * + * @return string */ - public static function extra_field_double_select_convert_array_to_ordered_array($options) + public static function translateDisplayName($variable, $defaultDisplayText) { - $options_parsed = []; - if (!empty($options)) { - foreach ($options as $option) { - if (0 == $option['option_value']) { - $options_parsed[$option['id']][] = $option; - } else { - $options_parsed[$option['option_value']][] = $option; - } - } - } + $camelCase = api_underscore_to_camel_case($variable); - return $options_parsed; + return isset($GLOBALS[$camelCase]) ? $GLOBALS[$camelCase] : $defaultDisplayText; } /** - * @return array + * @param int $fieldId + * + * @return array|bool */ - public static function tripleSelectConvertArrayToOrderedArray(array $options) + public function getFieldInfoByFieldId($fieldId) { - $level1 = self::getOptionsFromTripleSelect($options, 0); - $level2 = []; - $level3 = []; + $fieldId = (int) $fieldId; + $sql = "SELECT * FROM {$this->table} + WHERE + id = '$fieldId' AND + extra_field_type = $this->extraFieldType"; + $result = Database::query($sql); + if (Database::num_rows($result)) { + $row = Database::fetch_array($result, 'ASSOC'); - foreach ($level1 as $item1) { - $level2 += self::getOptionsFromTripleSelect($options, $item1['id']); - } + // All the options of the field + $sql = "SELECT * FROM $this->table_field_options + WHERE field_id='".$fieldId."' + ORDER BY option_order ASC"; + $result = Database::query($sql); + while ($option = Database::fetch_array($result)) { + $row['options'][$option['id']] = $option; + } - foreach ($level2 as $item2) { - $level3 += self::getOptionsFromTripleSelect($options, $item2['id']); + return $row; + } else { + return false; } - - return ['level1' => $level1, 'level2' => $level2, 'level3' => $level3]; } /** - * @param array $options the result of the get_field_options_by_field() array + * Add elements to a form. * - * @return string + * @param FormValidator $form The form object to which to attach this element + * @param int $itemId The item (course, user, session, etc) this extra_field is linked to + * @param array $exclude Variables of extra field to exclude + * @param bool $filter Whether to get only the fields with the "filter" flag set to 1 (true) + * or not (false) + * @param bool $useTagAsSelect Whether to show tag fields as select drop-down or not + * @param array $showOnlyTheseFields Limit the extra fields shown to just the list given here + * @param array $orderFields An array containing the names of the fields shown, in the right order + * @param array $extraData + * @param bool $orderDependingDefaults + * @param bool $adminPermissions + * @param array $separateExtraMultipleSelect + * @param array $customLabelsExtraMultipleSelect + * @param bool $addEmptyOptionSelects + * @param array $introductionTextList + * @param array $requiredFields + * @param bool $hideGeoLocalizationDetails + * + * @throws Exception + * + * @return array|bool If relevant, returns a one-element array with JS code to be added to the page HTML headers. + * Returns false if the form object was not given */ - public static function extra_field_double_select_convert_array_to_string($options) - { - $string = null; - $options_parsed = self::extra_field_double_select_convert_array_to_ordered_array($options); + public function addElements( + $form, + $itemId = 0, + $exclude = [], + $filter = false, + $useTagAsSelect = false, + $showOnlyTheseFields = [], + $orderFields = [], + $extraData = [], + $orderDependingDefaults = false, + $adminPermissions = false, + $separateExtraMultipleSelect = [], + $customLabelsExtraMultipleSelect = [], + $addEmptyOptionSelects = false, + $introductionTextList = [], + $requiredFields = [], + $hideGeoLocalizationDetails = false, + $help = false + ) { + if (empty($form)) { + return false; + } - if (!empty($options_parsed)) { - foreach ($options_parsed as $option) { - foreach ($option as $key => $item) { - $string .= $item['display_text']; - if (0 == $key) { - $string .= ':'; - } else { - if (isset($option[$key + 1])) { - $string .= ';'; + $itemId = (int) $itemId; + $form->addHidden('item_id', $itemId); + $extraData = false; + if (!empty($itemId)) { + $extraData = $this->get_handler_extra_data($itemId); + if (!empty($showOnlyTheseFields)) { + $setData = []; + foreach ($showOnlyTheseFields as $variable) { + $extraName = 'extra_'.$variable; + if (in_array($extraName, array_keys($extraData))) { + $setData[$extraName] = $extraData[$extraName]; } } - } - $string .= '|'; + $form->setDefaults($setData); + } else { + $form->setDefaults($extraData); } } - if (!empty($string)) { - $string = substr($string, 0, strlen($string) - 1); - } - - return $string; - } - - /** - * @param array $options The result of the get_field_options_by_field() array - * - * @return string - */ - public static function extraFieldSelectWithTextConvertArrayToString(array $options) - { - $string = ''; - $parsedOptions = self::extra_field_double_select_convert_array_to_ordered_array($options); - - if (empty($parsedOptions)) { - return ''; - } - - foreach ($parsedOptions as $options) { - $option = current($options); - - $string .= $option['display_text']; - $string .= '|'; + $conditions = []; + if ($filter) { + $conditions = ['filter = ?' => 1]; } - return rtrim($string, '|'); - } - - /** - * @return string - */ - public static function tripleSelectConvertArrayToString(array $options) - { - $string = ''; - $parsedOptions = self::tripleSelectConvertArrayToOrderedArray($options); - - foreach ($parsedOptions['level1'] as $item1) { - $string .= $item1['display_text']; - $level2 = self::getOptionsFromTripleSelect($parsedOptions['level2'], $item1['id']); - - foreach ($level2 as $item2) { - $string .= '\\'.$item2['display_text'].':'; - $level3 = self::getOptionsFromTripleSelect($parsedOptions['level3'], $item2['id']); + $extraFields = $this->get_all($conditions, 'option_order'); + $extra = $this->set_extra_fields_in_form( + $form, + $extraData, + $adminPermissions, + $extraFields, + $itemId, + $exclude, + $useTagAsSelect, + $showOnlyTheseFields, + $orderFields, + $orderDependingDefaults, + $separateExtraMultipleSelect, + $customLabelsExtraMultipleSelect, + $addEmptyOptionSelects, + $introductionTextList, + $hideGeoLocalizationDetails, + $help + ); - $string .= implode(';', array_column($level3, 'display_text')); + if (!empty($requiredFields)) { + /** @var HTML_QuickForm_input $element */ + foreach ($form->getElements() as $element) { + $name = str_replace('extra_', '', $element->getName()); + if (in_array($name, $requiredFields)) { + $form->setRequired($element); + } } - - $string .= '|'; } - return trim($string, '\\|;'); + return $extra; } /** - * @param array $params + * Return an array of all the extra fields available for this item. + * + * @param int $itemId (session_id, question_id, course id) * * @return array */ - public function clean_parameters($params) + public function get_handler_extra_data($itemId) { - if (!isset($params['variable']) || empty($params['variable'])) { - $params['variable'] = $params['display_text']; + if (empty($itemId)) { + return []; } - $params['variable'] = trim(strtolower(str_replace(" ", "_", $params['variable']))); + $extra_data = []; + $fields = $this->get_all(); + $field_values = new ExtraFieldValue($this->type); - if (!isset($params['field_order'])) { - $max_order = self::get_max_field_order(); - $params['field_order'] = $max_order; - } else { - $params['field_order'] = (int) $params['field_order']; - } + if (!empty($fields)) { + foreach ($fields as $field) { + $field_value = $field_values->get_values_by_handler_and_field_id( + $itemId, + $field['id'] + ); - return $params; - } + if (self::FIELD_TYPE_TAG == $field['field_type']) { + $tags = UserManager::get_user_tags_to_string( + $itemId, + $field['id'], + false + ); + $extra_data['extra_'.$field['variable']] = $tags; - /** - * @param array $params - * @param bool $show_query - * - * @return int|bool - */ - public function save($params, $show_query = false) - { - $fieldInfo = self::get_handler_field_info_by_field_variable($params['variable']); - $params = $this->clean_parameters($params); - $params['extra_field_type'] = $this->extraFieldType; + continue; + } - if ($fieldInfo) { - return $fieldInfo['id']; - } else { - $id = parent::save($params, $show_query); - if ($id) { - $fieldOption = new ExtraFieldOption($this->type); - $params['field_id'] = $id; - $fieldOption->save($params); - } + if ($field_value) { + $variable = $field['variable']; + $field_value = $field_value['value']; + switch ($field['field_type']) { + case self::FIELD_TYPE_TAG: + $tags = UserManager::get_user_tags_to_string( + $itemId, + $field['id'], + false + ); - return $id; - } - } + $extra_data['extra_'.$field['variable']] = $tags; + break; + case self::FIELD_TYPE_DOUBLE_SELECT: + case self::FIELD_TYPE_SELECT_WITH_TEXT_FIELD: + $selected_options = explode('::', $field_value); + $firstOption = isset($selected_options[0]) ? $selected_options[0] : ''; + $secondOption = isset($selected_options[1]) ? $selected_options[1] : ''; + $extra_data['extra_'.$field['variable']]['extra_'.$field['variable']] = $firstOption; + $extra_data['extra_'.$field['variable']]['extra_'.$field['variable'].'_second'] = $secondOption; - /** - * {@inheritdoc} - */ - public function update($params, $showQuery = false) - { - $params = $this->clean_parameters($params); - if (isset($params['id'])) { - $fieldOption = new ExtraFieldOption($this->type); - $params['field_id'] = $params['id']; - if (empty($params['field_type'])) { - $params['field_type'] = $this->type; + break; + case self::FIELD_TYPE_SELECT_MULTIPLE: + $field_value = explode(';', $field_value); + $extra_data['extra_'.$field['variable']] = $field_value; + break; + case self::FIELD_TYPE_RADIO: + $extra_data['extra_'.$field['variable']]['extra_'.$field['variable']] = $field_value; + break; + case self::FIELD_TYPE_TRIPLE_SELECT: + list($level1, $level2, $level3) = explode(';', $field_value); + + $extra_data["extra_$variable"]["extra_$variable"] = $level1; + $extra_data["extra_$variable"]["extra_{$variable}_second"] = $level2; + $extra_data["extra_$variable"]["extra_{$variable}_third"] = $level3; + break; + default: + $extra_data['extra_'.$field['variable']] = $field_value; + break; + } + } else { + // Set default values + if (isset($field['field_default_value']) && + !empty($field['field_default_value']) + ) { + $extra_data['extra_'.$field['variable']] = $field['field_default_value']; + } + } } - $fieldOption->save($params, $showQuery); } - return parent::update($params, $showQuery); + return $extra_data; } /** - * @param $id + * Get an array of all the values from the extra_field and extra_field_options tables + * based on the current object's type. * - * @return bool + * @param array $conditions + * @param null $order_field_options_by + * + * @return array */ - public function delete($id) + public function get_all($conditions = [], $order_field_options_by = null) { - $em = Database::getManager(); - $items = $em->getRepository('ChamiloCoreBundle:ExtraFieldSavedSearch')->findBy(['field' => $id]); - if ($items) { - foreach ($items as $item) { - $em->remove($item); - } - $em->flush(); + $conditions = Database::parse_conditions(['where' => $conditions]); + + if (empty($conditions)) { + $conditions .= ' WHERE extra_field_type = '.$this->extraFieldType; + } else { + $conditions .= ' AND extra_field_type = '.$this->extraFieldType; } - $field_option = new ExtraFieldOption($this->type); - $field_option->delete_all_options_by_field_id($id); - $session_field_values = new ExtraFieldValue($this->type); - $session_field_values->delete_all_values_by_field_id($id); + $sql = "SELECT * FROM $this->table + $conditions + ORDER BY field_order ASC + "; + + $result = Database::query($sql); + $extraFields = Database::store_result($result, 'ASSOC'); + + $option = new ExtraFieldOption($this->type); + if (!empty($extraFields)) { + foreach ($extraFields as &$extraField) { + $extraField['display_text'] = $this->translateDisplayName( + $extraField['variable'], + $extraField['display_text'] + ); + $extraField['options'] = $option->get_field_options_by_field( + $extraField['id'], + false, + $order_field_options_by + ); + } + } - return parent::delete($id); + return $extraFields; } /** @@ -1011,7 +941,8 @@ class ExtraField extends Model * * @param FormValidator $form The form these fields are to be attached to * @param array $extraData - * @param bool $adminPermissions Whether the display is considered without edition limits (true) or not (false) + * @param bool $adminPermissions Whether the display is considered without edition limits (true) or not + * (false) * @param array $extra * @param int $itemId The item (course, user, session, etc) this extra_field is attached to * @param array $exclude Extra fields to be skipped, by textual ID @@ -1312,7 +1243,6 @@ class ExtraField extends Model } $selectedOptions = []; - if ($separateValue > 0) { $em = Database::getManager(); $fieldTags = $em @@ -1524,7 +1454,7 @@ class ExtraField extends Model $leftpad = '1.7'; $top = '0.4'; $domain = parse_url($icon_path, PHP_URL_HOST); - if ('www.hi5.com' == $domain or 'hi5.com' == $domain) { + if ('www.hi5.com' === $domain || 'hi5.com' === $domain) { $leftpad = '3'; $top = '0'; } @@ -1661,7 +1591,8 @@ class ExtraField extends Model $url .= '&a=delete_file&field_id='.$field_details['id'].'&item_id='.$itemId; $deleteId = $field_details['variable'].'_delete'; - $form->addHtml(" + $form->addHtml( + " - "); + " + ); $linkToDelete = ' '.Display::url( Display::return_icon('delete.png', get_lang('Delete')), @@ -1752,78 +1684,343 @@ class ExtraField extends Model ); $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes'); - if ($freezeElement) { - $form->freeze('extra_'.$field_details['variable']); - } - break; - case self::FIELD_TYPE_ALPHANUMERIC_SPACE: - $form->addTextAlphanumericAndSpaces( - "extra_{$field_details['variable']}", - $field_details['display_text'] - ); - $form->applyFilter( - 'extra_'.$field_details['variable'], - 'stripslashes' - ); - if ($freezeElement) { - $form->freeze('extra_'.$field_details['variable']); - } - break; - case self::FIELD_TYPE_GEOLOCALIZATION_COORDINATES: - case self::FIELD_TYPE_GEOLOCALIZATION: - $dataValue = isset($extraData['extra_'.$field_details['variable']]) - ? $extraData['extra_'.$field_details['variable']] - : ''; + if ($freezeElement) { + $form->freeze('extra_'.$field_details['variable']); + } + break; + case self::FIELD_TYPE_ALPHANUMERIC_SPACE: + $form->addTextAlphanumericAndSpaces( + "extra_{$field_details['variable']}", + $field_details['display_text'] + ); + $form->applyFilter( + 'extra_'.$field_details['variable'], + 'stripslashes' + ); + if ($freezeElement) { + $form->freeze('extra_'.$field_details['variable']); + } + break; + case self::FIELD_TYPE_GEOLOCALIZATION_COORDINATES: + case self::FIELD_TYPE_GEOLOCALIZATION: + $dataValue = isset($extraData['extra_'.$field_details['variable']]) + ? $extraData['extra_'.$field_details['variable']] + : ''; + + $form->addGeoLocationMapField( + 'extra_'.$field_details['variable'], + $field_details['display_text'], + $dataValue, + $hideGeoLocalizationDetails + ); + + if ($freezeElement) { + $form->freeze('extra_'.$field_details['variable']); + } + break; + case self::FIELD_TYPE_SELECT_WITH_TEXT_FIELD: + $jquery_ready_content .= $this->addSelectWithTextFieldElement( + $form, + $field_details, + $freezeElement + ); + break; + case self::FIELD_TYPE_TRIPLE_SELECT: + $jquery_ready_content .= $this->addTripleSelectElement( + $form, + $field_details, + is_array($extraData) ? $extraData : [], + $freezeElement + ); + break; + } + } + } + + $return = []; + $return['jquery_ready_content'] = $jquery_ready_content; + + return $return; + } + + /** + * @param array $options + * + * @return array + */ + public static function extra_field_double_select_convert_array_to_ordered_array($options) + { + $optionsParsed = []; + if (!empty($options)) { + foreach ($options as $option) { + if (0 == $option['option_value']) { + $optionsParsed[$option['id']][] = $option; + } else { + $optionsParsed[$option['option_value']][] = $option; + } + } + } + + return $optionsParsed; + } + + /** + * @return array + */ + public static function tripleSelectConvertArrayToOrderedArray(array $options) + { + $level1 = self::getOptionsFromTripleSelect($options, 0); + $level2 = []; + $level3 = []; + + foreach ($level1 as $item1) { + $level2 += self::getOptionsFromTripleSelect($options, $item1['id']); + } + + foreach ($level2 as $item2) { + $level3 += self::getOptionsFromTripleSelect($options, $item2['id']); + } + + return ['level1' => $level1, 'level2' => $level2, 'level3' => $level3]; + } + + /** + * @param string $type + * + * @return array + */ + public function get_all_extra_field_by_type($type) + { + // all the information of the field + $sql = "SELECT * FROM {$this->table} + WHERE + field_type = '".Database::escape_string($type)."' AND + extra_field_type = $this->extraFieldType + "; + $result = Database::query($sql); + + $return = []; + while ($row = Database::fetch_array($result)) { + $return[] = $row['id']; + } + + return $return; + } + + /** + * @param int $id + */ + public function get_field_type_by_id($id) + { + $types = $this->get_field_types(); + if (isset($types[$id])) { + return $types[$id]; + } + + return null; + } + + /** + * @return array + */ + public function get_field_types() + { + return $this->get_extra_fields_by_handler($this->type); + } + + /** + * @param string $handler + * + * @return array + */ + public static function get_extra_fields_by_handler($handler) + { + $types = []; + $types[self::FIELD_TYPE_TEXT] = get_lang('FieldTypeText'); + $types[self::FIELD_TYPE_TEXTAREA] = get_lang('FieldTypeTextarea'); + $types[self::FIELD_TYPE_RADIO] = get_lang('FieldTypeRadio'); + $types[self::FIELD_TYPE_SELECT] = get_lang('FieldTypeSelect'); + $types[self::FIELD_TYPE_SELECT_MULTIPLE] = get_lang('FieldTypeSelectMultiple'); + $types[self::FIELD_TYPE_DATE] = get_lang('FieldTypeDate'); + $types[self::FIELD_TYPE_DATETIME] = get_lang('FieldTypeDatetime'); + $types[self::FIELD_TYPE_DOUBLE_SELECT] = get_lang('FieldTypeDoubleSelect'); + $types[self::FIELD_TYPE_DIVIDER] = get_lang('FieldTypeDivider'); + $types[self::FIELD_TYPE_TAG] = get_lang('FieldTypeTag'); + $types[self::FIELD_TYPE_TIMEZONE] = get_lang('FieldTypeTimezone'); + $types[self::FIELD_TYPE_SOCIAL_PROFILE] = get_lang('FieldTypeSocialProfile'); + $types[self::FIELD_TYPE_MOBILE_PHONE_NUMBER] = get_lang('FieldTypeMobilePhoneNumber'); + $types[self::FIELD_TYPE_CHECKBOX] = get_lang('FieldTypeCheckbox'); + $types[self::FIELD_TYPE_INTEGER] = get_lang('FieldTypeInteger'); + $types[self::FIELD_TYPE_FILE_IMAGE] = get_lang('FieldTypeFileImage'); + $types[self::FIELD_TYPE_FLOAT] = get_lang('FieldTypeFloat'); + $types[self::FIELD_TYPE_FILE] = get_lang('FieldTypeFile'); + $types[self::FIELD_TYPE_VIDEO_URL] = get_lang('FieldTypeVideoUrl'); + $types[self::FIELD_TYPE_LETTERS_ONLY] = get_lang('FieldTypeOnlyLetters'); + $types[self::FIELD_TYPE_ALPHANUMERIC] = get_lang('FieldTypeAlphanumeric'); + $types[self::FIELD_TYPE_LETTERS_SPACE] = get_lang('FieldTypeLettersSpaces'); + $types[self::FIELD_TYPE_ALPHANUMERIC_SPACE] = get_lang('FieldTypeAlphanumericSpaces'); + $types[self::FIELD_TYPE_GEOLOCALIZATION] = get_lang('Geolocalization'); + $types[self::FIELD_TYPE_GEOLOCALIZATION_COORDINATES] = get_lang('GeolocalizationCoordinates'); + $types[self::FIELD_TYPE_SELECT_WITH_TEXT_FIELD] = get_lang('FieldTypeSelectWithTextField'); + $types[self::FIELD_TYPE_TRIPLE_SELECT] = get_lang('FieldTypeTripleSelect'); + + switch ($handler) { + case 'course': + case 'session': + case 'user': + case 'skill': + break; + } + + return $types; + } + + /** + * @param array $params + * @param bool $show_query + * + * @return int|bool + */ + public function save($params, $show_query = false) + { + $fieldInfo = self::get_handler_field_info_by_field_variable($params['variable']); + $params = $this->clean_parameters($params); + $params['extra_field_type'] = $this->extraFieldType; + + if ($fieldInfo) { + return $fieldInfo['id']; + } else { + $id = parent::save($params, $show_query); + if ($id) { + $fieldOption = new ExtraFieldOption($this->type); + $params['field_id'] = $id; + $fieldOption->save($params); + } + + return $id; + } + } + + /** + * @param string $variable + * + * @return array|bool + */ + public function get_handler_field_info_by_field_variable($variable) + { + $variable = Database::escape_string($variable); + $sql = "SELECT * FROM {$this->table} + WHERE + variable = '$variable' AND + extra_field_type = $this->extraFieldType"; + $result = Database::query($sql); + if (Database::num_rows($result)) { + $row = Database::fetch_array($result, 'ASSOC'); + if ($row) { + $row['display_text'] = $this->translateDisplayName( + $row['variable'], + $row['display_text'] + ); + + // All the options of the field + $sql = "SELECT * FROM $this->table_field_options + WHERE field_id='".intval($row['id'])."' + ORDER BY option_order ASC"; + $result = Database::query($sql); + while ($option = Database::fetch_array($result)) { + $row['options'][$option['id']] = $option; + } + + return $row; + } + } + + return false; + } + + /** + * @param array $params + * + * @return array + */ + public function clean_parameters($params) + { + if (!isset($params['variable']) || empty($params['variable'])) { + $params['variable'] = $params['display_text']; + } + + $params['variable'] = trim(strtolower(str_replace(' ', '_', $params['variable']))); + + if (!isset($params['field_order'])) { + $max_order = self::get_max_field_order(); + $params['field_order'] = $max_order; + } else { + $params['field_order'] = (int) $params['field_order']; + } + + return $params; + } + + /** + * @return int + */ + public function get_max_field_order() + { + $sql = "SELECT MAX(field_order) + FROM {$this->table} + WHERE + extra_field_type = '.$this->extraFieldType.'"; + $res = Database::query($sql); + + $order = 0; + if (Database::num_rows($res) > 0) { + $row = Database::fetch_row($res); + $order = $row[0] + 1; + } - $form->addGeoLocationMapField( - 'extra_'.$field_details['variable'], - $field_details['display_text'], - $dataValue, - $hideGeoLocalizationDetails - ); + return $order; + } - /*$form->addElement( - 'text', - 'extra_'.$field_details['variable'], - $field_details['display_text'], - ['id' => 'extra_'.$field_details['variable']] - ); - $form->addHidden( - 'extra_'.$field_details['variable'].'_coordinates', - '', - ['id' => 'extra_'.$field_details['variable'].'_coordinates'] - ); + /** + * {@inheritdoc} + */ + public function update($params, $showQuery = false) + { + $params = $this->clean_parameters($params); + if (isset($params['id'])) { + $fieldOption = new ExtraFieldOption($this->type); + $params['field_id'] = $params['id']; + if (empty($params['field_type'])) { + $params['field_type'] = $this->type; + } + $fieldOption->save($params, $showQuery); + } - $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes'); - $form->applyFilter('extra_'.$field_details['variable'], 'trim');*/ + return parent::update($params, $showQuery); + } - if ($freezeElement) { - $form->freeze('extra_'.$field_details['variable']); - } - break; - case self::FIELD_TYPE_SELECT_WITH_TEXT_FIELD: - $jquery_ready_content .= $this->addSelectWithTextFieldElement( - $form, - $field_details, - $freezeElement - ); - break; - case self::FIELD_TYPE_TRIPLE_SELECT: - $jquery_ready_content .= $this->addTripleSelectElement( - $form, - $field_details, - is_array($extraData) ? $extraData : [], - $freezeElement - ); - break; - } + /** + * @param $id + * + * @return bool + */ + public function delete($id) + { + $em = Database::getManager(); + $items = $em->getRepository('ChamiloCoreBundle:ExtraFieldSavedSearch')->findBy(['field' => $id]); + if ($items) { + foreach ($items as $item) { + $em->remove($item); } + $em->flush(); } + $field_option = new ExtraFieldOption($this->type); + $field_option->delete_all_options_by_field_id($id); - $return = []; - $return['jquery_ready_content'] = $jquery_ready_content; + $session_field_values = new ExtraFieldValue($this->type); + $session_field_values->delete_all_values_by_field_id($id); - return $return; + return parent::delete($id); } /** @@ -1832,10 +2029,10 @@ class ExtraField extends Model */ public function setupBreadcrumb(&$breadcrumb, $action) { - if ('add' == $action) { + if ('add' === $action) { $breadcrumb[] = ['url' => $this->pageUrl, 'name' => $this->pageName]; $breadcrumb[] = ['url' => '#', 'name' => get_lang('Add')]; - } elseif ('edit' == $action) { + } elseif ('edit' === $action) { $breadcrumb[] = ['url' => $this->pageUrl, 'name' => $this->pageName]; $breadcrumb[] = ['url' => '#', 'name' => get_lang('Edit')]; } else { @@ -2112,6 +2309,25 @@ class ExtraField extends Model return $form; } + /** + * Gets an element. + * + * @param int $id + * @param bool $translateDisplayText Optional + * + * @return array + */ + public function get($id, $translateDisplayText = true) + { + $info = parent::get($id); + + if ($translateDisplayText) { + $info['display_text'] = self::translateDisplayName($info['variable'], $info['display_text']); + } + + return $info; + } + /** * @param $token * @@ -2215,247 +2431,130 @@ JAVASCRIPT; 'op' => 'cn', ]; - // Second - $search_options['value'] = $field['id'].':'; - $search_options['dataInit'] = 'register_second_select'; - - $column_model[] = [ - 'name' => 'extra_'.$field['variable'].'_second', - 'index' => 'extra_'.$field['variable'].'_second', - 'width' => '100', - 'hidden' => 'true', - 'search' => 'true', - 'stype' => 'select', - 'searchoptions' => $search_options, - ]; - $columns[] = $field['display_text'].' (2)'; - $rules[] = ['field' => 'extra_'.$field['variable'].'_second', 'op' => 'cn']; - continue; - } else { - $search_options['value'] = $extraFieldOption->getFieldOptionsToString( - $field['id'], - false, - 'display_text' - ); - } - $column_model[] = [ - 'name' => 'extra_'.$field['variable'], - 'index' => 'extra_'.$field['variable'], - 'width' => '100', - 'hidden' => 'true', - 'search' => 'true', - 'stype' => $type, - 'searchoptions' => $search_options, - ]; - $columns[] = $field['display_text']; - $rules[] = [ - 'field' => 'extra_'.$field['variable'], - 'op' => 'cn', - 'data' => '', - ]; - } - } - - return $rules; - } - - /** - * @param array $options - * - * @return array - */ - public function parseConditions($options) - { - $inject_extra_fields = null; - $extraFieldOption = new ExtraFieldOption($this->type); - $double_fields = []; - - if (isset($options['extra'])) { - $extra_fields = $options['extra']; - if (!empty($extra_fields)) { - $counter = 1; - foreach ($extra_fields as &$extra) { - $extra_field_obj = new ExtraField($this->type); - $extra_field_info = $extra_field_obj->get($extra['id']); - $extra['extra_field_info'] = $extra_field_info; - - if (isset($extra_field_info['field_type']) && - in_array( - $extra_field_info['field_type'], - [ - self::FIELD_TYPE_SELECT, - self::FIELD_TYPE_SELECT, - self::FIELD_TYPE_DOUBLE_SELECT, - ] - ) - ) { - $inject_extra_fields .= " fvo$counter.display_text as {$extra['field']}, "; - } else { - $inject_extra_fields .= " fv$counter.value as {$extra['field']}, "; - } - - if (isset($extra_fields_info[$extra['id']])) { - $info = $extra_fields_info[$extra['id']]; - } else { - $info = $this->get($extra['id']); - $extra_fields_info[$extra['id']] = $info; - } - if (isset($info['field_type']) && self::FIELD_TYPE_DOUBLE_SELECT == $info['field_type']) { - $double_fields[$info['id']] = $info; - } - $counter++; - } - } - } - - $options_by_double = []; - foreach ($double_fields as $double) { - $my_options = $extraFieldOption->get_field_options_by_field( - $double['id'], - true - ); - $options_by_double['extra_'.$double['variable']] = $my_options; - } - - $field_value_to_join = []; - //filter can be all/any = and/or - $inject_joins = null; - $inject_where = null; - $where = null; - - if (!empty($options['where'])) { - if (!empty($options['extra'])) { - // Removing double 1=1 - $options['where'] = str_replace(' 1 = 1 AND', '', $options['where']); - // Always OR - $counter = 1; - foreach ($extra_fields as $extra_info) { - $extra_field_info = $extra_info['extra_field_info']; - $inject_joins .= " INNER JOIN $this->table_field_values fv$counter - ON (s.".$this->primaryKey." = fv$counter.".$this->handler_id.") "; - // Add options - if (isset($extra_field_info['field_type']) && - in_array( - $extra_field_info['field_type'], - [ - self::FIELD_TYPE_SELECT, - self::FIELD_TYPE_SELECT, - self::FIELD_TYPE_DOUBLE_SELECT, - ] - ) - ) { - $options['where'] = str_replace( - $extra_info['field'], - 'fv'.$counter.'.field_id = '.$extra_info['id'].' AND fvo'.$counter.'.option_value', - $options['where'] - ); - $inject_joins .= " - INNER JOIN $this->table_field_options fvo$counter - ON ( - fv$counter.field_id = fvo$counter.field_id AND - fv$counter.value = fvo$counter.option_value - ) - "; - } else { - if (isset($extra_field_info['field_type']) && - self::FIELD_TYPE_TAG == $extra_field_info['field_type'] - ) { - $options['where'] = str_replace( - $extra_info['field'], - 'tag'.$counter.'.tag ', - $options['where'] - ); - - $inject_joins .= " - INNER JOIN $this->table_field_rel_tag tag_rel$counter - ON ( - tag_rel$counter.field_id = ".$extra_info['id']." AND - tag_rel$counter.item_id = s.".$this->primaryKey." - ) - INNER JOIN $this->table_field_tag tag$counter - ON (tag$counter.id = tag_rel$counter.tag_id) - "; - } else { - //text, textarea, etc - $options['where'] = str_replace( - $extra_info['field'], - 'fv'.$counter.'.field_id = '.$extra_info['id'].' AND fv'.$counter.'.value', - $options['where'] - ); - } - } - - $field_value_to_join[] = " fv$counter.$this->handler_id "; - $counter++; - } - if (!empty($field_value_to_join)) { - //$inject_where .= " AND s.id = ".implode(' = ', $field_value_to_join); + // Second + $search_options['value'] = $field['id'].':'; + $search_options['dataInit'] = 'register_second_select'; + + $column_model[] = [ + 'name' => 'extra_'.$field['variable'].'_second', + 'index' => 'extra_'.$field['variable'].'_second', + 'width' => '100', + 'hidden' => 'true', + 'search' => 'true', + 'stype' => 'select', + 'searchoptions' => $search_options, + ]; + $columns[] = $field['display_text'].' (2)'; + $rules[] = ['field' => 'extra_'.$field['variable'].'_second', 'op' => 'cn']; + continue; + } else { + $search_options['value'] = $extraFieldOption->getFieldOptionsToString( + $field['id'], + false, + 'display_text' + ); } + $column_model[] = [ + 'name' => 'extra_'.$field['variable'], + 'index' => 'extra_'.$field['variable'], + 'width' => '100', + 'hidden' => 'true', + 'search' => 'true', + 'stype' => $type, + 'searchoptions' => $search_options, + ]; + $columns[] = $field['display_text']; + $rules[] = [ + 'field' => 'extra_'.$field['variable'], + 'op' => 'cn', + 'data' => '', + ]; } - $where .= ' AND '.$options['where']; - } - - $order = null; - if (!empty($options['order'])) { - $order = " ORDER BY ".$options['order']; - } - $limit = null; - if (!empty($options['limit'])) { - $limit = " LIMIT ".$options['limit']; } - return [ - 'order' => $order, - 'limit' => $limit, - 'where' => $where, - 'inject_where' => $inject_where, - 'inject_joins' => $inject_joins, - 'field_value_to_join' => $field_value_to_join, - 'inject_extra_fields' => $inject_extra_fields, - ]; + return $rules; } - //@todo move this in the display_class or somewhere else - - /** - * @param $col - * @param $oper - * @param $val - * - * @return string - */ - public function get_where_clause($col, $oper, $val) + public function processExtraFieldSearch($values, $form, $alias, $condition = 'OR') { - if (empty($col)) { - return ''; - } - if ('bw' == $oper || 'bn' == $oper) { - $val .= '%'; - } - if ('ew' == $oper || 'en' == $oper) { - $val = '%'.$val; + // Parse params. + $fields = []; + foreach ($values as $key => $value) { + if (substr($key, 0, 6) !== 'extra_' && substr($key, 0, 7) !== '_extra_') { + continue; + } + if (!empty($value)) { + $fields[$key] = $value; + } } - if ('cn' == $oper || 'nc' == $oper || 'in' == $oper || 'ni' == $oper) { - if (is_array($val)) { - $result = '"%'.implode(';', $val).'%"'; - foreach ($val as $item) { - $item = trim($item); - $result .= ' OR '.$col.' LIKE "%'.$item.'%"'; - } - $val = $result; - return " $col {$this->ops[$oper]} $val "; - } else { - if (is_string($val)) { - $val = '%'.$val.'%'; + $extraFieldsAll = $this->get_all( + ['visible_to_self = ? AND filter = ?' => [1, 1]], + 'option_order' + ); + $extraFieldsType = array_column($extraFieldsAll, 'field_type', 'variable'); + $extraFields = array_column($extraFieldsAll, 'variable'); + $filter = new stdClass(); + $defaults = []; + foreach ($fields as $variable => $col) { + $variableNoExtra = str_replace('extra_', '', $variable); + if (isset($values[$variable]) && !empty($values[$variable]) && + in_array($variableNoExtra, $extraFields) + ) { + $rule = new stdClass(); + $rule->field = $variable; + $rule->op = 'in'; + $data = $col; + if (is_array($data) && array_key_exists($variable, $data)) { + $data = $col; + } + $rule->data = $data; + $filter->rules[] = $rule; + $filter->groupOp = 'AND'; + + if ($extraFieldsType[$variableNoExtra] == ExtraField::FIELD_TYPE_TAG) { + $tagElement = $form->getElement($variable); + $tags = []; + foreach ($values[$variable] as $tag) { + $tag = Security::remove_XSS($tag); + $tags[] = $tag; + $tagElement->addOption( + $tag, + $tag + ); + } + $defaults[$variable] = $tags; } else { - $val = ''; + if (is_array($data)) { + $defaults[$variable] = array_map(['Security', 'remove_XSS'], $data); + } else { + $defaults[$variable] = Security::remove_XSS($data); + } } } } - $val = \Database::escape_string($val); - return " $col {$this->ops[$oper]} '$val' "; + $result = $this->getExtraFieldRules($filter, 'extra_', $condition); + + $conditionArray = $result['condition_array']; + + $whereCondition = ''; + $extraCondition = ''; + if (!empty($conditionArray)) { + $extraCondition = ' ( '; + $extraCondition .= implode(' AND ', $conditionArray); + $extraCondition .= ' ) '; + } + $whereCondition .= $extraCondition; + $conditions = $this->parseConditions( + [ + 'where' => $whereCondition, + 'extra' => $result['extra_fields'], + ], + $alias + ); + + return ['condition' => $conditions, 'fields' => $fields, 'defaults' => $defaults]; } /** @@ -2464,12 +2563,18 @@ JAVASCRIPT; * * @return array */ - public function getExtraFieldRules($filters, $stringToSearch = 'extra_') + public function getExtraFieldRules($filters, $stringToSearch = 'extra_', $condition = 'OR') { $extra_fields = []; + $condition_array = []; // Getting double select if exists $double_select = []; + if (is_object($filters) && + property_exists($filters, 'rules') && + is_array($filters->rules) && + !empty($filters->rules) + ) { foreach ($filters->rules as $rule) { if (empty($rule)) { continue; @@ -2481,7 +2586,6 @@ JAVASCRIPT; } } - $condition_array = []; foreach ($filters->rules as $rule) { if (empty($rule)) { continue; @@ -2522,9 +2626,12 @@ JAVASCRIPT; if (isset($rule->data) && is_int($rule->data) && -1 == $rule->data) { continue; } - $condition_array[] = ' (' - .$this->get_where_clause($rule->field, $rule->op, $rule->data) - .') '; + /*var_dump($rule->data); + foreach ($rule->data as $option) { + }*/ + $where = $this->get_where_clause($rule->field, $rule->op, $rule->data, 'OR'); + $condition_array[] = " ( $where ) "; + $extra_fields[] = [ 'field' => $rule->field, 'id' => $field_option['id'], @@ -2543,6 +2650,14 @@ JAVASCRIPT; } } } + } + + /*var_dump( + [ + 'extra_fields' => $extra_fields, + 'condition_array' => $condition_array, + ] + );*/ return [ 'extra_fields' => $extra_fields, @@ -2550,61 +2665,270 @@ JAVASCRIPT; ]; } + /** + * @param $col + * @param $oper + * @param $val + * @param $conditionBetweenOptions + * + * @return string + */ + public function get_where_clause($col, $oper, $val, $conditionBetweenOptions = 'OR') + { + if (empty($col)) { + return ''; + } + $conditionBetweenOptions = in_array($conditionBetweenOptions, ['OR', 'AND']) ? $conditionBetweenOptions : 'OR'; + if ('bw' === $oper || 'bn' === $oper) { + $val .= '%'; + } + if ('ew' === $oper || 'en' === $oper) { + $val = '%'.$val; + } + if ('cn' === $oper || 'nc' === $oper || 'in' === $oper || 'ni' === $oper) { + if (is_array($val)) { + $result = '"%'.implode(';', $val).'%"'; + foreach ($val as $item) { + $item = trim($item); + $result .= ' '.$conditionBetweenOptions.' '.$col.' LIKE "%'.$item.'%"'; + } + $val = $result; + + return " $col {$this->ops[$oper]} $val "; + } else { + if (is_string($val)) { + $val = '%'.$val.'%'; + } else { + $val = ''; + } + } + } + $val = \Database::escape_string($val); + + return " $col {$this->ops[$oper]} '$val' "; + } + + /** + * @param array $options + * @param string $alias + * + * @return array + */ + public function parseConditions($options, $alias = 's') + { + $inject_extra_fields = null; + $extraFieldOption = new ExtraFieldOption($this->type); + $double_fields = []; + + if (isset($options['extra'])) { + $extra_fields = $options['extra']; + if (!empty($extra_fields)) { + $counter = 1; + $extra_field_obj = new ExtraField($this->type); + foreach ($extra_fields as &$extra) { + if (!isset($extra['id'])) { + continue; + } + $extra_field_info = $extra_field_obj->get($extra['id']); + if (empty($extra_field_info)) { + continue; + } + $extra['extra_field_info'] = $extra_field_info; + + switch ($extra_field_info['field_type']) { + case self::FIELD_TYPE_SELECT: + case self::FIELD_TYPE_DOUBLE_SELECT: + $inject_extra_fields .= " fvo$counter.display_text as {$extra['field']}, "; + break; + case self::FIELD_TYPE_TAG: + // If using OR + //$inject_extra_fields .= " tag$counter.tag as {$extra['field']}, "; + // If using AND + $newCounter = 1; + $fields = []; + $tagAlias = $extra['field']; + foreach ($extra['data'] as $data) { + $fields[] = "tag$counter$newCounter.tag"; + $newCounter++; + } + $tags = implode(' , " ", ', $fields); + $inject_extra_fields .= " CONCAT($tags) as $tagAlias, "; + break; + default: + $inject_extra_fields .= " fv$counter.value as {$extra['field']}, "; + break; + } + + if (isset($extra_fields_info[$extra['id']])) { + $info = $extra_fields_info[$extra['id']]; + } else { + $info = $this->get($extra['id']); + $extra_fields_info[$extra['id']] = $info; + } + if (isset($info['field_type']) && self::FIELD_TYPE_DOUBLE_SELECT == $info['field_type']) { + $double_fields[$info['id']] = $info; + } + $counter++; + } + } + } + + $options_by_double = []; + foreach ($double_fields as $double) { + $my_options = $extraFieldOption->get_field_options_by_field($double['id'], true); + $options_by_double['extra_'.$double['variable']] = $my_options; + } + + $field_value_to_join = []; + //filter can be all/any = and/or + $inject_joins = null; + $inject_where = null; + $where = null; + + if (!empty($options['where'])) { + if (!empty($options['extra'])) { + // Removing double 1=1 + $options['where'] = str_replace(' 1 = 1 AND', '', $options['where']); + // Always OR + $counter = 1; + foreach ($extra_fields as $extra_info) { + $extra_field_info = $extra_info['extra_field_info']; + $inject_joins .= " INNER JOIN $this->table_field_values fv$counter + ON ($alias.".$this->primaryKey." = fv$counter.".$this->handler_id.') '; + // Add options + switch ($extra_field_info['field_type']) { + case self::FIELD_TYPE_SELECT: + case self::FIELD_TYPE_DOUBLE_SELECT: + $options['where'] = str_replace( + $extra_info['field'], + 'fv'.$counter.'.field_id = '.$extra_info['id'].' AND fvo'.$counter.'.option_value', + $options['where'] + ); + $inject_joins .= " + INNER JOIN $this->table_field_options fvo$counter + ON ( + fv$counter.field_id = fvo$counter.field_id AND + fv$counter.value = fvo$counter.option_value + ) + "; + break; + case self::FIELD_TYPE_TAG: + /*$options['where'] = str_replace( + $extra_info['field'], + 'tag'.$counter.'.tag ', + $options['where'] + );*/ + $newCounter = 1; + $whereTag = []; + foreach ($extra['data'] as $data) { + $data = Database::escape_string($data); + $key = $counter.$newCounter; + $whereTag[] = ' tag'.$key.'.tag LIKE "%'.$data.'%" '; + $inject_joins .= " + INNER JOIN $this->table_field_rel_tag tag_rel$key + ON ( + tag_rel$key.field_id = ".$extra_info['id']." AND + tag_rel$key.item_id = $alias.".$this->primaryKey." + ) + INNER JOIN $this->table_field_tag tag$key + ON (tag$key.id = tag_rel$key.tag_id) + "; + $newCounter++; + } + $options['where'] = ' ('.implode(' AND ', $whereTag).') '; + break; + default: + // text, textarea, etc + $options['where'] = str_replace( + $extra_info['field'], + 'fv'.$counter.'.field_id = '.$extra_info['id'].' AND fv'.$counter.'.value', + $options['where'] + ); + break; + } + $field_value_to_join[] = " fv$counter.$this->handler_id "; + $counter++; + } + } + $where .= ' AND '.$options['where']; + } + + $order = null; + if (!empty($options['order'])) { + $order = ' ORDER BY '.$options['order']; + } + $limit = null; + if (!empty($options['limit'])) { + $limit = ' LIMIT '.$options['limit']; + } + + return [ + 'order' => $order, + 'limit' => $limit, + 'where' => $where, + 'inject_where' => $inject_where, + 'inject_joins' => $inject_joins, + 'field_value_to_join' => $field_value_to_join, + 'inject_extra_fields' => $inject_extra_fields, + ]; + } + /** * Get the extra fields and their formatted values. * * @param int|string $itemId The item ID (It could be a session_id, course_id or user_id) + * @param bool $filter + * @param array $onlyShow (list of extra fields variables to show) * * @return array The extra fields data */ - public function getDataAndFormattedValues($itemId) + public function getDataAndFormattedValues($itemId, $filter = false, $onlyShow = []) { $valuesData = []; $fields = $this->get_all(); $em = Database::getManager(); + $repoTag = $em->getRepository('ChamiloCoreBundle:ExtraFieldRelTag'); + foreach ($fields as $field) { if ('1' != $field['visible_to_self']) { continue; } + if ($filter && $field['filter'] != 1) { + continue; + } + + if (!empty($onlyShow) && !in_array($field['variable'], $onlyShow)) { + continue; + } + + $valueAsArray = []; $fieldValue = new ExtraFieldValue($this->type); $valueData = $fieldValue->get_values_by_handler_and_field_id( $itemId, $field['id'], true ); - if (ExtraField::FIELD_TYPE_TAG == $field['field_type']) { - $tags = $em - ->getRepository('ChamiloCoreBundle:ExtraFieldRelTag') - ->findBy( - [ - 'fieldId' => $field['id'], - 'itemId' => $itemId, - ] - ); + $tags = $repoTag->findBy(['fieldId' => $field['id'], 'itemId' => $itemId]); if ($tags) { /** @var \Chamilo\CoreBundle\Entity\ExtraFieldRelTag $tag */ $data = []; foreach ($tags as $extraFieldTag) { /** @var \Chamilo\CoreBundle\Entity\Tag $tag */ $tag = $em->find('ChamiloCoreBundle:Tag', $extraFieldTag->getTagId()); - /*$data[] = [ - 'id' => $extraFieldTag->getTagId(), - 'value' => $tag->getTag() - ];*/ $data[] = $tag->getTag(); } $valueData = implode(',', $data); + $valueAsArray = $data; } } if (!$valueData) { continue; } - - $displayedValue = get_lang('none'); + $displayedValue = get_lang('None'); switch ($field['field_type']) { case self::FIELD_TYPE_CHECKBOX: @@ -2670,48 +2994,16 @@ JAVASCRIPT; } $valuesData[] = [ + 'variable' => $field['variable'], 'text' => $field['display_text'], 'value' => $displayedValue, + 'value_as_array' => $valueAsArray, ]; } return $valuesData; } - /** - * Gets an element. - * - * @param int $id - * @param bool $translateDisplayText Optional - * - * @return array - */ - public function get($id, $translateDisplayText = true) - { - $info = parent::get($id); - - if ($translateDisplayText) { - $info['display_text'] = self::translateDisplayName($info['variable'], $info['display_text']); - } - - return $info; - } - - /** - * Translate the display text for a extra field. - * - * @param string $variable - * @param string $defaultDisplayText - * - * @return string - */ - public static function translateDisplayName($variable, $defaultDisplayText) - { - $camelCase = api_underscore_to_camel_case($variable); - - return isset($GLOBALS[$camelCase]) ? $GLOBALS[$camelCase] : $defaultDisplayText; - } - /** * @param int $fieldId * @param string $tag @@ -2745,8 +3037,8 @@ JAVASCRIPT; { $skillTable = Database::get_main_table(TABLE_MAIN_SKILL); $tagRelExtraTable = Database::get_main_table(TABLE_MAIN_EXTRA_FIELD_REL_TAG); - $fieldId = intval($fieldId); - $tagId = intval($tagId); + $fieldId = (int) $fieldId; + $tagId = (int) $tagId; $sql = "SELECT s.id FROM $skillTable s INNER JOIN $tagRelExtraTable t @@ -2811,212 +3103,6 @@ JAVASCRIPT; return $result; } - /** - * @param string $variable - * @param string $dataValue - * - * @return string - */ - public static function getLocalizationJavascript($variable, $dataValue) - { - $dataValue = addslashes($dataValue); - $html = ""; - - return $html; - } - - /** - * @param string $variable - * @param string $text - * - * @return string - */ - public static function getLocalizationInput($variable, $text) - { - $html = ' -
- -
- - -
-
-
- -
-
-
-
-
- '; - - return $html; - } - - /** - * @param int $parentId - * - * @return array - */ - private static function getOptionsFromTripleSelect(array $options, $parentId) - { - return array_filter($options, function ($option) use ($parentId) { - return $option['option_value'] == $parentId; - }); - } - /** * @param \FormValidator $form * @param int $defaultValueId @@ -3108,57 +3194,6 @@ JAVASCRIPT; $slct->addOption(implode('', $valueParts), $value, ['data-value' => $dataValue]); } - /* Enable this when field_loggeable is introduced as a table field (2.0) - if ($optionsExists && $field_details['field_loggeable'] && !empty($defaultValueId)) { - - $form->addElement( - 'textarea', - 'extra_' . $field_details['variable'] . '_comment', - $field_details['display_text'] . ' ' . get_lang('Comment') - ); - - $extraFieldValue = new ExtraFieldValue($this->type); - $repo = $app['orm.em']->getRepository($extraFieldValue->entityName); - $repoLog = $app['orm.em']->getRepository('Gedmo\Loggable\Entity\LogEntry'); - $newEntity = $repo->findOneBy( - array( - $this->handlerEntityId => $itemId, - 'fieldId' => $field_details['id'] - ) - ); - // @todo move this in a function inside the class - if ($newEntity) { - $logs = $repoLog->getLogEntries($newEntity); - if (!empty($logs)) { - $html = '' . get_lang('Latest changes') . '

'; - - $table = new HTML_Table(array('class' => 'data_table')); - $table->setHeaderContents(0, 0, get_lang('Value')); - $table->setHeaderContents(0, 1, get_lang('Comment')); - $table->setHeaderContents(0, 2, get_lang('EditDate')); - $table->setHeaderContents(0, 3, get_lang('Username')); - $row = 1; - foreach ($logs as $log) { - $column = 0; - $data = $log->getData(); - $fieldValue = isset($data['fieldValue']) ? $data['fieldValue'] : null; - $comment = isset($data['comment']) ? $data['comment'] : null; - - $table->setCellContents($row, $column, $fieldValue); - $column++; - $table->setCellContents($row, $column, $comment); - $column++; - $table->setCellContents($row, $column, api_get_local_time($log->getLoggedAt()->format('Y-m-d H:i:s'))); - $column++; - $table->setCellContents($row, $column, $log->getUsername()); - $row++; - } - $form->addElement('label', null, $html.$table->toHtml()); - } - } - } - */ - if ($freezeElement) { $form->freeze('extra_'.$fieldDetails['variable']); } @@ -3230,6 +3265,7 @@ JAVASCRIPT; } } } + $form ->defaultRenderer() ->setGroupElementTemplate('

{element}

', 'extra_'.$fieldDetails['variable']); @@ -3440,7 +3476,13 @@ JAVASCRIPT; /** @var \HTML_QuickForm_select $slctFirst */ $slctFirst = $form->createElement('select', "extra_$variable", null, $values1, ['id' => $slctFirstId]); /** @var \HTML_QuickForm_select $slctFirst */ - $slctSecond = $form->createElement('select', "extra_{$variable}_second", null, $values2, ['id' => $slctSecondId]); + $slctSecond = $form->createElement( + 'select', + "extra_{$variable}_second", + null, + $values2, + ['id' => $slctSecondId] + ); /** @var \HTML_QuickForm_select $slctFirst */ $slctThird = $form->createElement('select', "extra_{$variable}_third", null, $values3, ['id' => $slctThirdId]); @@ -3473,4 +3515,19 @@ JAVASCRIPT; return $js; } + + /** + * @param int $parentId + * + * @return array + */ + private static function getOptionsFromTripleSelect(array $options, $parentId) + { + return array_filter( + $options, + function ($option) use ($parentId) { + return $option['option_value'] == $parentId; + } + ); + } } diff --git a/public/main/inc/lib/extra_field_option.lib.php b/public/main/inc/lib/extra_field_option.lib.php index e97b460130..d4729d959a 100644 --- a/public/main/inc/lib/extra_field_option.lib.php +++ b/public/main/inc/lib/extra_field_option.lib.php @@ -1,4 +1,5 @@ extraField; } - /** - * Gets the number of options already available in the table for this item type. - * - * @return int Number of options available - * @assert () >= 0 - */ - /*public function get_count() - { - $row = Database::select('count(*) as count', $this->table, array(), 'first'); - - return $row['count']; - }*/ - /** * Gets the number of options available for this field. * @@ -75,7 +63,7 @@ class ExtraFieldOption extends Model return false; } $extraFieldType = $this->getExtraField()->getExtraFieldType(); - $fieldId = intval($fieldId); + $fieldId = (int) $fieldId; $sql = "SELECT count(*) as count FROM $this->table o @@ -125,11 +113,10 @@ class ExtraFieldOption extends Model */ public function delete_all_options_by_field_id($field_id) { - $field_id = intval($field_id); + $field_id = (int) $field_id; $sql = "DELETE FROM {$this->table} WHERE field_id = $field_id"; - $r = Database::query($sql); - return $r; + return Database::query($sql); } /** @@ -173,7 +160,7 @@ class ExtraFieldOption extends Model */ public function save($params, $showQuery = false) { - $field_id = intval($params['field_id']); + $field_id = (int) $params['field_id']; if (empty($field_id)) { return false; @@ -421,7 +408,7 @@ class ExtraFieldOption extends Model */ public function get_field_option_by_field_and_option($field_id, $option_value) { - $field_id = intval($field_id); + $field_id = (int) $field_id; $option_value = Database::escape_string($option_value); $extraFieldType = $this->getExtraField()->getExtraFieldType(); @@ -452,7 +439,7 @@ class ExtraFieldOption extends Model */ public function get_field_option_by_field_id_and_option_display_text($field_id, $option_display_text) { - $field_id = intval($field_id); + $field_id = (int) $field_id; $option_display_text = Database::escape_string($option_display_text); $extraFieldType = $this->getExtraField()->getExtraFieldType(); @@ -487,7 +474,7 @@ class ExtraFieldOption extends Model $option_display_text, $option_value ) { - $field_id = intval($field_id); + $field_id = (int) $field_id; $option_display_text = Database::escape_string($option_display_text); $option_value = Database::escape_string($option_value); $extraFieldType = $this->getExtraField()->getExtraFieldType(); @@ -520,7 +507,7 @@ class ExtraFieldOption extends Model */ public function get_field_options_by_field($field_id, $add_id_in_array = false, $ordered_by = null) { - $field_id = intval($field_id); + $field_id = (int) $field_id; $orderBy = null; switch ($ordered_by) { @@ -589,7 +576,7 @@ class ExtraFieldOption extends Model public function get_second_select_field_options_by_field($option_value_id, $to_json = false) { $em = Database::getManager(); - $option = $em->find('ChamiloCoreBundle:ExtraFieldOptions', intval($option_value_id)); + $option = $em->find('ChamiloCoreBundle:ExtraFieldOptions', $option_value_id); if (!$option) { return !$to_json ? [] : '{}'; @@ -676,7 +663,7 @@ class ExtraFieldOption extends Model */ public function get_max_order($field_id) { - $field_id = intval($field_id); + $field_id = (int) $field_id; $sql = "SELECT MAX(option_order) FROM {$this->table} WHERE field_id = $field_id"; @@ -758,7 +745,7 @@ class ExtraFieldOption extends Model } $form->addElement('header', $header); - $id = isset($_GET['id']) ? intval($_GET['id']) : ''; + $id = isset($_GET['id']) ? (int) $_GET['id'] : ''; $form->addElement('hidden', 'id', $id); $form->addElement('hidden', 'type', $this->type); @@ -817,9 +804,10 @@ class ExtraFieldOption extends Model */ public function searchByField($tag, $field_id, $limit = 10) { - $field_id = intval($field_id); - $limit = intval($limit); + $field_id = (int) $field_id; + $limit = (int) $limit; $tag = Database::escape_string($tag); + $sql = "SELECT DISTINCT id, option_display_text FROM {$this->table} WHERE @@ -928,7 +916,7 @@ class ExtraFieldOption extends Model /** * @param string $variable * - * @return array|\Chamilo\CoreBundle\Entity\ExtraFieldOptions[] + * @return array|ExtraFieldOptions[] */ public function getOptionsByFieldVariable($variable) { diff --git a/public/main/inc/lib/extra_field_value.lib.php b/public/main/inc/lib/extra_field_value.lib.php index 73a134811b..752a798be7 100644 --- a/public/main/inc/lib/extra_field_value.lib.php +++ b/public/main/inc/lib/extra_field_value.lib.php @@ -1,4 +1,5 @@ $value) { $found = strpos($key, '__persist__'); @@ -116,19 +119,22 @@ class ExtraFieldValue extends Model // Parse params. foreach ($extraFields as $fieldDetails) { - $field_variable = $fieldDetails['variable']; + if ($forceSave === false) { // if the field is not visible to the user in the end, we need to apply special rules if (1 != $fieldDetails['visible_to_self']) { - //only admins should be able to add those values - if (!api_is_platform_admin(true, true)) { - // although if not admin but sent through a CLI script, we should accept it as well - if (PHP_SAPI != 'cli') { - continue; //not a CLI script, so don't write the value to DB + //only admins should be able to add those values + if (!api_is_platform_admin(true, true)) { + // although if not admin but sent through a CLI script, we should accept it as well + if (PHP_SAPI != 'cli') { + continue; //not a CLI script, so don't write the value to DB + } } } } + $field_variable = $fieldDetails['variable']; + if ($onlySubmittedFields && !isset($params['extra_'.$field_variable])) { continue; } @@ -362,6 +368,32 @@ class ExtraFieldValue extends Model ]; $this->save($newParams); + break; + case ExtraField::FIELD_TYPE_DATE: + $d = DateTime::createFromFormat('Y-m-d', $value); + $valid = $d && $d->format('Y-m-d') === $value; + if ($valid) { + $newParams = [ + 'item_id' => $params['item_id'], + 'field_id' => $extraFieldInfo['id'], + 'value' => $value, + 'comment' => $comment, + ]; + $this->save($newParams, $showQuery); + } + break; + case ExtraField::FIELD_TYPE_DATETIME: + $d = DateTime::createFromFormat('Y-m-d H:i', $value); + $valid = $d && $d->format('Y-m-d H:i') === $value; + if ($valid) { + $newParams = [ + 'item_id' => $params['item_id'], + 'field_id' => $extraFieldInfo['id'], + 'value' => $value, + 'comment' => $comment, + ]; + $this->save($newParams, $showQuery); + } break; default: $newParams = [ @@ -408,7 +440,9 @@ class ExtraFieldValue extends Model $extraFieldInfo = $extra_field->get_handler_field_info_by_field_variable( $params['variable'] ); - $params['field_id'] = $extraFieldInfo['id']; + if ($extraFieldInfo) { + $params['field_id'] = $extraFieldInfo['id']; + } } if ($extraFieldInfo) { @@ -721,31 +755,38 @@ class ExtraFieldValue extends Model * Gets the ID from the item (course, session, etc) for which * the given field is defined with the given value. * - * @param string $field_variable Field (type of data) we want to check - * @param string $field_value Data we are looking for in the given field + * @param string $variable Field (type of data) we want to check + * @param string $value Data we are looking for in the given field * @param bool $transform Whether to transform the result to a human readable strings * @param bool $last Whether to return the last element or simply the first one we get + * @param bool $useLike * * @return mixed Give the ID if found, or false on failure or not found * @assert (-1,-1) === false */ public function get_item_id_from_field_variable_and_field_value( - $field_variable, - $field_value, + $variable, + $value, $transform = false, $last = false, - $all = false + $all = false, + $useLike = false ) { - $field_value = Database::escape_string($field_value); - $field_variable = Database::escape_string($field_variable); + $value = Database::escape_string($value); + $variable = Database::escape_string($variable); + + $valueCondition = " value = '$value' AND "; + if ($useLike) { + $valueCondition = " value LIKE '%".$value."%' AND "; + } $extraFieldType = $this->getExtraField()->getExtraFieldType(); $sql = "SELECT item_id FROM {$this->table} s INNER JOIN {$this->table_handler_field} sf ON (s.field_id = sf.id) WHERE - value = '$field_value' AND - variable = '".$field_variable."' AND + $valueCondition + variable = '".$variable."' AND sf.extra_field_type = $extraFieldType ORDER BY item_id "; @@ -757,7 +798,7 @@ class ExtraFieldValue extends Model $sql .= ' DESC'; } $result = Database::query($sql); - if (false !== $result && Database::num_rows($result)) { + if ($result !== false && Database::num_rows($result)) { if ($all) { $result = Database::store_result($result, 'ASSOC'); } else { @@ -765,9 +806,9 @@ class ExtraFieldValue extends Model } return $result; - } else { - return false; } + + return false; } /** diff --git a/public/main/inc/lib/glossary.lib.php b/public/main/inc/lib/glossary.lib.php index 88bce100c8..48d4e3891c 100644 --- a/public/main/inc/lib/glossary.lib.php +++ b/public/main/inc/lib/glossary.lib.php @@ -73,25 +73,42 @@ class GlossaryManager * * @author Isaac Flores * - * @param string $glossary_name The glossary term name + * @param string $name The glossary term name * * @return array The glossary info */ - public static function get_glossary_term_by_glossary_name($glossary_name) + public static function get_glossary_term_by_glossary_name($name) { $table = Database::get_course_table(TABLE_GLOSSARY); $session_id = api_get_session_id(); $course_id = api_get_course_int_id(); - $sql_filter = api_get_session_condition($session_id); - $sql = 'SELECT * FROM '.$table.' + $sessionCondition = api_get_session_condition($session_id); + + $glossaryName = Security::remove_XSS($name); + $glossaryName = api_convert_encoding($glossaryName, 'UTF-8', 'UTF-8'); + $glossaryName = trim($glossaryName); + $parsed = $glossaryName; + + if (api_get_configuration_value('save_titles_as_html')) { + $parsed = api_htmlentities($parsed); + $parsed = "%$parsed%"; + } + + $sql = "SELECT * FROM $table WHERE - c_id = '.$course_id.' AND - name LIKE trim("'.Database::escape_string($glossary_name).'")'.$sql_filter; + c_id = $course_id AND + ( + name LIKE '".Database::escape_string($glossaryName)."' + OR + name LIKE '".Database::escape_string($parsed)."' + ) + $sessionCondition + LIMIT 1 + "; $rs = Database::query($sql); - if (Database::num_rows($rs) > 0) { - $row = Database::fetch_array($rs, 'ASSOC'); - return $row; + if (Database::num_rows($rs) > 0) { + return Database::fetch_array($rs, 'ASSOC'); } return []; diff --git a/public/main/inc/lib/groupmanager.lib.php b/public/main/inc/lib/groupmanager.lib.php index 4027b08647..db262a34ed 100644 --- a/public/main/inc/lib/groupmanager.lib.php +++ b/public/main/inc/lib/groupmanager.lib.php @@ -16,10 +16,6 @@ use Chamilo\CourseBundle\Entity\CGroupRelUser; */ class GroupManager { - /* VIRTUAL_COURSE_CATEGORY: - in this category groups are created based on the virtual course of a course*/ - public const VIRTUAL_COURSE_CATEGORY = 1; - /* DEFAULT_GROUP_CATEGORY: When group categories aren't available (platform-setting), all groups are created in this 'dummy'-category*/ @@ -653,17 +649,18 @@ class GroupManager public static function getGroupListFilterByName($name, $categoryId, $courseId) { $name = trim($name); + $name = Database::escape_string($name); + $categoryId = (int) $categoryId; + $courseId = (int) $courseId; + if (empty($name)) { return []; } - $name = Database::escape_string($name); - $courseId = (int) $courseId; $table_group = Database::get_course_table(TABLE_GROUP); $sql = "SELECT * FROM $table_group WHERE c_id = $courseId AND name LIKE '%$name%'"; if (!empty($categoryId)) { - $categoryId = intval($categoryId); $sql .= " AND category_id = $categoryId"; } $sql .= " ORDER BY name"; @@ -1234,8 +1231,8 @@ class GroupManager } if (!empty($start) && !empty($limit)) { - $start = intval($start); - $limit = intval($limit); + $start = (int) $start; + $limit = (int) $limit; $sql .= " LIMIT $start, $limit"; } $res = Database::query($sql); @@ -1473,11 +1470,11 @@ class GroupManager public static function number_of_students($group_id, $course_id = null) { $table = Database::get_course_table(TABLE_GROUP_USER); - $group_id = intval($group_id); + $group_id = (int) $group_id; + $course_id = (int) $course_id; + if (empty($course_id)) { $course_id = api_get_course_int_id(); - } else { - $course_id = intval($course_id); } $sql = "SELECT COUNT(*) AS number_of_students FROM $table @@ -1498,7 +1495,7 @@ class GroupManager public static function maximum_number_of_students($group_id) { $table = Database::get_course_table(TABLE_GROUP); - $group_id = intval($group_id); + $group_id = (int) $group_id; $course_id = api_get_course_int_id(); $sql = "SELECT max_student FROM $table WHERE c_id = $course_id AND iid = $group_id"; @@ -2247,10 +2244,11 @@ class GroupManager * * @param int $user_id * @param int $courseId + * @param int|null $sessionId * * @return array */ - public static function getAllGroupPerUserSubscription($user_id, $courseId = 0) + public static function getAllGroupPerUserSubscription($user_id, $courseId = 0, $sessionId = null) { $table_group_user = Database::get_course_table(TABLE_GROUP_USER); $table_tutor_user = Database::get_course_table(TABLE_GROUP_TUTOR); @@ -2267,6 +2265,12 @@ class GroupManager WHERE g.c_id = $courseId AND (gu.user_id = $user_id OR tu.user_id = $user_id) "; + + if (null !== $sessionId) { + $sessionId = (int) $sessionId; + $sql .= " AND g.session_id = $sessionId "; + } + $res = Database::query($sql); $groups = []; while ($group = Database::fetch_array($res, 'ASSOC')) { @@ -2284,7 +2288,7 @@ class GroupManager */ public static function process_groups($group_list, $category_id = 0) { - global $charset; + $charset = 'UTF-8'; $category_id = (int) $category_id; $totalRegistered = 0; $group_data = []; @@ -2292,13 +2296,16 @@ class GroupManager $session_id = api_get_session_id(); $user_id = $user_info['user_id']; $hideGroup = api_get_setting('hide_course_group_if_no_tools_available'); + $extraField = new ExtraField('survey'); + $surveyGroupExists = $extraField->get_handler_field_info_by_field_variable('group_id') ? true : false; + $url = api_get_path(WEB_CODE_PATH).'group/'; foreach ($group_list as $this_group) { // Validation when belongs to a session $session_img = api_get_session_image($this_group['session_id'], $user_info['status']); // All the tutors of this group - $tutorsids_of_group = self::get_subscribed_tutors($this_group, true); + $tutors = self::get_subscribed_tutors($this_group, true); $isMember = self::is_subscribed($user_id, $this_group); // Create a new table-row @@ -2344,8 +2351,8 @@ class GroupManager // Tutor name $tutor_info = ''; - if (count($tutorsids_of_group) > 0) { - foreach ($tutorsids_of_group as $tutor_id) { + if (count($tutors) > 0) { + foreach ($tutors as $tutor_id) { $tutor = api_get_user_info($tutor_id); $username = api_htmlentities( sprintf(get_lang('Login: %s'), $tutor['username']), @@ -2405,7 +2412,6 @@ class GroupManager } } - $url = api_get_path(WEB_CODE_PATH).'group/'; // Edit-links if (api_is_allowed_to_edit(false, true) && !(api_is_session_general_coach() && intval($this_group['session_id']) != $session_id) @@ -2427,10 +2433,18 @@ class GroupManager $edit_actions .= ''. Display::return_icon('export_excel.png', get_lang('Export'), '', ICON_SIZE_SMALL).' '; - $edit_actions .= ''. - Display::return_icon('fill.png', get_lang('Fill the group randomly with course students'), '', ICON_SIZE_SMALL).' '; + if ($surveyGroupExists) { + $edit_actions .= Display::url( + Display::return_icon('survey.png', get_lang('ExportSurveyResults'), '', ICON_SIZE_SMALL), + $url.'group_overview.php?action=export_surveys&'.api_get_cidreq(true, false).'&id='.$this_group['id'] + ).' '; + } + $edit_actions .= ''. + Display::return_icon('fill.png', get_lang('FillGroup'), '', ICON_SIZE_SMALL).' '; - $edit_actions .= ''. + $edit_actions .= ''. Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_SMALL).' '; $row[] = $edit_actions; @@ -2899,7 +2913,7 @@ class GroupManager * * @return string */ - public static function getOverview($courseId, $keyword = null) + public static function getOverview($courseId, $keyword = '') { $content = null; $categories = self::get_categories(); diff --git a/public/main/inc/lib/image.lib.php b/public/main/inc/lib/image.lib.php index 0757259a08..6140e0bfc2 100644 --- a/public/main/inc/lib/image.lib.php +++ b/public/main/inc/lib/image.lib.php @@ -139,6 +139,8 @@ class Image /** * Image wrapper class. + * + * @package chamilo.include.image */ abstract class ImageWrapper { diff --git a/public/main/inc/lib/legal.lib.php b/public/main/inc/lib/legal.lib.php index ebb2f59847..15beb22365 100644 --- a/public/main/inc/lib/legal.lib.php +++ b/public/main/inc/lib/legal.lib.php @@ -1,4 +1,5 @@ 2000) { - $legal[2] = substr($legal[2], 0, 2000).' ... '; + $legal[2] = substr(strip_tags($legal[2]), 0, 2000).' ... '; } if (0 == $legal[4]) { $legal[4] = get_lang('HTML'); diff --git a/public/main/inc/lib/message.lib.php b/public/main/inc/lib/message.lib.php index 881d621417..aaec076276 100644 --- a/public/main/inc/lib/message.lib.php +++ b/public/main/inc/lib/message.lib.php @@ -187,7 +187,8 @@ class MessageManager title as col1, send_date as col2, msg_status as col3, - user_sender_id + user_sender_id, + user_receiver_id FROM $table WHERE $whereConditions @@ -206,6 +207,7 @@ class MessageManager $sendDate = $row['col2']; $status = $row['col3']; $senderId = $row['user_sender_id']; + $receiverId = $row['user_receiver_id']; $title = Security::remove_XSS($title, STUDENT, true); $title = cut($title, 80, true); @@ -216,6 +218,9 @@ class MessageManager } $userInfo = api_get_user_info($senderId); + if ($type == self::MESSAGE_TYPE_OUTBOX) { + $userInfo = api_get_user_info($receiverId); + } $message[3] = ''; if (!empty($senderId) && !empty($userInfo)) { $message[1] = ''.$title.'
'; @@ -569,6 +574,7 @@ class MessageManager } else { $params = [ 'user_sender_id' => $user_sender_id, + 'user_receiver_id' => $receiver_user_id, 'msg_status' => $status, 'send_date' => $now, 'title' => $subject, @@ -577,9 +583,6 @@ class MessageManager 'parent_id' => $parent_id, 'update_date' => $now, ]; - if (!empty($receiver_user_id)) { - $params['user_receiver_id'] = $receiver_user_id; - } $messageId = Database::insert($table, $params); } @@ -2459,6 +2462,92 @@ class MessageManager return $messages; } + /** + * Get the data of the last received messages for a user. + * + * @param int $userId The user id + * @param int $lastId The id of the last received message + * + * @return array + */ + public static function getReceivedMessages($userId, $lastId = 0) + { + $userId = intval($userId); + $lastId = intval($lastId); + + if (empty($userId)) { + return []; + } + $messagesTable = Database::get_main_table(TABLE_MESSAGE); + $userTable = Database::get_main_table(TABLE_MAIN_USER); + $sql = "SELECT m.*, u.user_id, u.lastname, u.firstname, u.picture_uri + FROM $messagesTable as m + INNER JOIN $userTable as u + ON m.user_sender_id = u.user_id + WHERE + m.user_receiver_id = $userId AND + m.msg_status IN (".MESSAGE_STATUS_NEW.", ".MESSAGE_STATUS_UNREAD.") + AND m.id > $lastId + ORDER BY m.send_date DESC"; + + $result = Database::query($sql); + + $messages = []; + if ($result !== false) { + while ($row = Database::fetch_assoc($result)) { + $pictureInfo = UserManager::get_user_picture_path_by_id($row['user_id'], 'web'); + $row['pictureUri'] = $pictureInfo['dir'].$pictureInfo['file']; + $messages[] = $row; + } + } + + return $messages; + } + + /** + * Get the data of the last received messages for a user. + * + * @param int $userId The user id + * @param int $lastId The id of the last received message + * + * @return array + */ + public static function getSentMessages($userId, $lastId = 0) + { + $userId = intval($userId); + $lastId = intval($lastId); + + if (empty($userId)) { + return []; + } + + $messagesTable = Database::get_main_table(TABLE_MESSAGE); + $userTable = Database::get_main_table(TABLE_MAIN_USER); + + $sql = "SELECT m.*, u.user_id, u.lastname, u.firstname, u.picture_uri + FROM $messagesTable as m + INNER JOIN $userTable as u + ON m.user_receiver_id = u.user_id + WHERE + m.user_sender_id = $userId + AND m.msg_status = ".MESSAGE_STATUS_OUTBOX." + AND m.id > $lastId + ORDER BY m.send_date DESC"; + + $result = Database::query($sql); + + $messages = []; + if ($result !== false) { + while ($row = Database::fetch_assoc($result)) { + $pictureInfo = UserManager::get_user_picture_path_by_id($row['user_id'], 'web'); + $row['pictureUri'] = $pictureInfo['dir'].$pictureInfo['file']; + $messages[] = $row; + } + } + + return $messages; + } + /** * Check whether a message has attachments. * @@ -2565,7 +2654,7 @@ class MessageManager /** * Send a notification to all admins when a new user is registered. */ - public static function sendNotificationByRegisteredUser(User $user) + public static function sendNotificationOfNewRegisteredUser(User $user) { $tplMailBody = new Template( null, @@ -2606,6 +2695,86 @@ class MessageManager } } + /** + * Send a notification to all admins when a new user is registered + * while the approval method is used for users registration. + */ + public static function sendNotificationOfNewRegisteredUserApproval(User $user) + { + $tplMailBody = new Template( + null, + false, + false, + false, + false, + false, + false + ); + $tplMailBody->assign('user', $user); + $tplMailBody->assign('is_western_name_order', api_is_western_name_order()); + $userId = $user->getId(); + $url_edit = Display::url( + api_get_path(WEB_CODE_PATH).'admin/user_edit.php?user_id='.$userId, + api_get_path(WEB_CODE_PATH).'admin/user_edit.php?user_id='.$userId + ); + $tplMailBody->assign( + 'manageUrl', + $url_edit + ); + // Get extra field values for this user and reformat the array + $extraFieldValues = new ExtraFieldValue('user'); + $userExtraFields = $extraFieldValues->getAllValuesByItem($userId); + $values = []; + foreach ($userExtraFields as $field => $value) { + $values[$value['variable']] = $value['value']; + } + $tplMailBody->assign( + 'extra', + $values + ); + $layoutContent = ''; + $emailbody = ''; + if (api_get_configuration_value('mail_template_system') == true) { + $mailTemplateManager = new MailTemplateManager(); + $templateText = $mailTemplateManager->getTemplateByType('new_user_mail_to_admin_approval.tpl'); + if (empty($templateText)) { + } else { + // custom procedure to load a template as a string (doesn't use cache so may slow down) + $template = $tplMailBody->twig->createTemplate($templateText); + $emailbody = $template->render($tplMailBody->params); + } + } + if (empty($emailbody)) { + $layoutContent = $tplMailBody->get_template('mail/new_user_mail_to_admin_approval.tpl'); + $emailbody = $tplMailBody->fetch($layoutContent); + } + + $emailsubject = '['.get_lang('ApprovalForNewAccount').'] '.$user->getUsername(); + + if (api_get_configuration_value('send_inscription_notification_to_general_admin_only')) { + $email = api_get_setting('emailAdministrator'); + $firstname = api_get_setting('administratorSurname'); + $lastname = api_get_setting('administratorName'); + api_mail_html("$firstname $lastname", $email, $emailsubject, $emailbody); + } else { + $admins = UserManager::get_all_administrators(); + foreach ($admins as $admin_info) { + self::send_message( + $admin_info['user_id'], + $emailsubject, + $emailbody, + [], + [], + null, + null, + null, + null, + $userId + ); + } + } + } + /** * Get the error log from failed mailing * This assumes a complex setup where you have a cron script regularly copying the mail queue log diff --git a/public/main/inc/lib/myspace.lib.php b/public/main/inc/lib/myspace.lib.php index 321af6111d..6f446b0303 100644 --- a/public/main/inc/lib/myspace.lib.php +++ b/public/main/inc/lib/myspace.lib.php @@ -399,7 +399,13 @@ class MySpace $is_western_name_order = api_is_western_name_order(); } $sort_by_first_name = api_sort_by_first_name(); - $tracking_column = isset($_GET['tracking_list_coaches_column']) ? $_GET['tracking_list_coaches_column'] : ($is_western_name_order xor $sort_by_first_name) ? 1 : 0; + + if (isset($_GET['tracking_list_coaches_column'])) { + $tracking_column = (int) $_GET['tracking_list_coaches_column']; + } else { + $tracking_column = ($is_western_name_order xor $sort_by_first_name) ? 1 : 0; + } + $tracking_direction = (isset($_GET['tracking_list_coaches_direction']) && in_array(strtoupper($_GET['tracking_list_coaches_direction']), ['ASC', 'DESC', 'ASCENDING', 'DESCENDING', '0', '1'])) ? $_GET['tracking_list_coaches_direction'] : 'DESC'; // Prepare array for column order - when impossible, use some of user names. if ($is_western_name_order) { @@ -1905,12 +1911,22 @@ class MySpace '.Display::return_icon('2rightarrow.png', get_lang('Details')).' '; + + $scoreInCourse = null; + if (null !== $avg_score_in_course) { + if (is_numeric($avg_score_in_course)) { + $scoreInCourse = $avg_score_in_course.'%'; + } else { + $scoreInCourse = $avg_score_in_course; + } + } + $csv_content[] = [ api_html_entity_decode($row_course[1], ENT_QUOTES, $charset), $nb_students_in_course, $avg_time_spent_in_course, is_null($avg_progress_in_course) ? null : $avg_progress_in_course.'%', - is_null($avg_score_in_course) ? null : is_numeric($avg_score_in_course) ? $avg_score_in_course.'%' : $avg_score_in_course, + $scoreInCourse, is_null($avg_score_in_exercise) ? null : $avg_score_in_exercise.'%', $avg_messages_in_course, $avg_assignments_in_course, @@ -2673,7 +2689,8 @@ class MySpace } if (isset($_GET['date']) && !empty($_GET['date'])) { - $dates = DateRangePicker::parseDateRange($_GET['date']); + $dateRangePicker = new DateRangePicker('date'); + $dates = $dateRangePicker->parseDateRange($_GET['date']); if (isset($dates['start']) && !empty($dates['start'])) { $dates['start'] = Database::escape_string($dates['start']); $sql .= " AND login_course_date >= '".$dates['start']."'"; @@ -2736,6 +2753,7 @@ class MySpace * @param int $sessionId * @param string $start_date * @param string $end_date + * @param bool $addUserIp * * @author Jorge Frisancho Jibaja * @author Julio Montoya fixing the function @@ -2749,14 +2767,15 @@ class MySpace $course_info, $sessionId, $start_date, - $end_date + $end_date, + $addUserIp = false ) { $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS); $user_id = (int) $user_id; $connections = []; if (!empty($course_info)) { $courseId = (int) $course_info['real_id']; - $end_date = add_day_to($end_date); + $end_date = self::add_day_to($end_date); $start_date = Database::escape_string($start_date); $end_date = Database::escape_string($end_date); @@ -2764,7 +2783,8 @@ class MySpace $sql = "SELECT login_course_date, logout_course_date, - TIMESTAMPDIFF(SECOND, login_course_date, logout_course_date) duration + TIMESTAMPDIFF(SECOND, login_course_date, logout_course_date) duration, + user_ip FROM $table WHERE user_id = $user_id AND @@ -2776,20 +2796,23 @@ class MySpace $rs = Database::query($sql); while ($row = Database::fetch_array($rs)) { - $connections[] = [ + $item = [ 'login' => $row['login_course_date'], 'logout' => $row['logout_course_date'], 'duration' => $row['duration'], ]; + if ($addUserIp) { + $item['user_ip'] = $row['user_ip']; + } + $connections[] = $item; } } return $connections; } -} /** - * @param $user_id + * @param int $user_id * @param array $course_info * @param int $sessionId * @param null $start_date @@ -2797,15 +2820,15 @@ class MySpace * * @return array */ -function get_stats($user_id, $course_info, $sessionId, $start_date = null, $end_date = null) + public static function getStats($user_id, $course_info, $sessionId, $start_date = null, $end_date = null) { $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS); $result = []; if (!empty($course_info)) { $stringStartDate = ''; $stringEndDate = ''; - if (null != $start_date && null != $end_date) { - $end_date = add_day_to($end_date); + if ($start_date != null && $end_date != null) { + $end_date = self::add_day_to($end_date); $start_date = Database::escape_string($start_date); $end_date = Database::escape_string($end_date); @@ -2843,7 +2866,7 @@ function get_stats($user_id, $course_info, $sessionId, $start_date = null, $end_ return $result; } -function add_day_to($end_date) + public static function add_day_to($end_date) { $foo_date = strtotime($end_date); $foo_date = strtotime(' +1 day', $foo_date); @@ -2852,36 +2875,6 @@ function add_day_to($end_date) return $foo_date; } -/** - * Converte an array to a table in html. - * - * @param array $result - * - * @author Jorge Frisancho Jibaja - * - * @version OCT-22- 2010 - * - * @return string - */ -function convert_to_string($result) -{ - $html = ''; - if (!empty($result)) { - foreach ($result as $key => $data) { - $html .= ''; - $html .= ''; - } - } - $html .= '
'; - $html .= api_get_local_time($data['login']); - $html .= ''; - - $html .= api_time_to_hms(api_strtotime($data['logout']) - api_strtotime($data['login'])); - $html .= '
'; - - return $html; -} - /** * This function draw the graphic to be displayed on the user view as an image. * @@ -2896,7 +2889,7 @@ function convert_to_string($result) * * @return string */ -function grapher($sql_result, $start_date, $end_date, $type = '') + public static function grapher($sql_result, $start_date, $end_date, $type = '') { if (empty($start_date)) { $start_date = ''; @@ -2936,10 +2929,10 @@ function grapher($sql_result, $start_date, $end_date, $type = '') $logout = api_strtotime($data['logout']); //creating the main array if (isset($main_month_year[date('m-Y', $login)])) { - $main_month_year[date('m-Y', $login)] += float_format(($logout - $login) / 60, 0); + $main_month_year[date('m-Y', $login)] += (float) ($logout - $login) / 60; } if (isset($main_day[date('d-m-Y', $login)])) { - $main_day[date('d-m-Y', $login)] += float_format(($logout - $login) / 60, 0); + $main_day[date('d-m-Y', $login)] += (float) ($logout - $login) / 60; } if ($i > 500) { break; @@ -3096,15 +3089,13 @@ function grapher($sql_result, $start_date, $end_date, $type = '') $myCache->saveFromCache($chartHash, $imgPath); $imgPath = api_get_path(WEB_ARCHIVE_PATH).$chartHash; } - $html = ''; - return $html; + return ''; } else { - $foo_img = api_convert_encoding( - '
'.get_lang('Graphic not available').'
', + return api_convert_encoding( + '
'.get_lang('GraphicNotAvailable').'
', 'UTF-8' ); - - return $foo_img; + } } } diff --git a/public/main/inc/lib/sessionmanager.lib.php b/public/main/inc/lib/sessionmanager.lib.php index 268fe65869..5aa933491e 100644 --- a/public/main/inc/lib/sessionmanager.lib.php +++ b/public/main/inc/lib/sessionmanager.lib.php @@ -25,6 +25,10 @@ use Monolog\Logger; */ class SessionManager { + public const STATUS_PLANNED = 1; + public const STATUS_PROGRESS = 2; + public const STATUS_FINISHED = 3; + public const STATUS_CANCELLED = 4; // See BT#4871 public const SESSION_CHANGE_USER_REASON_SCHEDULE = 1; public const SESSION_CHANGE_USER_REASON_CLASSROOM = 2; @@ -487,9 +491,10 @@ class SessionManager * Get session list for a session admin or platform admin. * * @param int $userId User Id for the session admin. - * @param array $options Optional. Order and limit keys. - * @param bool $getCount Optional. Whether to get all the results or only the count. - * @param array $columns Optional. Columns from jqGrid. + * @param array $options Order and limit keys. + * @param bool $getCount Whether to get all the results or only the count. + * @param array $columns Columns from jqGrid. + * @param string $listType * * @return array */ @@ -497,7 +502,8 @@ class SessionManager $userId, $options = [], $getCount = false, - $columns = [] + $columns = [], + $listType = 'all' ) { $tblSession = Database::get_main_table(TABLE_MAIN_SESSION); $sessionCategoryTable = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY); @@ -523,10 +529,11 @@ class SessionManager $extraFieldModel = new ExtraFieldModel('session'); $conditions = $extraFieldModel->parseConditions($options); + $sqlInjectJoins = $conditions['inject_joins']; $where .= $conditions['where']; $sqlInjectWhere = $conditions['inject_where']; - $inject_extra_fields = $conditions['inject_extra_fields']; + $injectExtraFields = $conditions['inject_extra_fields']; $order = $conditions['order']; $limit = $conditions['limit']; @@ -553,13 +560,18 @@ class SessionManager access_end_date, s.visibility, s.session_category_id, - $inject_extra_fields + $injectExtraFields s.id "; if ($showCountUsers) { $select .= ', count(su.user_id) users'; } + + if (api_get_configuration_value('allow_session_status')) { + $select .= ', status'; + } + if (isset($options['order'])) { $isMakingOrder = 0 === strpos($options['order'], 'category_name'); } @@ -600,6 +612,43 @@ class SessionManager } } + $date = api_get_utc_datetime(); + + switch ($listType) { + case 'all': + break; + case 'active': + $query .= "AND ( + (s.access_end_date IS NULL) + OR + ( + s.access_start_date IS NOT NULL AND + s.access_end_date IS NOT NULL AND + s.access_start_date <= '$date' AND s.access_end_date >= '$date') + OR + ( + s.access_start_date IS NULL AND + s.access_end_date IS NOT NULL AND + s.access_end_date >= '$date' + ) + )"; + break; + case 'close': + $query .= "AND ( + ( + s.access_start_date IS NOT NULL AND + s.access_end_date IS NOT NULL AND + s.access_start_date <= '$date' AND s.access_end_date <= '$date') + OR + ( + s.access_start_date IS NULL AND + s.access_end_date IS NOT NULL AND + s.access_end_date <= '$date' + ) + )"; + break; + } + if ($showCountUsers) { $query .= ' GROUP by s.id'; } @@ -616,8 +665,12 @@ class SessionManager $sessions = Database::store_result($result, 'ASSOC'); - if ($getCount) { - return $sessions[0]['total_rows']; + if ('all' === $listType) { + if ($getCount) { + return $sessions[0]['total_rows']; + } + + return $sessions; } return $sessions; @@ -630,6 +683,7 @@ class SessionManager * @param bool $getCount Whether to get all the results or only the count * @param array $columns * @param array $extraFieldsToLoad + * @param string $listType * * @return mixed Integer for number of rows, or array of results * @assert ([],true) !== false @@ -638,27 +692,25 @@ class SessionManager $options = [], $getCount = false, $columns = [], - $extraFieldsToLoad = [] + $extraFieldsToLoad = [], + $listType = 'all' ) { $showCountUsers = false; - if (!$getCount && !empty($columns['column_model'])) { foreach ($columns['column_model'] as $column) { - if ('users' == $column['name']) { + if ('users' === $column['name']) { $showCountUsers = true; } } } $userId = api_get_user_id(); - $sessions = self::getSessionsForAdmin($userId, $options, $getCount, $columns); - + $sessions = self::getSessionsForAdmin($userId, $options, $getCount, $columns, $listType); if ($getCount) { return (int) $sessions; } $formattedSessions = []; - $categories = self::get_all_session_category(); $orderedCategories = []; if (!empty($categories)) { @@ -743,10 +795,12 @@ class SessionManager } } - $categoryName = isset($orderedCategories[$session['session_category_id']]) - ? $orderedCategories[$session['session_category_id']] - : ''; + $categoryName = isset($orderedCategories[$session['session_category_id']]) ? $orderedCategories[$session['session_category_id']] : ''; $session['category_name'] = $categoryName; + if (isset($session['status'])) { + $session['status'] = self::getStatusLabel($session['status']); + } + $formattedSessions[] = $session; } @@ -1361,7 +1415,6 @@ class SessionManager $date_to = '', $options ) { - //escaping variables $sessionId = intval($sessionId); $courseId = intval($courseId); $studentId = intval($studentId); @@ -4310,6 +4363,24 @@ class SessionManager return Database::store_result($result, 'ASSOC'); } + /** + * @param int $user_id + * + * @return array + * + * @deprecated use get_sessions_by_general_coach() + */ + public static function get_sessions_by_coach($user_id) + { + $session_table = Database::get_main_table(TABLE_MAIN_SESSION); + + return Database::select( + '*', + $session_table, + ['where' => ['id_coach = ?' => $user_id]] + ); + } + /** * @param int $user_id * @param int $courseId @@ -4452,21 +4523,33 @@ class SessionManager $inOneMonth = api_get_local_time($inOneMonth); if (api_strtotime($s['access_start_date']) < $now) { $s['access_start_date'] = api_get_local_time($now); + } else { + $s['access_start_date'] = api_get_local_time($s['access_start_date']); } if (api_strtotime($s['display_start_date']) < $now) { $s['display_start_date'] = api_get_local_time($now); + } else { + $s['display_start_date'] = api_get_local_time($s['display_start_date']); } if (api_strtotime($s['coach_access_start_date']) < $now) { $s['coach_access_start_date'] = api_get_local_time($now); + } else { + $s['coach_access_start_date'] = api_get_local_time($s['coach_access_start_date']); } if (api_strtotime($s['access_end_date']) < $now) { $s['access_end_date'] = $inOneMonth; + } else { + $s['access_end_date'] = api_get_local_time($s['access_end_date']); } if (api_strtotime($s['display_end_date']) < $now) { $s['display_end_date'] = $inOneMonth; + } else { + $s['display_end_date'] = api_get_local_time($s['display_end_date']); } if (api_strtotime($s['coach_access_end_date']) < $now) { $s['coach_access_end_date'] = $inOneMonth; + } else { + $s['coach_access_end_date'] = api_get_local_time($s['coach_access_end_date']); } $extraFieldValue = new ExtraFieldValue('session'); @@ -5995,13 +6078,6 @@ class SessionManager $direction = in_array(strtolower($direction), ['asc', 'desc']) ? $direction : 'asc'; $column = Database::escape_string($column); - $limitCondition = ''; - if (isset($from) && isset($numberItems)) { - $from = (int) $from; - $numberItems = (int) $numberItems; - $limitCondition = "LIMIT $from, $numberItems"; - } - $urlId = api_get_current_access_url_id(); $sessionConditions = ''; @@ -6042,34 +6118,34 @@ class SessionManager } switch ($status) { + case 'admin': case 'drh': break; case 'drh_all': // Show all by DRH if (empty($sessionIdList)) { - $sessionsListSql = self::get_sessions_followed_by_drh( + $sessionListFollowed = self::get_sessions_followed_by_drh( $userId, null, null, false, - true, true ); - } else { + + if (!empty($sessionListFollowed)) { + $sessionIdList = array_column($sessionListFollowed, 'id'); + } + } + + if (!empty($sessionIdList)) { $sessionIdList = array_map('intval', $sessionIdList); $sessionsListSql = "'".implode("','", $sessionIdList)."'"; - } - if (!empty($sessionsListSql)) { $sessionConditions = " AND s.id IN ($sessionsListSql) "; } - break; - case 'session_admin': - $sessionConditions = " AND s.id_coach = $userId "; - $userConditionsFromDrh = ''; - break; - case 'admin': + break; case 'teacher': + case 'session_admin': $sessionConditions = " AND s.id_coach = $userId "; $userConditionsFromDrh = ''; break; @@ -6123,18 +6199,18 @@ class SessionManager $sql = "$masterSelect ( ($select FROM $tbl_session s + INNER JOIN $tbl_session_rel_access_url url ON (url.session_id = s.id) INNER JOIN $tbl_session_rel_course_rel_user su ON (s.id = su.session_id) INNER JOIN $tbl_user u ON (u.user_id = su.user_id) - INNER JOIN $tbl_session_rel_access_url url ON (url.session_id = s.id) $where $sessionConditions $userConditionsFromDrh ) UNION ( $select FROM $tbl_course c + INNER JOIN $tbl_course_rel_access_url url ON (url.c_id = c.id) INNER JOIN $tbl_course_user cu ON (cu.c_id = c.id) INNER JOIN $tbl_user u ON (u.user_id = cu.user_id) - INNER JOIN $tbl_course_rel_access_url url ON (url.c_id = c.id) $where $courseConditions $userConditionsFromDrh @@ -6158,11 +6234,18 @@ class SessionManager $column = str_replace('u.', '', $column); $sql .= " ORDER BY $column $direction "; } + + $limitCondition = ''; + if (isset($from) && isset($numberItems)) { + $from = (int) $from; + $numberItems = (int) $numberItems; + $limitCondition = "LIMIT $from, $numberItems"; + } + $sql .= $limitCondition; $result = Database::query($sql); - $result = Database::store_result($result); - return $result; + return Database::store_result($result); } /** @@ -7523,7 +7606,7 @@ class SessionManager /** * @param int $sessionId - * @param array $extraFieldsToInclude + * @param array $extraFieldsToInclude (empty means all) * * @return array */ @@ -7539,7 +7622,7 @@ class SessionManager } $sessionExtraField = new ExtraFieldModel('session'); - $fieldList = $sessionExtraField->get_all([ + $fieldList = $sessionExtraField->get_all(empty($extraFieldsToInclude) ? [] : [ "variable IN ( ".implode(", ", $variablePlaceHolders)." ) " => $variables, ]); @@ -7556,23 +7639,15 @@ class SessionManager // Get session field values $extra = new ExtraFieldValue('session'); - $sessionFieldValueList = $extra->get_all( - [ - "field_id IN ( ".implode(", ", $variablePlaceHolders)." )" => array_keys($fields), - ] - ); - - foreach ($sessionFieldValueList as $sessionFieldValue) { - // Match session field values to session - if ($sessionFieldValue['item_id'] != $sessionId) { - continue; - } - - // Check if session field value is set in session field list - if (!isset($fields[$sessionFieldValue['field_id']])) { - continue; + $sessionFieldValueList = []; + foreach (array_keys($fields) as $fieldId) { + $sessionFieldValue = $extra->get_values_by_handler_and_field_id($sessionId, $fieldId); + if ($sessionFieldValue != false) { + $sessionFieldValueList[$fieldId] = $sessionFieldValue; } + } + foreach ($sessionFieldValueList as $sessionFieldValue) { $extrafieldVariable = $fields[$sessionFieldValue['field_id']]; $extrafieldValue = $sessionFieldValue['value']; @@ -7592,7 +7667,7 @@ class SessionManager */ public static function isValidId($sessionId) { - $sessionId = intval($sessionId); + $sessionId = (int) $sessionId; if ($sessionId > 0) { $rows = Database::select( 'id', @@ -7838,18 +7913,11 @@ class SessionManager $form->addElement('html', '