Файл page.list.php в системе Cotonti CMF играет ключевую роль в отображении страниц с категориями и их списками на сайте. Это один из файлов модуля страниц, находящийся в директории /modules/page/inc. Он отвечает за генерацию и отображение списка страниц в категориях, а также за обработку пагинации, фильтрации и сортировки.
Основное назначение файла и его место в системе Cotonti
Файл page.list.php является важной частью системы Cotonti, отвечающей за отображение списка страниц для различных категорий сайта. Он реализует функциональность вывода страниц в категории, обработку сортировки по различным полям (например, названию, дате, автору), обработку пагинации для разделения списка на несколько страниц и вывод дополнительных пользовательских полей (extrafields) для категорий и страниц.
Этот файл взаимодействует с системой Cotonti в рамках модуля "pages" и используется в контексте вывода контента на странице сайта, в частности, на страницах с категориями. С помощью данного файла можно вывести список страниц в каждой категории, применяя к ним различные фильтры, сортировки и пагинацию.
Взаимодействие с сайтом
Файл page.list.php обрабатывает запросы на вывод списка страниц для определённой категории. Он собирает список страниц из базы данных, применяет сортировку и фильтрацию по различным критериям (например, по заголовкам, датам или авторам), обрабатывает пагинацию, а также учитывает наличие дополнительных полей (extrafields) для отображения. Все это выводится на страницах сайта в соответствующих категориях.
Кроме того, этот файл взаимодействует с другими частями системы Cotonti:
- Использует API для работы с плагинами (хуки).
- Работает с переменными конфигурации для настройки кеширования и вывода контента.
- Взаимодействует с объектами шаблонов (XTemplate), чтобы формировать и выводить страницы с использованием шаблонов.
Основные переменные, хуки, методы и классы
-
Переменные:
- $list_url_path: массив, содержащий параметры URL для формирования ссылок на страницы в категории.
- $dc, $dcurl, $durl: переменные, отвечающие за параметры пагинации.
- $allsub: массив всех подкатегорий для текущей категории.
- $subcat: массив подкатегорий, ограниченный количеством страниц на одну страницу (с учетом пагинации).
- $arrows: массив, хранящий иконки для сортировки по различным полям.
- $pagenav_cat: массив, содержащий данные для пагинации (ссылки на предыдущие и следующие страницы, номер текущей страницы).
- $sqllist_rowset: результат SQL-запроса, содержащий все страницы, которые нужно отобразить.
-
Хуки:
- page.list.rowcat.first: выполняется перед выводом строки категории.
- page.list.rowcat.loop: выполняется в цикле для каждой подкатегории.
- page.list.before_loop: выполняется перед выводом списка страниц.
- page.list.loop: выполняется внутри цикла для каждой страницы в категории.
- page.list.tags: выполняется после обработки всех страниц и перед выводом основного шаблона.
-
Методы и функции:
- cot_structure_children(): получает дочерние категории для текущей категории.
- cot_url(): формирует URL для перехода по страницам, категориям и фильтрации.
- cot_pagenav(): генерирует навигацию по страницам с учетом пагинации.
- cot_display_messages(): выводит сообщения об ошибках или уведомления.
- cot_generate_pagetags(): генерирует теги для страницы, включая информацию о владельце, числе комментариев, статусе страницы и другие данные.
- cot_generate_usertags(): генерирует теги для отображения информации о владельце страницы.
-
Классы:
- Cot::$cfg: класс конфигурации, используется для получения настроек системы.
- Cot::$usr: класс, представляющий информацию о текущем пользователе.
- Cot::$R: класс для работы с ресурсами, такими как иконки и изображения.
- Cot::$cache: класс для работы с кешированием страниц.
Суть содержания кода
Код в файле page.list.php выполняет следующие задачи:
-
Сортировка и фильтрация данных: Формируется список страниц с сортировкой по различным полям (заголовок, дата, автор и т.д.) и фильтрацией по параметрам URL.
-
Пагинация: Реализована пагинация для вывода страниц по частям, ограничивая количество страниц, отображаемых на одной странице.
-
Обработка подкатегорий: Выводятся все страницы и подкатегории для выбранной категории, включая подсчет количества страниц в подкатегориях.
-
Подключение плагинов: Используются хуки для подключения плагинов на различных этапах выполнения скрипта (до и после основного цикла).
-
Вывод дополнительных полей (extrafields): Для каждой категории и страницы могут быть выведены дополнительные пользовательские поля (extrafields), если они определены в конфигурации.
-
Отображение сообщений: Обрабатываются сообщения об ошибках или других уведомлениях через функцию cot_display_messages().
Использование владельцем сайта
Этот сценарий используется владельцем сайта для отображения страниц в категориях, их сортировки, фильтрации и организации навигации по страницам. Он позволяет отображать большое количество страниц в структурированном виде, с учетом пагинации и дополнительных полей.
С помощью данного файла можно настраивать, какие страницы и категории отображать на сайте, а также как организовать сортировку и фильтрацию контента для пользователей.
Стиль написания PHP-кода и совместимость
Код написан в стандартном стиле PHP с использованием популярных методов и функций, характерных для системы Cotonti. Он использует глобальные переменные и массивы для обработки данных и взаимодействует с объектами и методами Cotonti, такими как Cot::$cfg, Cot::$usr и другие.
Код совместим с версиями PHP от 5.3 и выше, так как в нем используется поддержка массивов, функций и методов, доступных в этих версиях PHP. Однако для оптимальной работы рекомендуется использовать более новые версии PHP, такие как 7.x и выше.
defined('COT_CODE') or die('Wrong URL'); // Неверный URL
// Настройка окружения
const COT_LIST = true; // Устанавливаем флаг COT_LIST в true
Cot::$env['location'] = 'list'; // Локация установлена на 'list'
// Параметры сортировки и фильтрации
$s = cot_import('s', 'G', 'ALP'); // поле для сортировки без 'page_'
$w = cot_import('w', 'G', 'ALP', 4); // способ сортировки (asc, desc)
$c = cot_import('c', 'G', 'TXT'); // код категории
$o = cot_import('ord', 'G', 'ARR'); // имена полей фильтрации без 'page_'
$p = cot_import('p', 'G', 'ARR'); // значения фильтров
$maxPageRowsPerPage = (int) Cot::$cfg['page']['cat___default']['maxrowsperpage']; // максимальное количество строк на странице по умолчанию
if ($maxPageRowsPerPage <= 0) { // если значение неправильно или отсутствует
$maxPageRowsPerPage = Cot::$cfg['maxrowsperpage']; // применяем общее значение для максимального числа строк
}
if (
!empty($c) // если код категории не пустой
&& !empty(Cot::$cfg['page']['cat_' . $c]) // если существует настройка для этой категории
&& !empty(Cot::$cfg['page']['cat_' . $c]['maxrowsperpage']) // если задано максимальное количество строк для этой категории
) {
$maxPageRowsPerPage = (int) Cot::$cfg['page']['cat_' . $c]['maxrowsperpage']; // переопределяем максимальное количество строк для категории
}
// Номер страницы для списка страниц
list($pg, $d, $durl) = cot_import_pagenav('d', $maxPageRowsPerPage); // получение номера страницы и данных для навигации по страницам
// Номер страницы для списка категорий
list($pgc, $dc, $dcurl) = cot_import_pagenav('dc', Cot::$cfg['page']['maxlistsperpage']); // получение номера страницы и данных для навигации по категориям
if ($c === 'all' || $c === 'system') { // если категория 'all' или 'system'
list(Cot::$usr['auth_read'], Cot::$usr['auth_write'], Cot::$usr['isadmin']) = cot_auth('admin', 'a'); // получаем разрешения для администратора
cot_block(Cot::$usr['isadmin']); // проверяем, является ли пользователь администратором
} elseif ($c === 'unvalidated' || $c === 'saved_drafts') { // если категория 'unvalidated' или 'saved_drafts'
list(Cot::$usr['auth_read'], Cot::$usr['auth_write'], Cot::$usr['isadmin']) = cot_auth('page', 'any'); // получаем разрешения для любой страницы
cot_block(Cot::$usr['auth_write']); // проверяем, есть ли у пользователя право на запись
} elseif (!isset(Cot::$structure['page'][$c])) { // если категория не существует
cot_die_message(404); // выводим сообщение об ошибке 404
} else { // для остальных категорий
list(Cot::$usr['auth_read'], Cot::$usr['auth_write'], Cot::$usr['isadmin']) = cot_auth('page', $c); // получаем разрешения для страницы в конкретной категории
cot_block(Cot::$usr['auth_read']); // проверяем, есть ли у пользователя право на чтение
}
/* === Hook === */
foreach (cot_getextplugins('page.list.first') as $pl) { // для каждого плагина в хуке 'page.list.first'
include $pl; // подключаем плагин
}
/* ===== */
$cat = []; // инициализация переменной $cat
if (isset(Cot::$structure['page'][$c])) { // если категория существует
$cat = &Cot::$structure['page'][$c]; // присваиваем ссылку на структуру категории
}
$defaultOrder = !empty(Cot::$cfg['page']['cat_' . $c]['order']) // если указано значение порядка для категории
? Cot::$cfg['page']['cat_' . $c]['order'] // используем значение порядка категории
: Cot::$cfg['page']['cat___default']['order']; // иначе используем порядок по умолчанию
if (empty($s)) { // если сортировка не указана
$s = $defaultOrder; // применяем порядок по умолчанию
}
$defaultOrderWay = !empty(Cot::$cfg['page']['cat_' . $c]['way']) // если указана направленность сортировки для категории
? Cot::$cfg['page']['cat_' . $c]['way'] // используем направленность сортировки категории
: Cot::$cfg['page']['cat___default']['way']; // иначе применяем направленность по умолчанию
if (empty($w) || !in_array($w, ['asc', 'desc'])) { // если направленность сортировки не указана или она неверна
$w = $defaultOrderWay; // применяем направленность сортировки по умолчанию
}
$pageListTruncateText = (int) Cot::$cfg['page']['cat___default']['truncatetext']; // максимальная длина текста по умолчанию
if (
!empty($c) // если категория задана
&& !empty(Cot::$cfg['page']['cat_' . $c]) // если категория существует в настройках
&& isset(Cot::$cfg['page']['cat_' . $c]['truncatetext']) // если для категории задано ограничение по длине текста
&& ((string) Cot::$cfg['page']['cat_' . $c]['truncatetext'] !== '') // если значение ограничено (не пустое)
) {
$pageListTruncateText = (int) Cot::$cfg['page']['cat_' . $c]['truncatetext']; // применяем значение длины текста для категории
}
$where = []; // инициализация массива условий для запроса
$params = []; // инициализация массива параметров для запроса
$where_state = Cot::$usr['isadmin'] ? '1' : 'page_ownerid = ' . Cot::$usr['id']; // если пользователь администратор, то условие равняется 1, иначе фильтруем по владельцу страницы
$where['state'] = "(page_state=0 AND $where_state)"; // добавляем условие для выбора опубликованных страниц или страниц для текущего пользователя
if ($c === 'unvalidated') { // если категория "unvalidated"
$cat['tpl'] = 'unvalidated'; // назначаем шаблон для категории "unvalidated"
$where['state'] = 'page_state = ' . COT_PAGE_STATE_PENDING; // выбираем страницы со статусом "не проверено"
$where['ownerid'] = Cot::$usr['isadmin'] ? '1' : 'page_ownerid = ' . Cot::$usr['id']; // проверяем права доступа на страницы, если администратор, то доступ ко всем, иначе — только свои
$cat['title'] = Cot::$L['page_validation']; // устанавливаем заголовок для категории
$cat['desc'] = Cot::$L['page_validation_desc']; // устанавливаем описание для категории
$s = 'date'; // сортировка по дате
$w = 'desc'; // сортировка по убыванию
} elseif ($c === 'saved_drafts') { // если категория "saved_drafts"
$cat['tpl'] = 'unvalidated'; // назначаем шаблон для категории "saved_drafts"
$where['state'] = 'page_state = ' . COT_PAGE_STATE_DRAFT; // выбираем страницы со статусом "черновик"
$where['ownerid'] = Cot::$usr['isadmin'] ? '1' : 'page_ownerid = ' . Cot::$usr['id']; // проверяем права доступа на страницы, если администратор, то доступ ко всем, иначе — только свои
$cat['title'] = Cot::$L['page_drafts']; // устанавливаем заголовок для категории
$cat['desc'] = Cot::$L['page_drafts_desc']; // устанавливаем описание для категории
$s = 'date'; // сортировка по дате
$w = 'desc'; // сортировка по убыванию
} elseif ($c === 'all') { // если категория "all"
$cat['title'] = 'All'; // устанавливаем заголовок для категории "All"
$cat['desc'] = 'All'; // устанавливаем описание для категории "All"
$cat['tpl'] = 'all'; // назначаем шаблон для категории "All"
} else { // если категория не соответствует ни одной из перечисленных
$where['cat'] = 'page_cat = ' . Cot::$db->quote($c); // фильтруем страницы по категории
$where['state'] = 'page_state = ' . COT_PAGE_STATE_PUBLISHED; // выбираем только опубликованные страницы
}
Cot::$sys['sublocation'] = $cat['title']; // устанавливаем имя подкатегории в системной переменной для отображения в интерфейсе
if ($o && $p) { // если переданы фильтры для полей и значений
if (!is_array($o)) { // если $o не является массивом
$o = [$o]; // преобразуем $o в массив
}
if (!is_array($p)) { // если $p не является массивом
$p = [$p]; // преобразуем $p в массив
}
$filters = array_combine($o, $p); // комбинируем массивы $o и $p в ассоциативный массив фильтров
foreach ($filters as $key => $val) { // проходим по каждому фильтру
$key = cot_import($key, 'D', 'ALP', 16); // импортируем ключ с валидацией, разрешаем только алфавитно-цифровые символы
$val = cot_import($val, 'D', 'TXT', 16); // импортируем значение с валидацией как текст
// @todo don't make requests in the loop // не стоит делать запросы в цикле
if ($key && $val && Cot::$db->fieldExists(Cot::$db->pages, "page_$key")) { // если ключ и значение существуют, а также поле с таким ключом в таблице
$params[$key] = $val; // добавляем значение в параметры запроса
$where['filter'][] = "page_$key = :$key"; // добавляем условие для фильтрации
}
}
empty($where['filter']) || $where['filter'] = implode(' AND ', $where['filter']); // если фильтры не пусты, объединяем их в строку с операторами AND
}
if (!Cot::$usr['isadmin'] && $c !== 'unvalidated' && $c !== 'saved_drafts') { // если пользователь не администратор и категория не 'unvalidated' или 'saved_drafts'
$where['date'] = "page_begin <= {$sys['now']} AND (page_expire = 0 OR page_expire > {$sys['now']})"; // добавляем условие на даты начала и окончания публикации страницы
}
if (!Cot::$db->fieldExists(Cot::$db->pages, "page_$s")) { // если поле сортировки не существует в таблице страниц
$s = 'title'; // заменяем поле сортировки на 'title'
}
$orderby = "page_$s $w"; // формируем строку для сортировки, используя выбранное поле и порядок сортировки
$list_url_path = ['c' => $c]; // создаем массив с параметром 'c' равным категории
if (!empty($o)) { // если указан порядок сортировки
$list_url_path['ord'] = $o; // добавляем параметр 'ord' с порядком сортировки
}
if (!empty($p)) { // если указаны фильтры
$list_url_path['p'] = $p; // добавляем параметр 'p' с фильтрами
}
// Для канонического URL
$pageurl_params = $list_url_path; // устанавливаем параметры для канонического URL, равные параметрам списка
if ($s !== $defaultOrder) { // если поле сортировки не равно значению по умолчанию
$list_url_path['s'] = $s; // добавляем параметр 's' с выбранным полем сортировки
}
if ($w !== $defaultOrderWay) { // если порядок сортировки не равен значению по умолчанию
$list_url_path['w'] = $w; // добавляем параметр 'w' с выбранным порядком сортировки
}
$list_url = cot_url('page', $list_url_path); // формируем URL для страницы с параметрами
if ($durl > 1) { // если текущая страница больше 1
$pageurl_params['d'] = $durl; // добавляем параметр 'd' для пагинации страниц
}
if ($dcurl > 1) { // если текущая страница категории больше 1
$pageurl_params['dc'] = $dcurl; // добавляем параметр 'dc' для пагинации категорий
}
$catpatharray = cot_structure_buildpath('page', $c); // создаем массив пути категории страниц
$catpath = in_array($c, ['all', 'system', 'unvalidated', 'saved_drafts'], true) // если категория одна из исключений (all, system, unvalidated, saved_drafts)
? $cat['title'] // то путь будет просто равен заголовку категории
: cot_breadcrumbs($catpatharray, Cot::$cfg['homebreadcrumb'], true); // иначе, строим хлебные крошки из пути категории, добавляем главную страницу
$shortpath = $catpatharray; // создаем копию пути категории
array_pop($shortpath); // удаляем последний элемент из пути (для укороченного пути)
$catpath_short = in_array($c, ['all', 'system', 'unvalidated', 'saved_drafts'], true) // если категория одна из исключений (all, system, unvalidated, saved_drafts)
? '' // то укороченный путь будет пустым
: cot_breadcrumbs($shortpath, Cot::$cfg['homebreadcrumb'], false); // иначе, строим укороченные хлебные крошки без главной страницы
$join_columns = isset($join_columns) ? $join_columns : ''; // если переменная join_columns существует, то используем ее, иначе пустая строка
$join_condition = isset($join_condition) ? $join_condition : ''; // если переменная join_condition существует, то используем ее, иначе пустая строка
/* === Hook === */
foreach (cot_getextplugins('page.list.query') as $pl) { // проходим по всем подключенным плагинам для страницы
include $pl; // подключаем каждый плагин
}
/* ===== */
$catpatharray = cot_structure_buildpath('page', $c); // создаем массив пути категории страниц
$catpath = in_array($c, ['all', 'system', 'unvalidated', 'saved_drafts'], true) // если категория одна из исключений (all, system, unvalidated, saved_drafts)
? $cat['title'] // то путь будет просто равен заголовку категории
: cot_breadcrumbs($catpatharray, Cot::$cfg['homebreadcrumb'], true); // иначе, строим хлебные крошки из пути категории, добавляем главную страницу
$shortpath = $catpatharray; // создаем копию пути категории
array_pop($shortpath); // удаляем последний элемент из пути (для укороченного пути)
$catpath_short = in_array($c, ['all', 'system', 'unvalidated', 'saved_drafts'], true) // если категория одна из исключений (all, system, unvalidated, saved_drafts)
? '' // то укороченный путь будет пустым
: cot_breadcrumbs($shortpath, Cot::$cfg['homebreadcrumb'], false); // иначе, строим укороченные хлебные крошки без главной страницы
$join_columns = isset($join_columns) ? $join_columns : ''; // если переменная join_columns существует, то используем ее, иначе пустая строка
$join_condition = isset($join_condition) ? $join_condition : ''; // если переменная join_condition существует, то используем ее, иначе пустая строка
/* === Hook === */
foreach (cot_getextplugins('page.list.query') as $pl) { // проходим по всем подключенным плагинам для страницы
include $pl; // подключаем каждый плагин
}
/* ===== */
if (empty($sql_page_string)) { // если строка SQL-запроса не установлена
$where = array_filter($where); // фильтруем пустые элементы в массиве $where
$where = ($where) ? 'WHERE ' . implode(' AND ', $where) : ''; // если условия есть, формируем строку WHERE, объединяя условия через 'AND'
$sql_page_count = "SELECT COUNT(*) FROM $db_pages as p $join_condition LEFT JOIN $db_users AS u ON u.user_id=p.page_ownerid $where"; // запрос для подсчета общего числа страниц
$limit = ''; // инициализация переменной лимита
if ($maxPageRowsPerPage > 0) { // если количество строк на страницу больше 0
$limit = "LIMIT $d, $maxPageRowsPerPage"; // добавляем лимит на количество строк на страницу
}
// формируем основной SQL-запрос для выборки страниц
$sql_page_string = "SELECT p.*, u.* $join_columns
FROM $db_pages as p $join_condition
LEFT JOIN $db_users AS u ON u.user_id=p.page_ownerid
$where
ORDER BY $orderby $limit";
}
$totallines = $db->query($sql_page_count, $params)->fetchColumn(); // выполняем запрос для подсчета общего числа записей
$sqllist = $db->query($sql_page_string, $params); // выполняем запрос для получения списка страниц
if (
(
!Cot::$cfg['easypagenav'] // если не включена простая навигация
&& $durl > 0 // если есть страница
&& $maxPageRowsPerPage > 0 // если есть максимальное количество строк на странице
&& $durl % $maxPageRowsPerPage > 0 // если остаток от деления номера страницы на максимальное количество строк не равен нулю
)
|| ($d > 0 && $d >= $totallines) // или если количество записей больше или равно общему числу записей
) {
cot_redirect(cot_url('page', $list_url_path + ['dc' => $dcurl])); // редирект на страницу с правильными параметрами
}
$pagenav = cot_pagenav(
'page', // тип страницы
$list_url_path + ['dc' => $dcurl], // параметры URL
$d, // номер текущей страницы
$totallines, // общее количество записей
$maxPageRowsPerPage // количество записей на странице
);
$catTitle = htmlspecialchars(strip_tags($cat['title'])); // извлекаем и очищаем от HTML-тегов заголовок категории, делаем его безопасным для отображения
Cot::$out['desc'] = htmlspecialchars(strip_tags($cat['desc'])); // очищаем описание категории от HTML-тегов и присваиваем его переменной для вывода
Cot::$out['subtitle'] = $catTitle; // устанавливаем подзаголовок страницы как название категории
if (!empty(Cot::$cfg['page']['cat_' . $c]['keywords'])) { // если для категории есть ключевые слова
Cot::$out['keywords'] = Cot::$cfg['page']['cat_' . $c]['keywords']; // присваиваем ключевые слова
} elseif (!empty(Cot::$cfg['page']['cat___default']['keywords'])) { // если нет, то используем ключевые слова по умолчанию
Cot::$out['keywords'] = Cot::$cfg['page']['cat___default']['keywords']; // присваиваем ключевые слова по умолчанию
}
if (!empty(Cot::$cfg['page']['cat_' . $c]['metadesc'])) { // если для категории есть мета-описание
Cot::$out['desc'] = Cot::$cfg['page']['cat_' . $c]['metadesc']; // присваиваем его переменной для мета-описания
}
if (empty(Cot::$out['desc']) && !empty(Cot::$cfg['page']['cat___default']['metadesc'])) { // если мета-описание не задано, используем описание по умолчанию
Cot::$out['desc'] = Cot::$cfg['page']['cat___default']['metadesc'] . ' - ' . $catTitle; // добавляем название категории в мета-описание
}
if (!empty(Cot::$cfg['page']['cat_' . $c]['metatitle'])) { // если для категории есть мета-заголовок
Cot::$out['subtitle'] = Cot::$cfg['page']['cat_' . $c]['metatitle']; // устанавливаем мета-заголовок в качестве подзаголовка страницы
}
// Building the canonical URL
Cot::$out['canonical_uri'] = cot_url('page', $pageurl_params); // формируем каноничный URL для страницы
$_SESSION['cat'] = $c; // сохраняем текущую категорию в сессии
$mskin = cot_tplfile(['page', 'list', $cat['tpl']]); // выбираем шаблон для отображения списка страниц в категории
if (!empty($pgc) && $pgc > 1) { // если есть переменная $pgc и её значение больше 1
Cot::$out['subtitle'] .= ' (' . $pgc . ')'; // добавляем количество страниц к подзаголовку
}
/* === Hook === */
foreach (cot_getextplugins('page.list.main') as $pl) { // выполняем подключение всех плагинов для страницы списка
include $pl; // подключаем плагин
}
/* ===== */
require_once Cot::$cfg['system_dir'] . '/header.php'; // подключаем файл заголовка системы
$t = new XTemplate($mskin); // создаем объект XTemplate для шаблона страницы
$categoryIcon = !empty($cat['icon']) // если есть иконка категории
? cot_rc( // вызываем шаблон для отображения иконки категории
'img_structure_cat',
[
'icon' => $cat['icon'], // передаем иконку категории
'title' => htmlspecialchars($cat['title']), // передаем название категории
'desc' => htmlspecialchars($cat['desc']), // передаем описание категории
]
)
: ''; // если иконка отсутствует, то оставляем пустое значение
// Присваиваем данные в шаблон
$t->assign([
'LIST_CAT_CODE' => $c, // код категории
'LIST_CAT_TITLE' => htmlspecialchars($cat['title']), // название категории
'LIST_CAT_RSS' => cot_url('rss', ['c' => $c]), // RSS-канал категории
'LIST_CAT_PATH' => $catpath, // путь к категории
'LIST_CAT_PATH_SHORT' => $catpath_short, // короткий путь к категории
'LIST_CAT_URL' => cot_url('page', $list_url_path), // URL страницы категории
'LIST_CAT_DESCRIPTION' => $cat['desc'], // описание категории
'LIST_CAT_ICON' => $categoryIcon, // иконка категории
'LIST_CAT_ICON_SRC' => !empty($cat['icon']) ? $cat['icon'] : '', // источник иконки категории
'LIST_BREADCRUMBS' => $catpath, // хлебные крошки для категории
'LIST_BREADCRUMBS_SHORT' => $catpath_short, // короткие хлебные крошки для категории
]);
if (isset(Cot::$cfg['legacyMode']) && Cot::$cfg['legacyMode']) { // проверяем, активирован ли режим совместимости (legacy mode)
// @deprecated in 0.9.24 // отмечено как устаревшее в версии 0.9.24
$t->assign([ // присваиваем данные в шаблон
'LIST_CAT' => $c, // код категории
'LIST_CATTITLE' => $cat['title'], // название категории
'LIST_CATEGORY' => htmlspecialchars($cat['title']), // название категории (с экранированием)
'LIST_CATPATH' => $catpath, // путь к категории
'LIST_CATSHORTPATH' => $catpath_short, // короткий путь к категории
'LIST_CATURL' => cot_url('page', $list_url_path), // URL категории
'LIST_CATDESC' => $cat['desc'], // описание категории
'LIST_CATICON' => $categoryIcon, // иконка категории
'LIST_PAGETITLE' => $catpath, // титул страницы (путь к категории)
'LIST_EXTRATEXT' => isset($extratext) ? $extratext : '', // дополнительный текст, если существует
'LIST_TOP_PAGINATION' => $pagenav['main'], // главная навигация по страницам
'LIST_TOP_PAGEPREV' => $pagenav['prev'], // ссылка на предыдущую страницу
'LIST_TOP_PAGENEXT' => $pagenav['next'], // ссылка на следующую страницу
'LIST_TOP_CURRENTPAGE' => $pagenav['current'], // текущая страница
'LIST_TOP_TOTALLINES' => $totallines, // общее количество строк
'LIST_TOP_MAXPERPAGE' => $maxPageRowsPerPage, // количество строк на страницу
'LIST_TOP_TOTALPAGES' => $pagenav['total'], // общее количество страниц
]);
}
$t->assign(cot_generatePaginationTags($pagenav)); // присваиваем теги для пагинации
if (Cot::$usr['auth_write'] && $c != 'all' && $c != 'unvalidated' && $c != 'saved_drafts') { // проверяем права на добавление страницы и исключаем определённые категории
$submitNewPageUrl = cot_url('page', ['c' => $c, 'm' => 'add']); // генерируем URL для добавления новой страницы
$t->assign([ // присваиваем данные для кнопки "Добавить новую страницу"
'LIST_SUBMIT_NEW_PAGE' => cot_rc('page_submitnewpage', ['sub_url' => $submitNewPageUrl]), // текст кнопки
'LIST_SUBMIT_NEW_PAGE_URL' => $submitNewPageUrl, // URL для кнопки
]);
if (isset(Cot::$cfg['legacyMode']) && Cot::$cfg['legacyMode']) { // проверка на устаревший режим
// @deprecated in 0.9.24 // отмечено как устаревшее в версии 0.9.24
$t->assign([ // присваиваем данные для кнопки "Добавить новую страницу" в устаревшем формате
'LIST_SUBMITNEWPAGE' => cot_rc('page_submitnewpage', ['sub_url' => $submitNewPageUrl]),
'LIST_SUBMITNEWPAGE_URL' => $submitNewPageUrl,
]);
}
}
// Extra fields for structure // обработка дополнительных полей для структуры
if (isset(Cot::$extrafields[Cot::$db->structure])) { // если у структуры есть дополнительные поля
foreach (Cot::$extrafields[Cot::$db->structure] as $exfld) { // для каждого дополнительного поля
$uname = strtoupper($exfld['field_name']); // имя поля в верхнем регистре
$exfld_title = cot_extrafield_title($exfld, 'structure_'); // заголовок дополнительного поля
$t->assign([ // присваиваем значения для дополнительных полей
'LIST_CAT_' . $uname . '_TITLE' => $exfld_title, // заголовок
'LIST_CAT_' . $uname => cot_build_extrafields_data('structure', $exfld, $cat[$exfld['field_name']]), // данные поля
'LIST_CAT_' . $uname . '_VALUE' => $cat[$exfld['field_name']], // значение поля
]);
}
}
$arrows = []; // инициализируем массив для стрелок сортировки
foreach (Cot::$extrafields[Cot::$db->pages] + array('title' => 'title', 'key' => 'key', 'date' => 'date', 'author' => 'author',
'owner' => 'owner', 'count' => 'count', 'filecount' => 'filecount') as $row_k => $row_p) { // проходим по дополнительным полям страниц и основным полям
$uname = strtoupper($row_k); // преобразуем имя поля в верхний регистр
$url_asc = cot_url('page', array('s' => $row_k, 'w' => 'asc') + $list_url_path); // генерируем URL для сортировки по возрастанию
$url_desc = cot_url('page', array('s' => $row_k, 'w' => 'desc') + $list_url_path); // генерируем URL для сортировки по убыванию
$arrows[$row_k]['asc'] = Cot::$R['icon_down']; // иконка для сортировки по возрастанию
$arrows[$row_k]['desc'] = Cot::$R['icon_up']; // иконка для сортировки по убыванию
if ($s == $row_k) { // если текущее поле сортировки совпадает с обрабатываемым
$arrows[$s][$w] = Cot::$R['icon_vert_active'][$w]; // присваиваем активную иконку для текущей сортировки
}
if(in_array($row_k, array('title', 'key', 'date', 'author', 'owner', 'count', 'filecount'))) { // если поле является основным
$t->assign(array( // присваиваем значения для ссылок на сортировку
'LIST_TOP_'.$uname => cot_rc("list_link_$row_k", array(
'cot_img_down' => $arrows[$row_k]['asc'], // иконка сортировки по возрастанию
'cot_img_up' => $arrows[$row_k]['desc'], // иконка сортировки по убыванию
'list_link_url_down' => $url_asc, // URL для сортировки по возрастанию
'list_link_url_up' => $url_desc // URL для сортировки по убыванию
))));
}
else { // для дополнительных полей
$extratitle = isset($L['page_'.$row_k.'_title']) ? $L['page_'.$row_k.'_title'] : $row_p['field_description']; // заголовок дополнительного поля
$t->assign(array( // присваиваем значения для сортировки по дополнительным полям
'LIST_TOP_'.$uname => cot_rc('list_link_field_name', array(
'cot_img_down' => $arrows[$row_k]['asc'],
'cot_img_up' => $arrows[$row_k]['desc'],
'list_link_url_down' => $url_asc,
'list_link_url_up' => $url_desc
))));
}
$t->assign(array( // присваиваем URL для ссылок сортировки
'LIST_TOP_'.$uname.'_URL_ASC' => $url_asc,
'LIST_TOP_'.$uname.'_URL_DESC' => $url_desc
));
}
$kk = 0; // инициализируем переменную счетчика
$allsub = cot_structure_children('page', $c, false, false, true, false); // получаем все дочерние категории для текущей категории страниц
$subcat = array_slice($allsub, $dc, Cot::$cfg['page']['maxlistsperpage']); // обрабатываем подкатегории с учетом пагинации, начиная с индекса $dc и ограничиваясь максимальным количеством элементов на странице
/* === Hook === */
foreach (cot_getextplugins('page.list.rowcat.first') as $pl) { // выполняем плагины, подключенные к хуку 'page.list.rowcat.first'
include $pl; // подключаем каждый плагин
}
/* ===== */
/* === Hook - Part1 : Set === */
$extp = cot_getextplugins('page.list.rowcat.loop'); // получаем плагины для хука 'page.list.rowcat.loop'
/* ===== */
foreach ($subcat as $x) { // проходим по каждой подкатегории в массиве $subcat
$kk++; // увеличиваем счетчик $kk для каждой итерации
$cat_childs = cot_structure_children('page', $x); // получаем дочерние категории для текущей категории $x
$subCategoriesCount = 0; // инициализируем переменную для подсчета дочерних элементов
foreach ($cat_childs as $cat_child) { // проходим по дочерним категориям
$subCategoriesCount += (int) $structure['page'][$cat_child]['count']; // увеличиваем счетчик для каждого дочернего элемента
}
$sub_url_path = $list_url_path; // копируем путь URL
$sub_url_path['c'] = $x; // добавляем идентификатор текущей подкатегории в URL
$t->assign([ // передаем данные в шаблон
'LIST_CAT_ROW_ID' => $structure['page'][$x]['id'],
'LIST_CAT_ROW_URL' => cot_url('page', $sub_url_path), // URL для текущей подкатегории
'LIST_CAT_ROW_TITLE' => htmlspecialchars($structure['page'][$x]['title']), // заголовок подкатегории
'LIST_CAT_ROW_DESCRIPTION' => $structure['page'][$x]['desc'], // описание подкатегории
'LIST_CAT_ROW_ICON' => !empty($structure['page'][$x]['icon']) // иконка подкатегории
? cot_rc(
'img_structure_cat',
[
'icon' => $structure['page'][$x]['icon'],
'title' => htmlspecialchars($structure['page'][$x]['title']),
'desc' => htmlspecialchars($structure['page'][$x]['desc']),
]
)
: '',
'LIST_CAT_ROW_ICON_SRC' => !empty($structure['page'][$x]['icon']) ? $structure['page'][$x]['icon'] : '', // источник иконки
'LIST_CAT_ROW_COUNT' => $subCategoriesCount, // количество дочерних категорий
'LIST_CAT_ROW_NUM' => $kk, // номер текущей строки
]);
if (isset(Cot::$cfg['legacyMode']) && Cot::$cfg['legacyMode']) { // проверяем, включен ли режим legacy
// @deprecated in 0.9.24
$t->assign([ // для устаревшей версии присваиваем данные с другим набором переменных
'LIST_ROWCAT_ID' => $structure['page'][$x]['id'],
'LIST_ROWCAT_URL' => cot_url('page', $sub_url_path),
'LIST_ROWCAT_TITLE' => $structure['page'][$x]['title'],
'LIST_ROWCAT_DESC' => $structure['page'][$x]['desc'],
'LIST_ROWCAT_ICON' => $structure['page'][$x]['icon'],
'LIST_ROWCAT_COUNT' => $subCategoriesCount,
'LIST_ROWCAT_ODDEVEN' => cot_build_oddeven($kk), // четность/нечетность строки
'LIST_ROWCAT_NUM' => $kk,
]);
}
// Extra fields for structure
if (!empty(Cot::$extrafields[Cot::$db->structure])) { // проверяем наличие дополнительных полей для структуры
foreach (Cot::$extrafields[Cot::$db->structure] as $exfld) { // проходим по каждому дополнительному полю
$uname = strtoupper($exfld['field_name']); // имя поля в верхнем регистре
$exfld_title = cot_extrafield_title($exfld, 'structure_'); // получаем название дополнительного поля
$t->assign([ // передаем данные дополнительных полей в шаблон
'LIST_CAT_ROW_' . $uname . '_TITLE' => $exfld_title,
'LIST_CAT_ROW_' . $uname => cot_build_extrafields_data('structure', $exfld,
Cot::$structure['page'][$x][$exfld['field_name']]),
'LIST_CAT_ROW_' . $uname . '_VALUE' => Cot::$structure['page'][$x][$exfld['field_name']],
]);
if (isset(Cot::$cfg['legacyMode']) && Cot::$cfg['legacyMode']) { // если включен legacyMode
// @deprecated in 0.9.24
$t->assign([ // для устаревшей версии присваиваем данные с другим набором переменных
'LIST_ROWCAT_' . $uname . '_TITLE' => $exfld_title,
'LIST_ROWCAT_' . $uname => cot_build_extrafields_data('structure', $exfld,
Cot::$structure['page'][$x][$exfld['field_name']]),
'LIST_ROWCAT_' . $uname . '_VALUE' => Cot::$structure['page'][$x][$exfld['field_name']],
]);
}
}
}
/* === Hook - Part2 : Include === */
foreach ($extp as $pl) { // подключаем плагины, если они есть
include $pl; // подключаем каждый плагин
}
/* ===== */
$t->parse('MAIN.LIST_CAT_ROW'); // рендерим текущий элемент в шаблон
}
$pagenav_cat = cot_pagenav( // вызываем функцию пагинации
'page', // тип страницы (может быть "page" для страницы)
$list_url_path + ['d' => $durl], // путь для навигации, с добавлением параметра durl
$dc, // текущая страница
count($allsub), // общее количество элементов
Cot::$cfg['page']['maxlistsperpage'], // максимальное количество элементов на странице
'dc' // переменная для пагинации
);
if (isset(Cot::$cfg['legacyMode']) && Cot::$cfg['legacyMode']) { // проверяем, включен ли legacy режим
// @deprecated in 0.9.24
$t->assign([ // передаем данные пагинации в шаблон для старой версии
'LISTCAT_PAGNAV' => $pagenav_cat['main'], // основная пагинация
'LISTCAT_PAGEPREV' => $pagenav_cat['prev'], // ссылка на предыдущую страницу
'LISTCAT_PAGENEXT' => $pagenav_cat['next'], // ссылка на следующую страницу
'LISTCAT_CURRENTPAGE' => $pagenav_cat['current'], // текущая страница
'LISTCAT_TOTALLINES' => count($allsub), // общее количество элементов
'LISTCAT_MAXPERPAGE' => Cot::$cfg['page']['maxlistsperpage'], // максимальное количество элементов на странице
'LISTCAT_TOTALPAGES' => $pagenav_cat['total'], // общее количество страниц
]);
}
$t->assign(cot_generatePaginationTags($pagenav_cat, 'LIST_CAT_')); // генерируем и передаем дополнительные теги для пагинации
$jj = 0; // счетчик для записи
/* === Hook - Part1 : Set === */
$extp = cot_getextplugins('page.list.loop'); // получаем плагины для цикла страниц
/* ===== */
$sqllist_rowset = $sqllist->fetchAll(); // получаем все записи из SQL-запроса
$sqllist_rowset_other = false; // флаг для проверки других записей
/* === Hook === */
foreach (cot_getextplugins('page.list.before_loop') as $pl) { // перед циклом выполняются плагины
include $pl; // включаем каждый плагин
}
/* ===== */
if (!$sqllist_rowset_other) { // если нет других записей
// Validate/Unvalidate page actions are in admin controller. We need to redirect back.
$urlParams = $list_url_path; // параметры URL для пагинации
if ($durl > 1) { // если durl больше 1, добавляем параметр
$urlParams['d'] = $durl;
}
if ($dcurl > 1) { // если dcurl больше 1, добавляем параметр
$urlParams['dc'] = $dcurl;
}
$backUrl = cot_url('page', $urlParams, '', true); // создаем URL для возврата
foreach ($sqllist_rowset as $pag) { // перебираем страницы из запроса
$jj++; // увеличиваем счетчик
$t->assign( // передаем данные в шаблон для генерации тега страницы
cot_generate_pagetags(
$pag,
'LIST_ROW_',
$pageListTruncateText,
Cot::$usr['isadmin'],
false,
'',
$backUrl
)
);
$t->assign([ // передаем дополнительные данные в шаблон
'LIST_ROW_OWNER' => cot_build_user($pag['page_ownerid'], $pag['user_name']), // создаем тег владельца
'LIST_ROW_ODDEVEN' => cot_build_oddeven($jj), // создаем тег для четности/нечетности строк
'LIST_ROW_NUM' => $jj, // номер строки
]);
$t->assign(cot_generate_usertags($pag, 'LIST_ROW_OWNER_')); // генерируем теги для пользователя
/* === Hook - Part2 : Include === */
foreach ($extp as $pl) { // после выполнения основного кода запускаем дополнительные плагины
include $pl; // подключаем плагин
}
/* ===== */
$t->parse('MAIN.LIST_ROW'); // парсим шаблон для текущей строки
}
}
// Error and message handling
cot_display_messages($t); // отображаем сообщения об ошибках и другие уведомления на странице
/* === Hook === */
foreach (cot_getextplugins('page.list.tags') as $pl) { // выполняем плагины для тегов страницы
include $pl; // подключаем каждый плагин
}
/* ===== */
$t->parse('MAIN'); // парсим шаблон 'MAIN'
$t->out('MAIN'); // выводим содержимое шаблона 'MAIN'
require_once Cot::$cfg['system_dir'] . '/footer.php'; // подключаем файл footer.php для вывода футера страницы
if (Cot::$cache && $usr['id'] === 0 && Cot::$cfg['cache_page']) { // проверка, если включен кэш и пользователь не авторизован
Cot::$cache->static->write(); // записываем кэш статической страницы
}