Файл extrafields.php в Cotonti

отвечает за управление дополнительными пользовательскими полями ( их еще называют экстраполя ) (extrafields) для различных таблиц базы данных

Файл extrafields.php в системной папке Cotonti CMF отвечает за управление дополнительными пользовательскими полями (их еще называют экстраполя) (extrafields) для различных таблиц базы данных. Эти поля могут быть использованы для хранения дополнительной информации, специфичной для определенных объектов, таких как страницы, категории, пользователи и другие.

Основные функции кода:

  1. Регистрация и управление дополнительными полями:

    • Функции в файле позволяют добавлять, изменять, удалять и обновлять дополнительные поля в базе данных.
  2. Работа с файлами:

    • Код также включает функциональность для работы с файлами, связанными с дополнительными полями (например, загрузка и перемещение файлов).
  3. Управление значениями полей:

    • Включает обработку различных типов полей, таких как файлы, чекбоксы, текстовые поля и другие.
  4. Хуки для расширяемости:

    • Важной частью кода являются хуки, которые позволяют подключать дополнительные плагины и расширения для обработки файлов и полей.
  5. Кэширование:

    • Используется кэширование для повышения производительности при загрузке и обработке данных о дополнительных полях.

Характеристика стиля PHP:

  • Объектно-ориентированный подход: Используются глобальные объекты для работы с базой данных и кэшированием (например, $db, Cot::$db, Cot::$cache).
  • Использование глобальных переменных: В коде часто применяются глобальные переменные (например, $cot_extrafields), что характерно для старых кодовых баз.
  • Встроенные проверки и валидация: Проверки на существование данных в базе и на корректность данных перед их использованием.
  • Конвенции и соглашения Cotonti: Применяется специфическая структура работы с таблицами и дополнительными полями, что свойственно системе управления контентом Cotonti.

Стиль кодирования также сочетает явное использование комментариев и пояснений, что помогает в понимании работы функций и их взаимодействия с базой данных и файлами.

 

 

/**
 * Extra fields API
 *
 * @package API - Extrafields
 * @copyright (c) Cotonti Team
 * @license https://github.com/Cotonti/Cotonti/blob/master/License.txt
 */
 // API для работы с дополнительными полями // Описание API для дополнительных полей

defined('COT_CODE') or die('Wrong URL'); 
// Проверка, что код был вызван из правильного места

require_once cot_incfile('forms'); 
// Подключение файла с функциями для работы с формами

/**
 * Returns Extra fields edit fields
 *
 * @param string $name Form input name
 * @param array $extrafield Extra field config
 * @param string $data Existing value for extra field
 * @return string
 *
 * @todo use constants for extra field types
 */
 // Функция для генерации полей редактирования дополнительных полей // Комментарий к функции

function cot_build_extrafields($name, $extrafield, $data)
{
	global $L, $R, $cfg, $pl; 
	// Подключение глобальных переменных

	$data = ($data === null) ? $extrafield['field_default'] : $data; 
	// Если значение не передано, используем значение по умолчанию из конфигурации поля

	switch ($extrafield['field_type']) { 
		// В зависимости от типа поля выполняем разные действия
		case 'input': 
		case 'inputint': 
		case 'currency': 
		case 'double':
			$result = cot_inputbox('text', $name, $data, '', $extrafield['field_html']); 
			// Для текстовых полей, числовых, валютных и с плавающей точкой используется стандартное текстовое поле
			break;
		case 'textarea': 
			$result = cot_textarea($name, $data, 4, 56, '', $extrafield['field_html']); 
			// Для текстовых областей используется textarea
			break;
		case 'select': 
			$extrafield['field_variants'] = str_replace([' , ', ', ', ' ,'], ',', $extrafield['field_variants']); 
			// Преобразование вариантов значений в правильный формат
			$opt_array = explode(",", $extrafield['field_variants']); 
			// Разделение строк на массив
			$ii = 0; 
			$options_titles = $options_values = []; 
			// Инициализация массивов для названий и значений вариантов
			foreach ($opt_array as $var) { 
				$ii++; 
				$var = trim($var); 
				$options_titles[$ii] = (!empty($L[$extrafield['field_name'] . '_' . $var])) ? $L[$extrafield['field_name'] . '_' . $var] : $var; 
				// Если есть локализованное название, используем его, иначе оставляем как есть
				$options_values[$ii] = $var; 
				// Добавление значения в список
			}
			$result = cot_selectbox(trim($data), $name, $options_values, $options_titles, false, '', $extrafield['field_html']); 
			// Генерация выпадающего списка
			break;
		case 'radio': 
			$extrafield['field_variants'] = str_replace([' , ', ', ', ' ,'], ',', $extrafield['field_variants']); 
			// Преобразование вариантов значений для радио кнопок
			$opt_array = explode(",", $extrafield['field_variants']); 
			// Разделение на массив
			$options_titles = $options_values = []; 
			// Инициализация массивов для названий и значений вариантов
			if (count($opt_array) > 0) { 
				$ii = 0; 
				foreach ($opt_array as $var) { 
					$ii++; 
					$var = trim($var); 
					$options_titles[$ii] = (!empty($L[$extrafield['field_name'] . '_' . $var])) ? $L[$extrafield['field_name'] . '_' . $var] : $var; 
					// Если есть локализованное название, используем его, иначе оставляем как есть
					$options_values[$ii] = $var; 
					// Добавление значения в список
				}
			}
			$result = cot_radiobox(trim($data), $name, $options_values, $options_titles, '', '', $extrafield['field_html']); 
			// Генерация радиокнопок
			break;
		case 'checkbox': 
			$title = cot_extrafield_title($extrafield); 
			// Получение заголовка для чекбокса
			$result = cot_checkbox($data, $name, $title, '', '1', $extrafield['field_html']); 
			// Генерация чекбокса
			break;
		case 'datetime': 
			global $sys; 
			// Подключение глобальной переменной для системного времени

			$extrafield['field_params'] = str_replace([' , ', ', ', ' ,'], ',', $extrafield['field_params']); 
			// Преобразование параметров поля
			list($min, $max, $format) = explode(",", $extrafield['field_params'], 3); 
			// Разделение на минимальные и максимальные значения, формат
			$max = (int)$max > 0 ? $max : 2030; 
			// Установка максимального значения
			$min =  (int)$min > 0 ? $min : 2000; 
			// Установка минимального значения

			$data = (mb_substr($data, 0, 1) == "+") ? $sys['now'] + (int)(mb_substr($data, 1)) : $data; 
			// Если дата с плюсом, добавляем количество секунд к текущему времени
			$data = (mb_substr($data, 0, 1) == "-") ? $sys['now'] - (int)(mb_substr($data, 1)) : $data; 
			// Если дата с минусом, вычитаем количество секунд из текущего времени

			$result = cot_selectbox_date((int)$data, 'long', $name, (int)$max, (int)$min, true, $extrafield['field_html']); 
			// Генерация селектора даты и времени
			break;
		case 'country': 
			global $cot_countries; 
			// Подключение глобальной переменной стран

			$result = cot_selectbox_countries(trim($data), $name, true, '', $extrafield['field_html']); 
			// Генерация выпадающего списка стран
			break;
		case 'range': 
			$extrafield['field_params'] = str_replace([' , ', ', ', ' ,'], ',', $extrafield['field_params']); 
			// Преобразование параметров диапазона
			list($min, $max) = explode(',',$extrafield['field_params'], 2); 
			// Разделение на минимальное и максимальное значение
			$result = cot_selectbox(trim($data), $name, range((int)$min, (int)$max), range((int)$min, (int)$max), true, '', $extrafield['field_html']); 
			// Генерация выпадающего списка с диапазоном значений
			break;
		case 'checklistbox': 
			$extrafield['field_variants'] = str_replace([' , ', ', ', ' ,'], ',', $extrafield['field_variants']); 
			// Преобразование вариантов значений для чекбоксов
			$opt_array = explode(",", $extrafield['field_variants']); 
			// Разделение на массив
			$options_titles = $options_values = []; 
			// Инициализация массивов для названий и значений вариантов
			if (count($opt_array) > 0) { 
				$ii = 0; 
				foreach ($opt_array as $var) { 
					$ii++; 
					$var = trim($var); 
					$options_titles[$ii] = (!empty($L[$extrafield['field_name'] . '_' . $var])) ? $L[$extrafield['field_name'] . '_' . $var] : $var; 
					// Если есть локализованное название, используем его, иначе оставляем как есть
					$options_values[$ii] = $var; 
					// Добавление значения в список
				}
			}
			if (!is_array($data)) { 
				$data = trim(str_replace([' , ', ', ', ' ,'], ',', $data)); 
				$data = explode(',', $data); 
			}
			$result = cot_checklistbox($data, $name, $options_values, $options_titles, '', '', true, $extrafield['field_html']); 
			// Генерация чеклистбокса
			break;
		case 'file': 
			$extrafield['field_params'] = (!empty($extrafield['field_params'])) ? $extrafield['field_params'] : $cfg['extrafield_files_dir']; 
			// Настройка параметров для поля типа файл
			$extrafield['field_params'] .= (mb_substr($extrafield['field_params'], -1) == '/') ? '' : '/'; 
			// Убедимся, что в пути к файлу есть слэш
			$data_filepath = $extrafield['field_params'] . htmlspecialchars($data); 
			// Полный путь к файлу

			/* === Hook === */ 
			foreach (cot_getextplugins('extrafields.build.file') as $pl) { 
				include $pl; 
			} 
			/* ===== */ 
			$result = cot_filebox($name, htmlspecialchars($data), $data_filepath, 'rdel_' . $name, '', $extrafield['field_html']); 
			// Генерация поля для загрузки файлов
			break;
		default: 
			$result = ''; 
			// В случае неизвестного типа поля возвращаем пустое значение
			break;
	}
	return $result; 
	// Возвращаем результат
}

 

 

/**
 * Импортирует данные дополнительных полей
 *
 * @param string $inputname Имя переменной (или значение для source=D)
 * @param $extrafield Массив с дополнительным полем
 * @param string $source Тип источника: G (GET), P (POST), C (COOKIE) или D (фильтрация переменных)
 * @param string $oldvalue Старое значение дополнительного поля
 * @param string $titlePrefix Префикс для заголовка
 * @return string
 */
function cot_import_extrafields($inputname, $extrafield, $source = 'P', $oldvalue = '', $titlePrefix = '')
{
	global $L;  // Подключаем глобальный массив $L для локализаций (переводов)
    
    // Получаем заголовок для поля
    $exfld_title = cot_extrafield_title($extrafield, $titlePrefix); 

    $import = null; // Инициализируем переменную для хранения импортированного значения
    // Обрабатываем типы полей
    switch ($extrafield['field_type']) {
        case 'input':  // Если тип поля - "input"
            // Если тип обработки текста 'Text', используем 'TXT', иначе 'HTM'
            $import = ($extrafield['field_parse'] == 'Text') ? cot_import($inputname, $source, 'TXT') : cot_import($inputname, $source, 'HTM');
            
            // Проверяем на соответствие регулярному выражению, если оно задано
            if (!empty($extrafield['field_params']) && !is_null($import) && !preg_match($extrafield['field_params'], $import)) {
                // Если не совпало, выводим ошибку
                $errMsg = (isset($L['field_pregmatch_' . $extrafield['field_name']])) ?
                    $L['field_pregmatch_' . $extrafield['field_name']] : $exfld_title.': '.$L['field_pregmatch'];
                cot_error($errMsg, $inputname);  // Функция вывода ошибки
            }
            break;  // Завершаем обработку поля типа "input"
        case 'inputint':  // Если тип поля - "inputint" (целое число)
        case 'range':  // Или тип поля "range" (диапазон)
            // Заменяем пробелы и запятые в параметрах на однообразный формат
            $extrafield['field_params'] = str_replace([' , ', ', ', ' ,'], ',', $extrafield['field_params']);
            
            // Импортируем значение как целое число
            $import = cot_import($inputname, $source, 'INT');

            // Переменные для минимального и максимального значений диапазона
            $min = $max = null;
            
            // Если заданы параметры для диапазона
            if (!empty($extrafield['field_params'])) {
                // Разбиваем параметры на минимальное и максимальное значения
                $tmp = explode(",", $extrafield['field_params'], 2);
                if (isset($tmp[0]) && is_numeric($tmp[0])) {
                    $min = (int)trim($tmp[0]);  // Присваиваем минимальное значение
                }

                if (isset($tmp[1]) && is_numeric($tmp[1])) {
                    $min = (int)trim($tmp[1]);  // Присваиваем максимальное значение
                }

                // Проверяем, что значение в пределах диапазона
                if (!is_null($import)) {
                    if ( (!is_null($min) && ($import < $min)) || (!is_null($max) && ($import > $max)) ) {
                        // Если значение выходит за пределы диапазона, выводим ошибку
                        $errMsg = (isset(Cot::$L['field_range_' . $extrafield['field_name']])) ?
                            Cot::$L['field_range_' . $extrafield['field_name']] : $exfld_title . ': ' . Cot::$L['field_range'];
                        cot_error($errMsg, $inputname);  // Функция вывода ошибки
                    }
                }
            }
            // Если импортированное значение равно null
            if (is_null($import)) {
                // Если поле типа inputint или есть дефолтное значение, присваиваем дефолтное значение
                $import = ($extrafield['field_type'] == 'inputint' || !empty($extrafield['field_default'])) ? (int)$extrafield['field_default'] : '';
                // Проверяем, что значение не выходит за пределы диапазона
                if (is_numeric($import) && !empty($extrafield['field_params'])) {
                    if (!is_null($min) && ($import < $min)) $import = $min;  // Если меньше минимального, присваиваем минимальное
                    if (!is_null($max) && ($import > $max)) $import = $max;  // Если больше максимального, присваиваем максимальное
                }
            }
            break;  // Завершаем обработку поля типа "inputint" или "range"
        case 'currency':  // Если тип поля - "currency" (валюта)
        case 'double':  // Или тип поля "double" (дробное число)
            // Заменяем пробелы и запятые в параметрах на однообразный формат
            $extrafield['field_params'] = str_replace([' , ', ', ', ' ,'], ',', $extrafield['field_params']);
            
            // Импортируем значение как число (тип NUM)
            $import = cot_import($inputname, $source, 'NUM');
            if (!is_null($import)) {
                // Преобразуем в число с плавающей точкой
                $import = (float) $import;
            }

            // Переменные для минимального и максимального значений диапазона
            $min = $max = null;
            // Если заданы параметры для диапазона
            if (!empty($extrafield['field_params'])) {
                // Разбиваем параметры на минимальное и максимальное значения
                $param = explode(",", $extrafield['field_params'], 2);
                if (isset($param[0])) {
                    $min = (float) $param[0];  // Присваиваем минимальное значение
                }
                if (isset($param[1])) {
                    $max = (float) $param[1];  // Присваиваем максимальное значение
                }
            }

            // Проверяем, что значение в пределах диапазона
            if (!is_null($import) && !empty($extrafield['field_params'])) {
                if (($min !== null && ($import < $min)) || ($max !== null && ($import > $max))) {
                    // Если значение выходит за пределы диапазона, выводим ошибку
                    $errMsg = (isset(Cot::$L['field_range_' . $extrafield['field_name']])) ?
                        Cot::$L['field_range_' . $extrafield['field_name']] : $exfld_title . ': ' . Cot::$L['field_range'];
                    cot_error($errMsg, $inputname);  // Функция вывода ошибки
                }
            }

            // Если импортированное значение равно null
            if (is_null($import)) {
                // Если есть дефолтное значение, присваиваем дефолт
                $import =  !empty($extrafield['field_default']) ? (float) $extrafield['field_default'] : 0;
                // Проверяем, что значение не выходит за пределы диапазона
                if (!empty($extrafield['field_params'])) {
                    if ($min !== null && ($import < $min)) {
                        $import = $min;  // Если меньше минимального, присваиваем минимальное
                    }
                    if ($max !== null && ($import > $max)) {
                        $import = $max;  // Если больше максимального, присваиваем максимальное
                    }
                }
            }
            break;  // Завершаем обработку поля типа "currency" или "double"
        case 'textarea':  // Если тип поля - "textarea"
            // Импортируем значение как HTML-текст
            $import = cot_import($inputname, $source, 'HTM');
            break;  // Завершаем обработку поля типа "textarea"
        case 'select':  // Если тип поля - "select" (выпадающий список)
            // Импортируем значение как строку
            $import = cot_import($inputname, $source, 'TXT');
            
            // Если значение не пустое и существуют параметры для выбора
            if (!empty($import) && !empty($extrafield['field_params'])) {
                // Разбиваем параметры на массив значений
                $values = explode(',', $extrafield['field_params']);
                // Если импортированное значение не содержится в списке возможных значений
                if (!in_array($import, $values)) {
                    // Устанавливаем ошибку
                    cot_error($exfld_title . ': ' . Cot::$L['field_notinarray'], $inputname);
                }
            }

            // Если импортированное значение равно null, присваиваем дефолтное значение
            if (is_null($import) && !empty($extrafield['field_default'])) {
                $import = $extrafield['field_default'];
            }
            break;  // Завершаем обработку поля типа "select"
        
        case 'radio':  // Если тип поля - "radio" (переключатель)
            // Импортируем значение как строку
            $import = cot_import($inputname, $source, 'TXT');
            
            // Если значение не пустое и существуют параметры для выбора
            if (!empty($import) && !empty($extrafield['field_params'])) {
                // Разбиваем параметры на массив значений
                $values = explode(',', $extrafield['field_params']);
                // Если импортированное значение не содержится в списке возможных значений
                if (!in_array($import, $values)) {
                    // Устанавливаем ошибку
                    cot_error($exfld_title . ': ' . Cot::$L['field_notinarray'], $inputname);
                }
            }

            // Если импортированное значение равно null, присваиваем дефолтное значение
            if (is_null($import) && !empty($extrafield['field_default'])) {
                $import = $extrafield['field_default'];
            }
            break;  // Завершаем обработку поля типа "radio"
        
        case 'range':  // Если тип поля - "range" (диапазон)
            // Импортируем значение как целое число
            $import = cot_import($inputname, $source, 'INT');
            
            // Если значение не пустое и параметры диапазона заданы
            if (!is_null($import) && !empty($extrafield['field_params'])) {
                // Разбиваем параметры на минимальное и максимальное значения
                $param = explode(',', $extrafield['field_params'], 2);
                $min = isset($param[0]) ? (int)$param[0] : null;  // Присваиваем минимальное значение
                $max = isset($param[1]) ? (int)$param[1] : null;  // Присваиваем максимальное значение
                
                // Проверяем, что значение находится в пределах диапазона
                if ((!is_null($min) && $import < $min) || (!is_null($max) && $import > $max)) {
                    // Если значение выходит за пределы диапазона, выводим ошибку
                    cot_error($exfld_title . ': ' . Cot::$L['field_range'], $inputname);
                }
            }

            // Если импортированное значение равно null
            if (is_null($import)) {
                // Присваиваем дефолтное значение
                $import = !empty($extrafield['field_default']) ? (int)$extrafield['field_default'] : null;
                // Проверяем минимальное и максимальное значения
                if (!is_null($import) && !empty($extrafield['field_params'])) {
                    if (!is_null($min) && $import < $min) {
                        $import = $min;  // Присваиваем минимальное значение
                    }
                    if (!is_null($max) && $import > $max) {
                        $import = $max;  // Присваиваем максимальное значение
                    }
                }
            }
            break;  // Завершаем обработку поля типа "range"
        case 'file':  // Если тип поля - "file" (загрузка файла)
            // Импортируем значение как строку
            $import = cot_import($inputname, $source, 'TXT');
            // Проверяем, что загружаемый файл указан и соответствует параметрам
            if (!empty($import) && !empty($extrafield['field_params'])) {
                // Разбиваем параметры на массив расширений
                $values = explode(',', $extrafield['field_params']);
                // Извлекаем расширение загруженного файла
                $ext = strtolower(pathinfo($import, PATHINFO_EXTENSION));
                // Если расширение файла не указано в списке допустимых
                if (!in_array($ext, $values)) {
                    // Устанавливаем ошибку
                    cot_error($exfld_title . ': ' . Cot::$L['field_fileext'], $inputname);
                }
            }
            break;  // Завершаем обработку поля типа "file"

        case 'checklistbox':  // Если тип поля - "checklistbox" (список с возможностью выбора нескольких элементов)
            // Импортируем значение как массив
            $import = cot_import($inputname, $source, 'ARR');
            // Проверяем, что параметры для списка заданы
            if (!empty($extrafield['field_params'])) {
                // Разбиваем параметры на массив допустимых значений
                $values = explode(',', $extrafield['field_params']);
                // Если есть выбранные элементы
                if (!empty($import)) {
                    // Проходим по каждому выбранному элементу
                    foreach ($import as $value) {
                        // Если значение не содержится в списке допустимых
                        if (!in_array($value, $values)) {
                            // Устанавливаем ошибку
                            cot_error($exfld_title . ': ' . Cot::$L['field_notinarray'], $inputname);
                            break;  // Прекращаем дальнейшую проверку
                        }
                    }
                }
            }
            // Если импортируемое значение отсутствует, присваиваем значение по умолчанию
            if (empty($import) && !empty($extrafield['field_default'])) {
                $import = explode(',', $extrafield['field_default']);  // Преобразуем значение по умолчанию в массив
            }
            break;  // Завершаем обработку поля типа "checklistbox"

        default:  // Если тип поля не распознан
            // Импортируем значение как строку по умолчанию
            $import = cot_import($inputname, $source, 'TXT');
            break;  // Завершаем выполнение
    }

    // Возвращаем результат импорта
    return $import;  // Возвращаем обработанное значение поля
}

 

/**
 * Заголовок для дополнительного поля
 *
 * @param array  $extrafield  Массив с информацией о дополнительном поле
 * @param string $titlePrefix Префикс для заголовка
 * @return string             Заголовок поля
 */
function cot_extrafield_title($extrafield, $titlePrefix = '')
{
    // Изначально устанавливаем описание поля в качестве заголовка
    $title = $extrafield['field_description'];  // Устанавливаем описание поля как базовый заголовок

    $fieldLocation = '';  // Инициализируем переменную для хранения расположения поля
    if (isset($extrafield['field_location'])) $fieldLocation = $extrafield['field_location'];  
    // Если поле имеет указанное расположение, сохраняем его в переменную

    // Проверяем наличие заголовка с использованием префикса
    if ($titlePrefix != '' && isset(Cot::$L[$titlePrefix.$extrafield['field_name'].'_title'])) {
        $title = Cot::$L[$titlePrefix.$extrafield['field_name'].'_title'];  
        // Используем локализованный заголовок с указанным префиксом
    } 
    // Проверяем наличие заголовка с учётом расположения поля
    elseif ($fieldLocation != '' && isset(Cot::$L[$fieldLocation.'_'.$extrafield['field_name'].'_title'])) {
        $title = Cot::$L[$fieldLocation.'_'.$extrafield['field_name'].'_title'];  
        // Используем локализованный заголовок с учётом расположения
    } 
    // Проверяем наличие общего заголовка для поля
    elseif (isset(Cot::$L[$extrafield['field_name'].'_title'])) {
        $title = Cot::$L[$extrafield['field_name'].'_title'];  
        // Используем общий локализованный заголовок поля
    }

    // Если заголовок пустой, устанавливаем имя поля в качестве заголовка
    if ($title == '') $title = $extrafield['field_name'];  // Устанавливаем имя поля как заголовок по умолчанию

    return $title;  // Возвращаем итоговый заголовок
}

Этот код определяет функцию для получения заголовка дополнительного поля. Она проверяет наличие локализованных строк на основе заданных условий (префикса, расположения и имени поля). Если ни одно условие не выполняется, используется имя поля.

 

/**
 * Возвращает данные дополнительных полей
 *
 * @param string $name Название строки локализации
 * @param array $extrafield Данные дополнительного поля
 * @param string $value Существующее значение пользователя
 * @param string $parser Парсер, который используется (если не указан, берётся стандартный)
 * @return string Обработанное значение
 */
function cot_build_extrafields_data($name, $extrafield, $value, $parser = '')
{
    global $L;  // Подключаем глобальную переменную локализации

    $parse_type = ['HTML', 'Text'];  // Определяем типы парсинга

    // Выполняем действия в зависимости от типа дополнительного поля
    switch ($extrafield['field_type'])
    {
        // Для полей типа select и radio
        case 'select':
        case 'radio':
            if ($value === null || $value === '') {  // Проверяем, что значение не пустое
                return '';  // Возвращаем пустую строку, если значение отсутствует
            }
            $value = htmlspecialchars($value);  // Преобразуем специальные символы для предотвращения XSS
            return (!empty($L[$extrafield['field_name'] . '_' . $value])) ? $L[$extrafield['field_name'] . '_' . $value] : $value;
            // Если есть локализация для значения, возвращаем её, иначе возвращаем само значение
            break;

        // Для поля типа checkbox
        case 'checkbox':
            $value = ($value) ? 1 : 0;  // Преобразуем значение в 1 или 0
            return $value;  // Возвращаем обработанное значение
            break;

        // Для поля типа datetime
        case 'datetime':
            $extrafield['field_params'] = str_replace([' , ', ', ', ' ,'], ',', $extrafield['field_params']);
            // Убираем лишние пробелы вокруг запятых в параметрах
            list($min, $max, $format) = explode(",", $extrafield['field_params'], 3);
            // Разбиваем параметры на минимальное, максимальное значение и формат даты
            return (empty($format)) ? $value : cot_date($format, $value);
            // Если формат даты не указан, возвращаем значение, иначе форматируем его
            break;

        // Для поля типа checklistbox
        case 'checklistbox':
            if ($value === null || $value === '') {  // Проверяем, что значение не пустое
                return '';  // Возвращаем пустую строку, если значение отсутствует
            }
            $value = htmlspecialchars($value);  // Преобразуем специальные символы
            $value = trim(str_replace([' , ', ', ', ' ,'], ',', $value));
            // Убираем лишние пробелы вокруг запятых и преобразуем в строку
            $value = explode(',', $value);  // Преобразуем строку в массив
            $sep = (!empty($extrafield['field_params'])) ? $extrafield['field_params'] : ', ';
            // Используем разделитель из параметров, если он указан, иначе запятая с пробелом
            $result = '';  // Инициализируем переменную для результата
            $i = 0;  // Счётчик для разделения значений
            if (is_array($value)) {  // Проверяем, является ли значение массивом
                foreach($value as $k => $v) {  // Перебираем значения массива
                    if ($i != 0) {  // Если это не первое значение
                        $result .= $sep;  // Добавляем разделитель
                    }
                    $i++;  // Увеличиваем счётчик
                    $result .= (!empty($L[$extrafield['field_name'] . '_' . $v])) ? $L[$extrafield['field_name'] . '_' . $v] : $v;
                    // Если есть локализация для значения, добавляем её, иначе добавляем само значение
                }
            }
            return $result;  // Возвращаем итоговый результат
            break;

        // Для полей типа country, file и filesize
        case 'country':
        case 'file':
        case 'filesize':
            $value = (is_null($value)) ? '' : $value;  // Если значение равно null, возвращаем пустую строку
            return $value;  // Возвращаем обработанное значение
            break;

        // Для текстовых, числовых и других типов полей
        case 'input':
        case 'inputint':
        case 'currency':
        case 'double':
        case 'textarea':
        case 'range':
        default:
            if ($value === null || $value === '') {  // Проверяем, что значение не пустое
                return '';  // Возвращаем пустую строку, если значение отсутствует
            }
            $value = cot_parse($value, ($extrafield['field_parse'] == 'Text') ? false : true, $parser);
            // Выполняем парсинг значения. Если поле настроено как текстовое, отключаем HTML-парсер
            return $value;  // Возвращаем обработанное значение
            break;
    }
}

Этот код обрабатывает значения дополнительных полей в зависимости от их типа. Для каждого типа поля применяются разные проверки и преобразования. Если значение отсутствует, возвращается пустая строка.

 

/**
 * Дополнительные поля - возвращает стандартную HTML-конструкцию для различных типов полей (без атрибутов value и name)
 *
 * @access private
 * @param string $type Тип поля (input, textarea и т.д.)
 * @return string HTML-конструкция
 */
function cot_default_html_construction($type)
{
    include Cot::$cfg['system_dir'] . '/resources.rc.php';  // Подключаем файл ресурсов системы

    // Файл ресурсов темы может использовать файл языка темы
    // Нет необходимости загружать эти значения глобально, чтобы не перезаписать уже загруженные значения
    $langFile = Cot::$cfg['themes_dir'] . '/' . Cot::$cfg['defaulttheme'] . '/' . Cot::$cfg['defaulttheme'] . '.' .
        Cot::$cfg['defaultlang'] . '.' . 'lang.php';  // Формируем путь к языковому файлу темы
    if (!file_exists($langFile)) {  // Если файл для текущего языка не найден
        $langFile = Cot::$cfg['themes_dir'] . '/' . Cot::$cfg['defaulttheme'] . '/' . Cot::$cfg['defaulttheme'] .
            '.en.lang.php';  // Используем файл языка по умолчанию (английский)
    }
    if (file_exists($langFile)) {  // Если языковой файл существует
        include $langFile;  // Подключаем его
    }

    $resourceFile = Cot::$cfg['themes_dir'] . '/' . Cot::$cfg['defaulttheme'] . '/' . Cot::$cfg['defaulttheme'] .
        '.php';  // Формируем путь к файлу ресурсов темы
    if (file_exists($resourceFile)) {  // Если файл ресурсов существует
        include $resourceFile;  // Подключаем его
    }

    $html = '';  // Инициализируем переменную для HTML-кода
    switch ($type) {  // В зависимости от типа поля
        case 'input':
        case 'inputint':
        case 'currency':
        case 'double':
            $html = $R['input_text'];  // Получаем HTML-конструкцию для текстового ввода
            $html = str_replace('{$attrs}', '{$attrs} maxlength="255"', $html);  // Добавляем ограничение на длину текста
            break;
        case 'textarea':
            $html = $R['input_textarea'];  // Получаем HTML-конструкцию для текстовой области
            break;
        case 'country':
        case 'select':
        case 'range':
            $html = $R['input_select'];  // Получаем HTML-конструкцию для выпадающего списка
            break;
        case 'checkbox':
            $html = $R['input_checkbox'];  // Получаем HTML-конструкцию для флажка
            break;
        case 'checklistbox':
            $html = $R['input_check'];  // Получаем HTML-конструкцию для списка с флажками
            break;
        case 'radio':
            $html = $R['input_radio'];  // Получаем HTML-конструкцию для радио-кнопок
            break;
        case 'datetime':
            $html = $R['input_date'];  // Получаем HTML-конструкцию для ввода даты
            break;
        case 'file':
            $html = $R['input_filebox'] . '|' . $R['input_filebox_empty'];  // Конструкция для загрузки файла
            break;
        case 'filesize':
            $html = '';  // Для размера файла конструкция не используется
            break;
    }

    $html = str_replace('{$attrs}', '', $html);  // Убираем placeholder {$attrs}, если он не был заменён

    return $html;  // Возвращаем готовую HTML-конструкцию
}

Этот код возвращает базовую HTML-конструкцию для разных типов дополнительных полей в зависимости от их типа. Конструкции определяются в файле ресурсов темы и зависят от текущих настроек темы и языка. Для некоторых полей добавляются дополнительные атрибуты, такие как maxlength для текстового ввода. Если тип поля не поддерживается, возвращается пустая строка.

 

 

/**
 * Добавляет дополнительное поле для страниц
 *
 * @param string $location Таблица для добавления дополнительного поля
 * @param string $name Название поля (уникальное)
 * @param string $type Тип поля (input, textarea и т.д.)
 * @param string $html Строка HTML-ресурса
 * @param string $variants Варианты значений (для радиокнопок, селекторов и т.д.)
 * @param string $default Значение по умолчанию
 * @param bool $required Поле обязательно для заполнения
 * @param string $parse Тип парсинга (HTML, BBCodes)
 * @param string $description Описание поля (опционально, для администратора)
 * @param string $params Параметры (для радиокнопок, селекторов и т.д.)
 * @param string $enabled Активность поля
 * @param bool $noalter Не изменять таблицу, только зарегистрировать поле
 * @param string $customtype Изменить тип SQL, размер, значение по умолчанию
 * @return bool Успешность добавления поля
 *
 * @global CotDB $db
 */
function cot_extrafield_add($location, $name, $type, $html = '', $variants = '', $default = '', $required = false,
                $parse = 'HTML', $description = '', $params = '', $enabled = 1, $noalter = false, $customtype = '')
{
    global $db, $db_extra_fields;

    // Проверка корректности имени поля
    $checkname = cot_import($name, 'D', 'ALP'); // Импортируем имя поля
    $checkname = str_replace(['-', '.'], ['', ''], $checkname); // Удаляем запрещённые символы
    if ($checkname != $name) { // Если имя некорректное
        return false;
    }

    // Проверка существования поля в таблице или среди зарегистрированных дополнительных полей
    if (
        Cot::$db->query("SELECT field_name FROM $db_extra_fields WHERE field_name = '$name' AND field_location='$location'")->rowCount() > 0 // Проверяем существование в доп. полях
        || (Cot::$db->query("SHOW COLUMNS FROM $location WHERE SUBSTR(Field, INSTR(Field, '_') + 1) = '$name'")->rowCount() > 0 && !$noalter) // Проверяем существование в таблице
    ) {
        return false; // Поле уже существует
    }

    $fieldsres = Cot::$db->query("SHOW COLUMNS FROM $location"); // Получаем список столбцов таблицы
    $prefixFound = false; // Флаг нахождения префикса столбцов
    while ($fieldrow = $fieldsres->fetch()) { // Перебираем столбцы
        $column = $fieldrow['Field']; // Название столбца
        if (!$prefixFound) { // Если префикс ещё не найден
            $column_prefix = substr($column, 0, strpos($column, "_")); // Определяем префикс
            $fieldName = $column;
            if (!empty($column_prefix)) $fieldName = str_replace($column_prefix . '_', '', $column); // Убираем префикс
            if ($fieldName == 'id' || mb_strtolower($fieldrow['Key']) == 'pri') $prefixFound = true; // Префикс найден
        }

        preg_match("#.*?_$name$#", $column, $match); // Проверяем совпадение имени поля
        if (isset($match[1]) && $match[1] != "" && !$noalter) {
            return false; // Поле уже существует
        }
    }

    $fieldsres->closeCursor(); // Закрываем курсор запроса

    // Формируем данные для регистрации дополнительного поля
    $extf['field_location'] = $location;
    $extf['field_name'] = $name;
    $extf['field_type'] = $type;
    $extf['field_html'] = (!empty($html)) ? $html : cot_default_html_construction($type); // Используем HTML-конструкцию по умолчанию
    $extf['field_variants'] = is_null($variants) ? '' : $variants; // Варианты значений
    $extf['field_params'] = is_null($params) ? '' : $params; // Параметры
    $extf['field_default'] = is_null($default) ? '' : $default; // Значение по умолчанию
    $extf['field_required'] = $required ? 1 : 0; // Обязательное поле
    $extf['field_parse'] = is_null($parse) ? 'HTML' : $parse; // Тип парсинга
    $extf['field_enabled'] = ($enabled > 0) ? 1 : 0; // Включено
    $extf['field_description'] = is_null($description) ? '' : $description; // Описание

    $step1 = $db->insert($db_extra_fields, $extf) == 1; // Вставляем данные в таблицу дополнительных полей
    if ($step1) cot_log("Add extrafield '" . $name . "' in list table '" . $location . "'", 'adm', 'extrafield', 'add'); // Логируем добавление
    if ($noalter) { // Если не требуется изменять структуру таблицы
        return $step1;
    }

    // Определяем тип SQL-столбца в зависимости от типа поля
    switch ($type) {
        case 'select':
        case 'radio':
        case 'range':
        case 'file':
        case 'input':
            $sqltype = "VARCHAR(255) DEFAULT ''"; // Поле VARCHAR
            break;
        case 'inputint':
            $sqltype = "int DEFAULT '0'"; // Поле INT
            break;
        case 'currency':
            $sqltype = "DOUBLE(13,2) DEFAULT '0'"; // Поле DOUBLE с фиксированной точностью
            break;
        case 'double':
            $sqltype = "DOUBLE DEFAULT '0'"; // Поле DOUBLE
            break;
        case 'checklistbox':
        case 'textarea':
            $sqltype = "TEXT"; // Поле TEXT
            break;
        case 'checkbox':
            $sqltype = 'TINYINT UNSIGNED'; // Поле для чекбокса
            break;
        case 'datetime':
            $sqltype = "int DEFAULT '0'"; // Поле для даты
            break;
        case 'country':
            $sqltype = "CHAR(2)"; // Поле для кода страны
            break;
        case 'filesize':
            $sqltype = "int NOT NULL"; // Поле для размера файла
            break;
    }
    if (!empty($customtype)) { // Если задан пользовательский тип
        $sqltype = $customtype; // Используем его
    }
    $fieldName = $name;
    if ($column_prefix != '') { // Добавляем префикс, если он есть
        $fieldName = $column_prefix . '_' . $name;
    }
    $step2 = Cot::$db->query("ALTER TABLE $location ADD $fieldName $sqltype "); // Добавляем столбец в таблицу
    if ($step2) {
        cot_log(
            "Add extrafield '" . $name . "' in DB table '" . $location . "'",
            'adm', 'extrafield',
            'add'
        ); // Логируем изменение структуры таблицы
    }

    if ($step1 || $step2) {
        Cot::$cache && Cot::$cache->db->remove('cot_extrafields', 'system'); // Очищаем кэш
    }

    return $step1 && $step2; // Возвращаем успех, если оба шага выполнены
}

Этот код добавляет новое поле в таблицу базы данных и регистрирует его как дополнительное поле в системе Cotonti. Он проверяет корректность имени, наличие поля в таблице и поддерживает настройку типа SQL-столбца. Также учитываются случаи, когда изменение структуры таблицы не требуется.

 

 

/**
 * Update extra field for pages
 *
 * @param string $location Table contains extrafield // Таблица, содержащая дополнительное поле
 * @param string $oldname Exist name of field // Текущее имя поля
 * @param string $name Field name (unique) // Новое имя поля
 * @param string $html HTML Resource string // HTML-код для рендера поля
 * @param string $variants Variants of values (for radiobuttons, selectors etc) // Варианты значений
 * @param string $default Default value // Значение по умолчанию
 * @param bool $required Required field // Поле обязательное
 * @param string $parse Parsing Type (HTML, BBCodes) // Тип парсинга значения поля
 * @param string $description Description of field (optional, for admin) // Описание поля для администратора
 * @param string $params Params (for radiobuttons, selectors etc) // Дополнительные параметры
 * @param string $enabled Enable field // Включение поля
 * @param string $customtype Modify sql type, size, default // Пользовательский SQL-тип
 * @return bool // Возвращает результат обновления поля
 *
 * @global CotDB $db // Глобальный объект базы данных
 */
function cot_extrafield_update($location, $oldname, $name, $type, $html='', $variants='', $default='', $required=0, $parse='HTML', $description='', $params = '', $enabled = 1, $customtype = '')
{
    global $db, $db_extra_fields;

    // Импортируем имя поля, проверяем на корректность
    $checkname = cot_import($name, 'D', 'ALP'); // Импортирует и фильтрует имя поля
    $checkname = str_replace(['-', '.'], ['', ''], $checkname); // Убирает запрещённые символы
    if ($checkname != $name) {
        return false; // Если имя поля некорректное, прерываем выполнение
    }

    // Проверяем, существует ли указанное поле в таблице `db_extra_fields`
    $fieldsres = $db->query("SELECT * FROM $db_extra_fields WHERE field_name = '$oldname' AND field_location='$location'");
    if ($fieldsres->rowCount() <= 0 || $name != $oldname && $db->query("SHOW COLUMNS FROM $location WHERE SUBSTR(Field, INSTR(Field, '_') + 1) = '$name'")->rowCount() > 0) {
        return false; // Если поле отсутствует или новое имя уже занято, прерываем выполнение
    }

    // Получаем информацию о поле
    $field = $fieldsres->fetch(); // Извлекаем строку из результатов
    $fieldsres->closeCursor(); // Освобождаем ресурсы запроса

    // Получаем список всех колонок таблицы
    $fieldsres = $db->query("SHOW COLUMNS FROM $location");
    $fieldrow = $fieldsres->fetch(); // Извлекаем первую строку
    $fieldsres->closeCursor();
    $column = $fieldrow['Field']; // Имя первой колонки
    $column_prefix = substr($column, 0, strpos($column, "_")); // Извлекаем префикс колонки

    // Проверяем, требуется ли обновление структуры таблицы
    $alter = false;
    if ($name != $field['field_name']) { // Проверяем, изменилось ли имя поля
        $extf['field_name'] = $name;
        $alter = true; // Устанавливаем флаг изменения структуры
    }
    if ($type != $field['field_type'] && empty($customtype)) { // Проверяем, изменился ли тип поля
        $extf['field_type'] = $type;
        $alter = true; // Устанавливаем флаг изменения структуры
    }

    // Обновляем параметры поля
    $extf['field_html'] = (!empty($html) && $type == $field['field_type']) ? $html : cot_default_html_construction($type); // HTML-код поля
    $extf['field_parse'] = is_null($parse) ? 'HTML' : $parse; // Тип парсинга
    $extf['field_variants'] = is_null($variants) ? '' : $variants; // Варианты значений
    $extf['field_params'] = is_null($params) ? '' : $params; // Параметры
    $extf['field_default'] = is_null($default) ? '' : $default; // Значение по умолчанию
    $extf['field_required'] = ($required > 0) ? 1 : 0; // Флаг обязательного поля
    $extf['field_description'] = is_null($description) ? '' : $description; // Описание поля
    $extf['field_enabled'] = ($enabled > 0) ? 1 : 0; // Включение поля

    // Обновляем запись в `db_extra_fields`
    $step1 = $db->update($db_extra_fields, $extf, "field_name = '$oldname' AND field_location='$location'") == 1; // Выполняем запрос на обновление
    if ($step1) cot_log("Updated extrafield '" . $oldname . "' in list table '" . $location . "'", 'adm', 'extrafield', 'update'); // Логируем обновление

    if (!$alter) { // Если структура не изменялась, выходим
        $step1 = $step1 ? $step1 : 2; // Устанавливаем результат выполнения
        return $step1;
    }

    // Определяем SQL-тип в зависимости от типа поля
    switch ($type) {
        case 'select':
        case 'radio':
        case 'range':
        case 'file':
        case 'input': $sqltype = "VARCHAR(255) DEFAULT ''"; break;
        case 'inputint': $sqltype = "int DEFAULT 0"; break;
        case 'currency': $sqltype = "DOUBLE(13,2) DEFAULT 0"; break;
        case 'double': $sqltype = "DOUBLE DEFAULT 0"; break;
        case 'checklistbox':
        case 'textarea': $sqltype = "TEXT"; break;
        case 'checkbox': $sqltype = 'TINYINT(1) UNSIGNED'; break;
        case 'datetime': $sqltype = "int DEFAULT 0"; break;
        case 'country': $sqltype = "CHAR(2)"; break;
        case 'filesize': $sqltype = "int NOT NULL"; break;
    }
    if (!empty($customtype)) { // Если указан пользовательский SQL-тип
        $sqltype = $customtype;
    }

    // Обновляем имя поля в таблице базы данных
    if ($column_prefix != '') {
        $oldname = $column_prefix.'_'.$oldname;
        $name = $column_prefix.'_'.$name;
    }
    $sql = "ALTER TABLE $location CHANGE $oldname $name $sqltype "; // SQL для изменения структуры
    $step2 = $db->query($sql); // Выполняем запрос
    if ($step2) cot_log("Updated extrafield '" . $name . "' in DB table '" . $location . "'", 'adm', 'extrafield', 'update'); // Логируем изменение структуры

    return $step1 && $step2; // Возвращаем результат
}

Функция cot_extrafield_update

Эта функция обновляет существующее дополнительное поле (extrafield) в указанной таблице базы данных Cotonti.


 

Функция cot_extrafield_remove

Эта функция удаляет дополнительное поле (extrafield) из базы данных и таблицы Cotonti.

/**
 * Delete extra field
 *
 * @param string $location Table contains extrafield // Таблица, содержащая дополнительное поле
 * @param string $name Name of extra field // Имя дополнительного поля
 * @return bool // Возвращает результат удаления
 *
 * @global CotDB $db // Глобальный объект базы данных
 */
function cot_extrafield_remove($location, $name)
{
    global $db, $db_extra_fields;

    // Проверяем, существует ли указанное поле в таблице дополнительных полей
    if ((int) $db->query("SELECT COUNT(*) FROM $db_extra_fields WHERE field_name = '$name' AND field_location='$location'")->fetchColumn() <= 0) {
        // Если поле не найдено, прерываем выполнение
        return false;
    }

    // Получаем информацию о колонках таблицы
    $fieldsres = $db->query("SHOW COLUMNS FROM $location");
    $fieldrow = $fieldsres->fetch(); // Извлекаем первую строку результата
    $fieldsres->closeCursor(); // Закрываем курсор
    $column = $fieldrow['Field']; // Имя первой колонки
    $column_prefix = substr($column, 0, strpos($column, "_")); // Извлекаем префикс колонки

    // Удаляем запись о дополнительном поле из таблицы `db_extra_fields`
    $step1 = $db->delete($db_extra_fields, "field_name = '$name' AND field_location='$location'") == 1; // Удаляем запись
    if ($step1) {
        // Логируем удаление поля
        cot_log("Deleted extrafield '" . $name . "' from list table '" . $location . "'", 'adm', 'extrafield', 'delete');
    }

    $step2 = true; // По умолчанию считаем, что структура таблицы не менялась
    $tmp = $name; // Сохраняем имя поля во временной переменной
    if ($column_prefix != '') {
        $tmp = '_' . $name; // Добавляем префикс, если он есть
    }

    // Проверяем, существует ли колонка с таким именем в таблице
    if (Cot::$db->query("SHOW COLUMNS FROM $location LIKE '%{$tmp}'")->rowCount() > 0) {
        // Если колонка существует, формируем полное имя с префиксом
        if ($column_prefix != '') {
            $name = $column_prefix . "_" . $name;
        }

        // Удаляем колонку из таблицы
        $step2 = Cot::$db->query("ALTER TABLE $location DROP " . $name);
        if ($step2) {
            // Логируем удаление колонки из таблицы
            cot_log(
                "Deleted extrafield '" . $name . "' from DB table '" . $location . "'",
                'adm', 'extrafield',
                'delete'
            );
        }
    }

    // Очищаем кеш для системы, если изменения были произведены
    if ($step1 || $step2) {
        Cot::$cache && Cot::$cache->db->remove('cot_extrafields', 'system');
    }

    // Возвращаем результат: оба шага должны быть успешными
    return $step1 && $step2;
}

Пояснения:

  1. Проверка наличия поля:

    • Используется запрос SELECT COUNT(*) для проверки, существует ли поле в таблице db_extra_fields.
    • Если поле отсутствует, функция сразу возвращает false.
  2. Работа с префиксом:

    • Колонки в таблицах Cotonti часто имеют префиксы. Например, если таблица содержит поля с именами вида page_extra1, то префикс — это page.
    • Префикс извлекается из имени первой колонки таблицы.
  3. Удаление записи о поле:

    • В первой части удаляется запись о поле из системной таблицы db_extra_fields.
  4. Удаление колонки из таблицы:

    • Проверяется, существует ли колонка в указанной таблице. Если существует, формируется запрос на удаление колонки.
  5. Очистка кеша:

    • После успешного удаления поля из базы и структуры таблицы очищается кеш для обновления данных.
  6. Логирование:

    • Все изменения записываются в журнал через функцию cot_log.

Функция обеспечивает надежное удаление дополнительного поля как из системной таблицы, так и из структуры базы данных, с учетом всех особенностей Cotonti.


 

Функция cot_extrafields_register_table

Эта функция регистрирует таблицу в реестре дополнительных полей (extrafields) Cotonti.

/**
 * Registers a table in extrafields registry
 * @param string $table_name Unprefixed table name // Имя таблицы без префикса
 */
function cot_extrafields_register_table($table_name)
{
    // Проверяем, зарегистрирована ли таблица в глобальном массиве $extrafields
    if (!isset(Cot::$extrafields[Cot::$db->{$table_name}])) { 
        // Если таблица еще не зарегистрирована, инициализируем её пустым массивом
        Cot::$extrafields[Cot::$db->{$table_name}] = [];
    }
}

 

Пояснения:

  1. Аргумент функции:

    • $table_name — это имя таблицы, передаваемое без префикса. Например, если в базе данных таблица называется cot_pages, то передается только pages.
  2. Проверка регистрации:

    • Cot::$extrafields — это глобальный массив, в котором хранятся зарегистрированные таблицы и их дополнительные поля.
    • Cot::$db->{$table_name} возвращает полное имя таблицы с учетом префикса, заданного в конфигурации (например, cot_pages для таблицы pages).
  3. Инициализация:

    • Если таблица еще не зарегистрирована в массиве Cot::$extrafields, создается новая запись с ключом — именем таблицы и значением — пустым массивом. Это позволяет в дальнейшем добавлять в эту таблицу новые дополнительные поля.
  4. Пример использования:

    cot_extrafields_register_table('pages'); // Регистрирует таблицу cot_pages

Функция минимальна, но выполняет важную задачу — обеспечивает возможность динамически регистрировать таблицы для работы с дополнительными полями.

 


Функция cot_import_filesarray

Эта функция преобразует структуру массива данных загружаемых файлов из стандартного формата $_FILES['field']['key']['index'] в более удобный формат $array['index']['key'].

/**
 * Преобразует структуру данных загружаемых файлов из:
 * $_FILES['field']['key']['index']
 * в более удобный формат:
 * $array['index']['key']
 *
 * @param array $file_post Имя ключа из массива $_FILES
 * @return array|null Преобразованный массив или null, если входной массив пустой
 */
function cot_import_filesarray($file_post)
{
	// Получаем данные из массива $_FILES по переданному ключу
	$file_post = $_FILES[$file_post]; // Присваиваем данные загружаемых файлов в переменную
    if (empty($file_post)) return null; // Если данных нет, возвращаем null

	$file_arr = []; // Инициализируем пустой массив для преобразования
	$file_keys = array_keys($file_post); // Получаем список ключей массива $_FILES (например, 'name', 'type', 'tmp_name', 'error', 'size')

	// Перебираем каждый файл по имени (индексу)
	foreach ($file_post['name'] as $name => $value) {
		// Для каждого ключа (например, 'name', 'type') добавляем значение в новый формат
		foreach ($file_keys as $key) {
			$file_arr[$name][$key] = $file_post[$key][$name]; // Заполняем новый массив, меняя структуру
		}
	}

	return $file_arr; // Возвращаем преобразованный массив
}

Пояснения:

Изначальная структура массива: В PHP массив $_FILES при загрузке нескольких файлов имеет такую структуру:
 
 
$_FILES = [
    'field_name' => [
        'name' => ['file1.jpg', 'file2.jpg'],
        'type' => ['image/jpeg', 'image/jpeg'],
        'tmp_name' => ['/tmp/phpYzdqkD', '/tmp/php1234'],
        'error' => [0, 0],
        'size' => [12345, 67890]
    ]
];

 

Цель преобразования: Функция преобразует данные в более удобный для обработки формат:
 
 
$file_arr = [
    0 => [
        'name' => 'file1.jpg',
        'type' => 'image/jpeg',
        'tmp_name' => '/tmp/phpYzdqkD',
        'error' => 0,
        'size' => 12345
    ],
    1 => [
        'name' => 'file2.jpg',
        'type' => 'image/jpeg',
        'tmp_name' => '/tmp/php1234',
        'error' => 0,
        'size' => 67890
    ]
];

 

Основная логика:

Получаем ключи массива $_FILES (name, type, tmp_name, error, size).
Перебираем массив $_FILES['name'], где каждый индекс соответствует одному файлу.
Заполняем новый массив $file_arr, используя текущий индекс для группировки данных каждого файла.
Проверка на пустой массив: Если данные в $_FILES по указанному ключу отсутствуют, возвращается null.

Пример использования:


$_FILES = [
    'upload' => [
        'name' => ['file1.jpg', 'file2.jpg'],
        'type' => ['image/jpeg', 'image/jpeg'],
        'tmp_name' => ['/tmp/phpYzdqkD', '/tmp/php1234'],
        'error' => [0, 0],
        'size' => [12345, 67890]
    ]
];

$files = cot_import_filesarray('upload');
print_r($files);


Результат:
 
Array
(
    [0] => Array
        (
            [name] => file1.jpg
            [type] => image/jpeg
            [tmp_name] => /tmp/phpYzdqkD
            [error] => 0
            [size] => 12345
        )

    [1] => Array
        (
            [name] => file2.jpg
            [type] => image/jpeg
            [tmp_name] => /tmp/php1234
            [error] => 0
            [size] => 67890
        )
)

 


 

Функция cot_extrafield_movefiles

Эта функция перемещает загруженные файлы из временной директории в новое место, а также удаляет старые файлы, если они существуют.

/**
 * Перемещает файлы и удаляет старые файлы в массиве $uploadfiles
 */
function cot_extrafield_movefiles()
{
	global $uploadfiles, $cfg, $pl; // Подключаем глобальные переменные для работы с файлами и плагинами

	// Проверяем, является ли $uploadfiles массивом
	if (is_array($uploadfiles)) {
		// Перебираем все файлы в массиве $uploadfiles
		foreach ($uploadfiles as $uploadfile) {
			/* === Hook === */
			// Подключаем плагины для обработки файлов
			foreach (cot_getextplugins('extrafields.movefiles') as $pl) {
				include $pl; // Включаем каждый плагин из списка
			}
			/* ===== */

			// Если существует старый файл (old) и он реально существует в файловой системе
			if (!empty($uploadfile['old']) && file_exists($uploadfile['old'])) {
				@unlink($uploadfile['old']); // Удаляем старый файл
			}

			// Если существует временный файл (tmp) и новый путь (new)
			if (!empty($uploadfile['tmp']) && !empty($uploadfile['new'])) {
				@move_uploaded_file($uploadfile['tmp'], $uploadfile['new']); // Перемещаем файл из временной директории в новое место
			}
		}
	}
}

Пояснения:

  1. Глобальные переменные:

    • $uploadfiles: Массив, содержащий информацию о загруженных файлах, например, временные файлы и их новые пути.
    • $cfg, $pl: Глобальные переменные, подключаемые для работы с конфигурацией и плагинами.
  2. Перебор файлов: Функция проверяет, что переменная $uploadfiles является массивом, затем перебирает все элементы массива (каждый элемент — это информация о загруженном файле).

  3. Обработка плагинов: Через хуки (cot_getextplugins('extrafields.movefiles')) функция вызывает внешние плагины для дополнительной обработки файлов, например, для проверки или модификации файлов перед их перемещением.

  4. Удаление старых файлов: Если старый файл существует (путь в $uploadfile['old'] указан), он удаляется с помощью @unlink. Оператор @ подавляет возможные ошибки (например, если файл не найден).

  5. Перемещение временных файлов: Если файл существует в временном месте ($uploadfile['tmp']) и имеется новый путь для его сохранения ($uploadfile['new']), файл перемещается с помощью move_uploaded_file. Это безопасный способ перемещения загруженных файлов.

 

Пример использования:

Если в $uploadfiles хранится информация о загруженных файлах:

$uploadfiles = [
    [
        'old' => '/path/to/old/file1.jpg',
        'tmp' => '/tmp/phpYzdqkD',
        'new' => '/path/to/new/file1.jpg'
    ],
    [
        'old' => '/path/to/old/file2.jpg',
        'tmp' => '/tmp/php1234',
        'new' => '/path/to/new/file2.jpg'
    ]
];

cot_extrafield_movefiles();


Старые файлы, указанные в old, будут удалены.
Временные файлы, указанные в tmp, будут перемещены в новые директории, указанные в new.


 

Функция cot_extrafield_unlinkfiles

Эта функция удаляет файлы, связанные с дополнительными полями типа "file", из заданной директории. Она проверяет тип поля, строит путь к файлу и удаляет его, если файл существует.

/**
 * Удаляет файлы в массиве extrafield
 * @param string $fielddata Данные поля
 * @param array $extrafield Данные о дополнительных полях
 */
function cot_extrafield_unlinkfiles($fielddata, $extrafield)
{
	global $cfg, $pl; // Подключаем глобальные переменные для конфигурации и плагинов

	// Проверяем, что тип поля — это 'file'
	if ($extrafield['field_type'] == 'file') {
		// Если параметр поля 'field_params' не пустой, используем его, иначе берём путь из конфигурации
		$extrafield['field_params'] = (!empty($extrafield['field_params'])) ? $extrafield['field_params'] : $cfg['extrafield_files_dir'];
		
		// Добавляем косую черту в конец пути, если её нет
		$extrafield['field_params'] .= (mb_substr($extrafield['field_params'], -1) == '/') ? '' : '/';
		
		// Проверяем, существует ли файл по пути, составленному из 'field_params' и 'fielddata'
		if ($extrafield['field_params'].$fielddata) {
			/* === Hook === */
			// Подключаем плагины для обработки удаления файлов
			foreach (cot_getextplugins('extrafields.unlinkfiles') as $pl) {
				include $pl; // Включаем каждый плагин из списка
			}
			/* ===== */
			// Удаляем файл с помощью unlink
			@unlink($extrafield['field_params'].$fielddata); // Осуществляем удаление файла
		}
	}
}

Пояснения:

  1. Глобальные переменные:

    • $cfg: Конфигурационные данные, содержащие информацию о путях для хранения файлов.
    • $pl: Переменная, которая используется для плагинов, подключаемых к процессу удаления файлов.
  2. Проверка типа поля: Функция проверяет, что тип поля в массиве $extrafield равен 'file'. Это необходимо, чтобы операция удаления выполнялась только для файлов.

  3. Построение пути к файлу: Если параметр поля field_params не пустой, то используется его значение, иначе берётся путь из конфигурации $cfg['extrafield_files_dir']. Также проверяется, чтобы в конце пути была косая черта (/).

  4. Удаление файла: Функция проверяет, существует ли файл по пути, составленному из field_params и fielddata. Если файл существует, подключаются плагины через хуки (cot_getextplugins('extrafields.unlinkfiles')) и затем файл удаляется с помощью unlink.

  5. Подключение плагинов: Перед удалением файла вызываются все подключённые плагины, что позволяет расширить функциональность — например, выполнять дополнительные действия до или после удаления файла.

 

Пример использования:
Если в $extrafield содержится информация о файле, который нужно удалить:

$extrafield = [
    'field_type' => 'file',
    'field_params' => '/path/to/files/'
];

$fielddata = 'uploaded_file.jpg'; // Имя файла для удаления

cot_extrafield_unlinkfiles($fielddata, $extrafield);


Путь к файлу будет составлен как /path/to/files/uploaded_file.jpg.
Если файл существует, он будет удалён.


Функция cot_load_extrafields

Эта функция загружает данные дополнительных полей в глобальную переменную $cot_extrafields. Если данные уже загружены или если параметр $forcibly установлен в true, данные загружаются заново. Функция также поддерживает кэширование, чтобы данные не загружались повторно, если это не требуется.

/**
 * Загружает данные дополнительных полей в глобальную переменную
 * @param bool $forcibly Принудительная перезагрузка данных
 * @global array $cot_extrafields Глобальная переменная для хранения данных
 * @global CotDB $db Объект базы данных
 * @global Cache $cache Кэш
 */
function cot_load_extrafields($forcibly = false)
{
	global $db, $cot_extrafields, $db_extra_fields, $cache;

    // Если данные ещё не загружены или требуется принудительная перезагрузка
    if (empty($cot_extrafields) || $forcibly) {
		$cot_extrafields = []; // Очищаем глобальную переменную, чтобы загрузить новые данные
		
		// Условие, проверяющее, если это не установка (COT_INSTALL), то фильтруем только включённые поля
		$where = (defined('COT_INSTALL')) ? "1" : "field_enabled=1";
		
		// Запрос к базе данных для получения всех активных дополнительных полей
		$fieldsres = Cot::$db->query('SELECT * FROM ' . Cot::$db->extra_fields .
            " WHERE $where ORDER BY field_type ASC"); // Сортируем по типу поля

		// Перебираем все строки, полученные из базы, и сохраняем их в массив $cot_extrafields
		while ($row = $fieldsres->fetch()) {
			$cot_extrafields[$row['field_location']][$row['field_name']] = $row;
		}

		$fieldsres->closeCursor(); // Закрываем курсор после получения данных
        // Если кэширование активно, сохраняем данные в кэш
        Cot::$cache && Cot::$cache->db->store('cot_extrafields', $cot_extrafields, 'system');
	}
}

/* ======== Pre-загрузка дополнительных полей ======== */

// Загружаем данные дополнительных полей
cot_load_extrafields();

// Проверяем, есть ли данные для структуры, если нет — инициализируем как пустой массив
$cot_extrafields[Cot::$db->structure] = (!empty($cot_extrafields[Cot::$db->structure])) ?
    $cot_extrafields[Cot::$db->structure] : [];

Пояснения:

  1. Глобальные переменные:

    • $db: Объект базы данных, с помощью которого выполняются запросы.
    • $cot_extrafields: Глобальная переменная, в которую будут загружены данные о дополнительных полях.
    • $db_extra_fields: Таблица или настройка, относящаяся к дополнительным полям (предположительно, для использования в других частях кода).
    • $cache: Кэш, используется для хранения данных, чтобы не загружать их из базы данных повторно.
  2. Параметр $forcibly:

    • Если $forcibly равно true, данные будут перезагружены, даже если они уже загружены в $cot_extrafields.
    • Если $cot_extrafields пустой, данные также будут загружены.
  3. Условие для выборки активных полей:

    • Если не установлена константа COT_INSTALL, то загружаются только активные поля (field_enabled=1), чтобы исключить неактивные или временно выключенные поля.
  4. Запрос данных:

    • Все данные из таблицы дополнительных полей ($db_extra_fields) извлекаются с сортировкой по типу поля (field_type).
  5. Сохранение в глобальный массив:

    • Полученные данные сохраняются в глобальную переменную $cot_extrafields, где они индексируются по field_location и field_name.
  6. Кэширование:

    • Если кэширование включено, данные сохраняются в кэше для дальнейшего использования, чтобы избежать повторных запросов в базу данных.
  7. Пример использования:

    • В коде после вызова функции cot_load_extrafields() добавляется логика для работы с данными для структуры (если данные для структуры уже загружены, они остаются, если нет — инициализируются как пустой массив).

 

Пример использования:
Когда необходимо загрузить все данные о дополнительных полях:

cot_load_extrafields(); // Загружает данные в $cot_extrafields

// Обрабатываем данные для структуры
if (empty($cot_extrafields[Cot::$db->structure])) {
    // Если данных для структуры нет, инициализируем как пустой массив
    $cot_extrafields[Cot::$db->structure] = [];
}

Этот код гарантирует, что данные о дополнительных полях будут загружены и доступны для использования в других частях кода.

 


Функция cot_build_extrafields  используется для формирования или обработки значений дополнительных полей (extrafields) на основе переданных параметров. Хотя конкретная реализация этой функции не была приведена в коде, основываясь на именах переменных и типичных задачах, можно сделать выводы о её функционале.

Вот как можно предположить, что работает функция:

1. Параметры функции:

  • $name — это имя дополнительного поля, которое, скорее всего, указывает на то, для какого поля мы строим или обрабатываем данные. Это может быть имя столбца или идентификатор поля в базе данных.
  • $extrafield — массив или объект, содержащий параметры или метаданные для дополнительного поля, такие как тип поля (например, текстовое поле, чекбокс и т. д.), параметры (например, варианты для селектов или радио кнопок) и другие настройки поля.
  • $data — данные, которые должны быть привязаны или обработаны для указанного поля. Это может быть введённая информация пользователя или информация, извлечённая из базы данных, которая будет отображаться в этом поле.

2. Предположительная роль функции:

Функция cot_build_extrafields может быть предназначена для:

  • Формирования HTML-вывода для отображения значений дополнительных полей на странице. Например, для поля типа input она может создать соответствующий HTML-код для текстового поля. Для поля типа checkbox или radio — HTML-разметку для соответствующих элементов.
  • Обработки введённых данных: Функция может также заниматься преобразованием данных перед их сохранением в базу данных, если это необходимо, например, для приведения значений в нужный формат.
  • Проверки значений: Возможно, функция выполняет валидацию данных, проверяя, соответствует ли введенная информация типу поля (например, число для числового поля, строка для текстового и т.д.).

Пример возможного содержания функции:

Предположим, функция выглядит так

function cot_build_extrafields($name, $extrafield, $data)
{
    // Проверка на тип поля
    switch ($extrafield['field_type']) {
        case 'input':
            // Для типа 'input' создается текстовое поле
            return '<input type="text" name="' . $name . '" value="' . htmlspecialchars($data) . '" />';
        case 'textarea':
            // Для типа 'textarea' создается текстовая область
            return '<textarea name="' . $name . '">' . htmlspecialchars($data) . '</textarea>';
        case 'checkbox':
            // Для типа 'checkbox' создается чекбокс
            return '<input type="checkbox" name="' . $name . '" ' . ($data ? 'checked' : '') . ' />';
        case 'select':
            // Для типа 'select' создается выпадающий список
            $options = explode(',', $extrafield['field_variants']);
            $select_html = '<select name="' . $name . '">';
            foreach ($options as $option) {
                $select_html .= '<option value="' . htmlspecialchars($option) . '"' . ($data == $option ? ' selected' : '') . '>' . htmlspecialchars($option) . '</option>';
            }
            $select_html .= '</select>';
            return $select_html;
        // Можно добавить другие типы полей, такие как 'radio', 'file' и так далее
    }

    return '';  // Если тип поля не поддерживается, вернуть пустую строку
}

3. Как работает этот код:

  • Внутри функции используется switch-case для обработки различных типов дополнительных полей (например, текстовое поле, textarea, checkbox, select и т.д.).
  • Для каждого типа поля генерируется соответствующий HTML-код.
  • Данные, переданные в $data, используются для установки значений в эти поля. Например, для текстового поля это будет значение, введенное пользователем, для чекбокса — атрибут checked, если значение истинное.
  • Если поле не распознано, функция возвращает пустую строку.

4. Применение в контексте Cotonti:

  • Функция может быть использована при выводе форм или при отображении значений дополнительных полей на страницах, на которых они были добавлены.
  • Она помогает в унификации отображения данных на фронтенде, что важно для обеспечения консистентности в пользовательском интерфейсе.

В заключение, cot_build_extrafields может быть ключевой функцией для построения элементов формы или отображения данных, относящихся к дополнительным полям, в зависимости от их типа и значений.


Пример из файла page.add.php

Общее описание:

  • Этот блок кода отвечает за обработку и отображение дополнительных полей для страниц.
  • Он проверяет, есть ли дополнительные поля для страниц (Cot::$extrafields[Cot::$db->pages]), затем для каждого поля:
    • Извлекает соответствующие данные,
    • Генерирует HTML-код для поля,
    • Генерирует заголовок для поля,
    • Присваивает эти данные переменным шаблона для дальнейшего использования на странице.
  • В конце выполняется парсинг блока шаблона, который отображает все дополнительные поля.

Это типичная динамическая обработка форм с дополнительными полями в CMS, где данные передаются в шаблон для их отображения на веб-странице.

// Extra fields
if (!empty(Cot::$extrafields[Cot::$db->pages])) {  // Проверяется, что массив дополнительных полей для страницы (Cot::$extrafields[Cot::$db->pages]) не пустой
    foreach (Cot::$extrafields[Cot::$db->pages] as $exfld) {  // Перебираются все дополнительные поля для страницы
        $uname = strtoupper($exfld['field_name']);  // Переменной $uname присваивается имя поля в верхнем регистре (для использования в шаблоне)
        $data = isset($rpage['page_' . $exfld['field_name']]) ? $rpage['page_' . $exfld['field_name']] : null;  // Извлекается значение для дополнительного поля из массива $rpage, если оно существует, или присваивается null, если данных нет
        $exfld_val = cot_build_extrafields('rpage' . $exfld['field_name'], $exfld, $data);  // Генерируется HTML-код для дополнительного поля с помощью функции cot_build_extrafields
        $exfld_title = cot_extrafield_title($exfld, 'page_');  // Получается заголовок для дополнительного поля с помощью функции cot_extrafield_title

        $t->assign([  // Присваиваются значения переменным шаблона для вывода на страницу
            'PAGEADD_FORM_' . $uname => $exfld_val,  // Присваивается HTML-код для поля
            'PAGEADD_FORM_' . $uname . '_TITLE' => $exfld_title,  // Присваивается заголовок для поля
            'PAGEADD_FORM_EXTRAFLD' => $exfld_val,  // Присваивается HTML-код для поля (для использования в других местах шаблона)
            'PAGEADD_FORM_EXTRAFLD_TITLE' => $exfld_title,  // Присваивается заголовок для поля (для использования в других местах шаблона)
        ]);
        $t->parse('MAIN.EXTRAFLD');  // Парсится (вставляется) блок шаблона 'MAIN.EXTRAFLD', который отображает дополнительные поля
    }
}

1. Назначение кода:

Этот код используется для обработки и отображения дополнительных полей (extrafields) на странице добавления или редактирования данных страницы. Он проверяет наличие дополнительных полей для страницы, строит их и присваивает их значения для отображения в шаблоне.

2. Объяснение по шагам:
 
// Проверка на наличие дополнительных полей для страницы


if (!empty(Cot::$extrafields[Cot::$db->pages])) {


Проверяется, есть ли дополнительные поля для объекта pages в глобальной переменной Cot::$extrafields. Если поля существуют, то выполнение кода продолжается.

foreach (Cot::$extrafields[Cot::$db->pages] as $exfld) {


Перебираются все дополнительные поля для страницы (каждое поле содержится в массиве Cot::$extrafields[Cot::$db->pages]). Каждое поле представлено в массиве как $exfld.

$uname = strtoupper($exfld['field_name']);

Переменной $uname присваивается имя поля в верхнем регистре. Это имя поля будет использоваться в шаблоне для создания уникальных идентификаторов для элементов формы.

$data = isset($rpage['page_' . $exfld['field_name']]) ? $rpage['page_' . $exfld['field_name']] : null;

Здесь извлекаются данные из массива $rpage, связанные с конкретным дополнительным полем. Если данные для данного поля существуют в массиве $rpage, они присваиваются переменной $data. Если данных нет, то устанавливается значение null.
 
$exfld_val = cot_build_extrafields('rpage' . $exfld['field_name'], $exfld, $data);


Функция cot_build_extrafields используется для создания HTML-кода для дополнительного поля. В качестве параметров передаются:
'rpage' . $exfld['field_name'] — это имя поля, которое будет использоваться для идентификации поля в шаблоне.
$exfld — массив с метаданными поля (например, тип поля, параметры и т.д.).
$data — данные, которые будут привязаны к данному полю (например, значение, которое отображается в поле или которое уже введено пользователем).
 
$exfld_title = cot_extrafield_title($exfld, 'page_');
        
        
Функция cot_extrafield_title используется для получения заголовка или названия для дополнительного поля, которое будет отображаться в форме. Название, скорее всего, зависит от метаданных поля, переданных в $exfld.
 
$t->assign([
    'PAGEADD_FORM_' . $uname => $exfld_val,
    'PAGEADD_FORM_' . $uname . '_TITLE' => $exfld_title,
    'PAGEADD_FORM_EXTRAFLD' => $exfld_val,
    'PAGEADD_FORM_EXTRAFLD_TITLE' => $exfld_title,
]);
        
        
Здесь происходит присваивание значений переменным шаблона. В шаблоне будут использоваться ключи:
'PAGEADD_FORM_' . $uname — значение для дополнительного поля (генерируемое HTML).
'PAGEADD_FORM_' . $uname . '_TITLE' — название (заголовок) для дополнительного поля.
'PAGEADD_FORM_EXTRAFLD' и 'PAGEADD_FORM_EXTRAFLD_TITLE' — также используются для универсальных данных.
 
$t->parse('MAIN.EXTRAFLD');
        
        
Этот метод парсит шаблон MAIN.EXTRAFLD, то есть вставляет сгенерированные значения в соответствующее место шаблона для вывода на странице.
3. Основной процесс:
Если для страницы заданы дополнительные поля, то для каждого из них:
Формируется HTML-код поля с помощью cot_build_extrafields.
Заголовок для поля генерируется через cot_extrafield_title.
Эти данные передаются в шаблон, чтобы на странице отображались нужные элементы формы с корректными значениями и названиями.
4. Зачем это нужно:
Этот код необходим для того, чтобы динамически обрабатывать и отображать дополнительные поля на страницах в системе Cotonti. Это позволяет администраторам и пользователям добавлять дополнительные поля на страницы, которые могут быть использованы для ввода и хранения информации, не предусмотренной в стандартной структуре страницы.

5. Характеристика стиля PHP:
Стиль кода в целом является чистым и понятным, с четким разделением логики и шаблонов.
Используется много условных проверок (например, empty и isset) для обработки данных и предотвращения ошибок.
Для формирования динамических элементов используется метод работы с шаблонами (предполагается использование библиотеки или системы шаблонов, такой как XTemplate).
Применяется переиспользуемая функция cot_build_extrafields, что соответствует принципам модульности и повторного использования кода.
Таким образом, код демонстрирует типичный для Cotonti подход к работе с дополнительными полями в контексте отображения данных в пользовательских интерфейсах.

 

 

 

 

 

44 минут чтения Administrator

Комментарии (0)

Комментарии отсутствуют
Добавление комментариев доступно только зарегистрированным пользователям

Автор контента

Administrator

Оффлайн

Administrator

Последняя авторизация: 05.07.2026 18:32

  • Страница размещена: 24.01.2025 15:02
  • Последнее обновление: 24.01.2025 15:55

Похожие страницы

Файл admin.extrafields.php в Cotonti CMF
1 Файл admin.extrafields.php в движке Cotonti CMF предназначен для управления дополнительными полями (extra fields) в
API экстраполей в Cotonti (Extrafields API)
2 API экстраполей (Extrafields API)Экстраполя служат для дополнения определенными данными какие-либо сущности на сайте.
Файл "page.extrafields.php" в Cotonti CMF
3 Файл "page.extrafields.php" в системе Cotonti CMF является частью модуля "page", и он отвечает за
Файл "forums.extrafields.php" в системе Cotonti CMF
4 Файл "forums.extrafields.php" в системе Cotonti CMF является частью модуля Forums и используется для
Модуль "Users", - users.extrafields.php в Cotonti CMF
5 Основное назначение файла Файл users.extrafields.php в Cotonti CMF представляет собой часть модуля для управления