Файл page.functions.php в Cotonti
содержит функции, которые используются для генерации списков страниц, фильтрации контента, работы с категориями, сортировки страниц, а также для выполнения кэширования запросов
Описание файла "page.functions.php" в Cotonti CMF
1. Основное назначение и место в системе Cotonti
Файл "page.functions.php" в системе Cotonti находится в директории /modules/page/inc и выполняет роль вспомогательного скрипта для работы с функционалом страниц (page module). Этот файл содержит функции, которые используются для генерации списков страниц, фильтрации контента, работы с категориями, сортировки страниц, а также для выполнения кэширования запросов. Он служит для создания динамических частей страниц, таких как списки, категории и элементы навигации, а также для реализации взаимодействия с базой данных.
Файл тесно интегрирован с другими модулями системы Cotonti, такими как пользовательская авторизация, кэширование, комментарии и другие плагины.
2. Взаимодействие внутри сайта
Внутри сайта этот файл используется для динамического вывода контента, связанного с страницами. Он формирует запросы к базе данных для получения данных о страницах, их категориях, а также выполняет отображение этих данных в формате HTML через шаблоны. Пример использования — это отображение списка страниц в административной части сайта или на публичной части сайта.
Файл использует систему шаблонов XTemplate, которая позволяет выводить данные на основе HTML-шаблонов. Он также может работать с другими модулями, такими как комментарии, подключая их к страницам.
3. Переменные, хуки, методы, функции, классы
Переменные:
- $categories — Строка или массив, который содержит коды категорий для фильтрации страниц. Влияет на то, какие страницы будут выбраны.
- $count — Количество элементов, которые нужно отобразить. Если 0, то выводятся все страницы.
- $template — Путь к шаблону, который используется для отображения данных.
- $order — Параметр для сортировки страниц в SQL-запросе.
- $condition — Дополнительные условия для выборки страниц.
- $active_only — Параметр, ограничивающий выборку только активными страницами.
- $use_subcat — Включает ли подкатегории в выборку.
- $exclude_current — Исключает текущую страницу из выборки.
- $blacklist — Список категорий, которые нужно исключить из выборки.
- $pagination — Строка для настройки постраничной навигации.
- $cache_ttl — Время жизни кэша для запроса в секундах.
Хуки:
- cot_getextplugins('page.enum.query') — Хук для расширения запроса к базе данных.
- cot_getextplugins('page.enum.loop') — Хук для расширения цикла перебора страниц.
- cot_getextplugins('page.enum.tags') — Хук для расширения тегов, которые используются в шаблоне.
Методы и функции:
- cot_structure_children() — Получает подкатегории для указанной категории.
- cot_generate_pagetags() — Генерирует теги для страницы (мета-информация, URL и т. д.).
- cot_generate_usertags() — Генерирует теги для пользователя, связанного с текущей страницей.
- cot_comments_link() — Получает ссылку на комментарии для страницы, если плагин комментариев активен.
- cot_comments_count() — Получает количество комментариев для страницы.
- cot_pagenav() — Формирует строку для постраничной навигации.
Классы:
- XTemplate — Класс, который используется для обработки шаблонов и вывода HTML-контента на основе данных, полученных в процессе выполнения функций.
4. Суть содержания кода и выполняемые задачи
Файл "page.functions.php" включает несколько ключевых задач:
-
Фильтрация страниц по категориям: В зависимости от переданных параметров, код извлекает страницы из определенных категорий, включая или исключая подкатегории, фильтруя по состоянию активности и дате публикации.
-
Работа с кэшированием: В случае, если включен кэш и задано время его жизни, файл кэширует результаты запросов, что позволяет ускорить выполнение запросов при повторных обращениях.
-
Генерация динамического контента: Через шаблон XTemplate происходит генерация HTML-разметки для отображения страниц. Включает в себя перебор данных о страницах и вывод информации о них в соответствующих тегах (например, мета-информация, ссылки на страницы, комментарии).
-
Постраничная навигация: Файл формирует постраничную навигацию для списков страниц, чтобы ограничить количество отображаемых элементов на одной странице.
-
Работа с комментариями: Если плагин комментариев активен, код подключает данные о комментариях для каждой страницы и выводит ссылки на них, а также количество комментариев.
-
Расширяемость через хуки: Код предоставляет возможность расширять его функциональность через хуки, которые могут добавлять дополнительные данные, фильтрации, теги и обработчики.
5. Как использовать этот сценарий владельцу сайта
Владелец сайта может использовать данный файл для:
-
Вывод списка страниц: Он может использовать функцию cot_page_enum() для генерации списка страниц на сайте. Например, для вывода всех страниц в определенной категории или для создания меню с динамическим содержимым.
-
Настройка вывода информации: Благодаря передаче параметров, таких как сортировка, фильтрация по категориям или по статусу, владелец может настроить, какие страницы и как будут отображаться на сайте.
-
Оптимизация с помощью кэширования: Используя кэш, владельцы сайтов могут ускорить выполнение страниц, уменьшая нагрузку на базу данных при повторных запросах.
-
Интеграция с комментариями: При активированном плагине комментариев владелец может легко интегрировать систему комментариев для каждой страницы, автоматически выводя количество комментариев и ссылки на них.
-
Постраничная навигация: Владелец сайта может настроить отображение большого количества страниц с помощью постраничной навигации, что улучшает UX при просмотре контента.
В целом, данный файл является мощным инструментом для управления содержимым сайта и позволяет владельцу гибко настраивать вывод страниц, используя систему фильтрации и сортировки.
<?php
/**
* Page API
*
* @package Page
* @copyright (c) Cotonti Team
* @license https://github.com/Cotonti/Cotonti/blob/master/License.txt
*/
use cot\extensions\ExtensionsService; // Подключение пространства имен для работы с расширениями
defined('COT_CODE') or die('Wrong URL.'); // Проверка на корректность URL-адреса для предотвращения прямого доступа к файлу
// Requirements
require_once cot_langfile('page', 'module'); // Подключение языкового файла модуля "page"
require_once cot_incfile('page', 'module', 'resources'); // Подключение ресурсов модуля "page"
require_once cot_incfile('forms'); // Подключение функционала работы с формами
require_once cot_incfile('extrafields'); // Подключение функционала для работы с дополнительными полями
/*
* Page States
* 0 - опубликована
* 1 - ожидает утверждения администратором (модератором)
* 2 - черновик
*/
const COT_PAGE_STATE_PUBLISHED = 0; // Константа для состояния "опубликована"
const COT_PAGE_STATE_PENDING = 1; // Константа для состояния "ожидает утверждения"
const COT_PAGE_STATE_DRAFT = 2; // Константа для состояния "черновик"
// Tables and extras
Cot::$db->registerTable('pages'); // Регистрация таблицы "pages" в базе данных
cot_extrafields_register_table('pages'); // Регистрация дополнительный полей для таблицы "pages"
if (empty(Cot::$structure['page'])) { // Проверка, если структура страницы еще не определена
Cot::$structure['page'] = []; // Инициализация пустого массива для структуры страницы
}
/**
* Обрезает страницу после тега 'more' или после первой страницы (если мультистраничный контент)
*
* @param string $html Тело страницы
* @return string
*/
function cot_cut_more($html) // Функция для обрезки страницы до тега 'more' или до первого разрыва страницы в случае мультистраничного контента
{
$mpos = mb_strpos($html, '<!--more-->'); // Поиск тега <!--more--> в контенте страницы
if ($mpos === false) // Если тег <!--more--> не найден
{
$mpos = mb_strpos($html, '[more]'); // Пытаемся найти альтернативный тег [more]
}
if ($mpos === false) // Если тег [more] также не найден
{
$mpos = mb_strpos($html, '<hr class="more" />'); // Пытаемся найти разрыв страницы <hr class="more" />
}
if ($mpos !== false) // Если хотя бы один из тегов найден
{
$html = mb_substr($html, 0, $mpos); // Обрезаем контент страницы до найденного тега
}
$mpos = mb_strpos($html, 'newpage'); // Ищем тег newpage, который используется для создания новых страниц в мультистраничном контенте
if ($mpos !== false) // Если тег newpage найден
{
$html = mb_substr($html, 0, $mpos); // Обрезаем контент до этого тега
}
if (mb_strpos($html, 'title')) // Проверяем наличие тега title в контенте
{
$html = preg_replace('#\[title\](.*?)\[/title\][\s\r\n]*(<br />)?#i', '', $html); // Удаляем все вхождения тега [title] с его содержимым
}
return $html; // Возвращаем обрезанный HTML-контент
}
- Эта функция выполняет обрезку контента страницы, учитывая различные теги, такие как
<!--more-->,[more],<hr class="more" />, иnewpage, чтобы оставить только часть страницы до этих тегов. - Также удаляется содержимое внутри тегов
title, если они присутствуют в контенте. - Это полезно для разделения страницы на части или создания превью, где только первая часть контента отображается, а остальная скрыта или доступна по ссылке.
/**
* Читает необработанные данные из файла
*
* @param string $file Путь к файлу
* @return string
*/
function cot_readraw($file) // Функция для чтения данных из файла
{
return (mb_strpos($file, '..') === false && file_exists($file)) ? file_get_contents($file) : 'Файл не найден : '.$file; // Если путь не содержит '..' и файл существует, читаем содержимое, иначе выводим сообщение о несуществующем файле
}
/**
* Возвращает все теги страницы для coTemplate
*
* @param int|array $page_data Массив данных страницы или ID
* @param string $tag_prefix Префикс для тегов
* @param int $textLength Длина обрезаемого текста
* @param bool $admin_rights Права администратора страницы
* @param bool $pagepath_home Добавить ссылку на главную в путь страницы
* @param string $emptytitle Текст заголовка страницы, если страница не существует
* @param string $backUrl URL для действий с валидацией страницы
*
* @return array|null
* @global CotDB $db
*/
function cot_generate_pagetags( // Функция для генерации тегов страницы для coTemplate
$page_data, // Данные страницы или её ID
$tag_prefix = '', // Префикс для тегов
$textLength = 0, // Длина для обрезки текста
$admin_rights = null, // Права администратора страницы
$pagepath_home = false, // Добавление ссылки на главную в путь страницы
$emptytitle = '', // Текст заголовка страницы, если страница не существует
$backUrl = null // URL для действия с валидацией
) {
// $L, $Ls, $R нужны для включения хуков
global $L, $Ls, $R, $cfg; // Объявление глобальных переменных для хуков
global $db, $cot_extrafields, $db_pages, $usr, $sys, $cot_yesno, $structure, $db_structure; // Объявление глобальных переменных для базы данных и других системных значений
static $extp_first = null, $extp_main = null; // Статические переменные для плагинов
static $pag_auth = []; // Статический массив для авторизации страницы
if (is_null($extp_first)) { // Если переменная $extp_first ещё не инициализирована
$extp_first = cot_getextplugins('pagetags.first'); // Загружаем плагины для хуков на этапе 'first'
$extp_main = cot_getextplugins('pagetags.main'); // Загружаем плагины для главного этапа
}
/* === Хук === */
foreach ($extp_first as $pl) { // Включаем плагины первого этапа
include $pl; // Подключаем файл плагина
}
/* ===== */
if (!empty($page_data) && !is_array($page_data)) { // Если данные страницы не пусты и не являются массивом
$pageID = (int) $page_data; // Преобразуем $page_data в целое число, если оно не массив
$page_data = null; // Обнуляем переменную $page_data
if ($pageID > 0) { // Если ID страницы больше 0
$sql = Cot::$db->query('SELECT * FROM ' . Cot::$db->pages . ' WHERE page_id = ? LIMIT 1', $pageID); // Выполняем SQL запрос для получения данных страницы по её ID
$page_data = $sql->fetch(); // Извлекаем результат запроса в переменную $page_data
}
}
if (empty($page_data)) { // Если данные страницы пустые
return null; // Возвращаем null, если страница не найдена
}
if ($page_data['page_id'] > 0 && !empty($page_data['page_title'])) { // Если ID страницы больше 0 и есть название страницы
if (is_null($admin_rights)) { // Если права администратора не заданы
if (!isset($pag_auth[$page_data['page_cat']])) { // Если права доступа для категории страницы ещё не установлены
$pag_auth[$page_data['page_cat']] = cot_auth('page', $page_data['page_cat'], 'RWA1'); // Получаем права доступа для указанной категории страницы
}
$admin_rights = (bool) $pag_auth[$page_data['page_cat']][2]; // Устанавливаем флаг прав администратора на основе полученных прав
}
$pagepath = cot_structure_buildpath('page', $page_data['page_cat']); // Строим путь к странице на основе категории
$catpath = cot_breadcrumbs($pagepath, $pagepath_home, false); // Генерируем хлебные крошки для пути к категории
$page_data['page_pageurl'] = cot_page_url($page_data); // Получаем URL страницы
$pageLink = [[$page_data['page_pageurl'], $page_data['page_title']]]; // Создаём массив с URL и заголовком страницы
$breadcrumbs = cot_breadcrumbs(array_merge($pagepath, $pageLink), $pagepath_home); // Генерируем хлебные крошки для страницы
if (!empty($page_data['page_url']) && $page_data['page_file']) { // Если у страницы есть URL и файл
$dotpos = mb_strrpos($page_data['page_url'], ".") + 1; // Находим позицию последней точки в URL
$type = mb_strtolower(mb_substr($page_data['page_url'], $dotpos, 5)); // Получаем расширение файла
$page_data['page_fileicon'] = cot_rc('page_icon_file_path', ['type' => $type]); // Получаем путь к иконке файла на основе расширения
if (!file_exists($page_data['page_fileicon'])) { // Если иконка файла не существует
$page_data['page_fileicon'] = cot_rc('page_icon_file_default'); // Используем иконку по умолчанию
}
$page_data['page_fileicon'] = cot_rc('page_icon_file', ['icon' => $page_data['page_fileicon']]); // Генерируем иконку файла
} else {
$page_data['page_fileicon'] = ''; // Если у страницы нет файла, иконка пустая
}
$date_format = 'datetime_medium'; // Устанавливаем формат даты в 'datetime_medium'
$text = cot_parse($page_data['page_text'], $cfg['page']['markup'], $page_data['page_parser']); // Применяем разметку и парсер к тексту страницы
$text_cut = cot_cut_more($text); // Обрезаем текст после тега 'more' или на первой странице (если многостраничный текст)
if ($textLength > 0 && mb_strlen($text_cut) > $textLength) { // Если задана длина текста и текст больше этой длины
$text_cut = cot_string_truncate($text_cut, $textLength); // Обрезаем текст до указанной длины
}
$cutted = mb_strlen($text) > mb_strlen($text_cut); // Проверяем, был ли текст обрезан
$cat_url = cot_url('page', ['c' => $page_data['page_cat']]); // Формируем URL для категории страницы
$urlParams = [ // Формируем параметры для URL
'm' => 'page', // Указываем модуль страницы
'a' => 'validate', // Указываем действие для валидации
'id' => $page_data['page_id'], // Указываем ID страницы
'x' => Cot::$sys['xk'], // Добавляем токен безопасности
];
if (!empty($backUrl)) { // Если задан URL возврата
$urlParams['back'] = base64_encode($backUrl); // Добавляем параметр для возврата
}
$validate_url = cot_url('admin', $urlParams); // Формируем URL для действия валидации
$urlParams['a'] = 'unvalidate'; // Меняем действие на 'unvalidate' для отмены валидации
$unvalidate_url = cot_url('admin', $urlParams); // Формируем URL для отмены валидации
$edit_url = cot_url('page', "m=edit&id={$page_data['page_id']}"); // Формируем URL для редактирования страницы
$delete_url = cot_url('page', "m=edit&a=update&delete=1&id={$page_data['page_id']}&x={$sys['xk']}"); // Формируем URL для удаления страницы
$page_data['page_status'] = cot_page_status( // Получаем статус страницы (опубликована, на модерации, черновик)
$page_data['page_state'], // Состояние страницы
$page_data['page_begin'], // Дата начала публикации
$page_data['page_expire'] // Дата окончания публикации
);
$haveFile = Cot::$L['No']; // Инициализируем переменную $haveFile значением "No" (по умолчанию файл отсутствует)
$page_data['page_file'] = (int) $page_data['page_file']; // Преобразуем значение 'page_file' в целое число
if ($page_data['page_file'] == 1) { // Если 'page_file' равно 1
$haveFile = Cot::$L['Yes']; // Устанавливаем $haveFile в "Yes" (файл есть)
} elseif ($page_data['page_file'] == 2) { // Если 'page_file' равно 2
$haveFile = Cot::$L['Members_download']; // Устанавливаем $haveFile в "Members_download" (доступно для скачивания только для пользователей)
}
$catTitle = isset($structure['page'][$page_data['page_cat']]['title']) // Проверяем, существует ли заголовок категории страницы
? htmlspecialchars($structure['page'][$page_data['page_cat']]['title']) // Если существует, получаем и экранируем заголовок
: ''; // Если не существует, оставляем пустое значение
$catDescription = isset($structure['page'][$page_data['page_cat']]['desc']) // Проверяем, существует ли описание категории страницы
? $structure['page'][$page_data['page_cat']]['desc'] // Если существует, получаем описание
: ''; // Если не существует, оставляем пустое значение
$pageDescription = (isset($page_data['page_desc']) && $page_data['page_desc'] !== '') // Проверяем, существует ли описание страницы и оно не пустое
? htmlspecialchars($page_data['page_desc']) // Если существует, экранируем описание страницы
: ''; // Если не существует, оставляем пустое значение
$temp_array = [ // Создаем массив с данными страницы
'URL' => $page_data['page_pageurl'], // Ссылка на страницу
'ID' => $page_data['page_id'], // Идентификатор страницы
'TITLE' => htmlspecialchars($page_data['page_title'], ENT_COMPAT, 'UTF-8', false), // Заголовок страницы с экранированием HTML
'BREADCRUMBS' => $breadcrumbs, // Хлебные крошки для страницы
'ALIAS' => $page_data['page_alias'], // Псевдоним страницы
'STATE' => $page_data['page_state'], // Состояние страницы
'STATUS' => $page_data['page_status'], // Статус страницы
'LOCAL_STATUS' => $L['page_status_' . $page_data['page_status']], // Локализованный статус страницы
'CAT' => $page_data['page_cat'], // Категория страницы
'CAT_URL' => $cat_url, // Ссылка на категорию страницы
'CAT_TITLE' => $catTitle, // Название категории страницы
'CAT_PATH' => $catpath, // Путь к категории
'CAT_PATH_SHORT' => cot_rc_link($cat_url, $catTitle), // Краткая версия пути с ссылкой
'CAT_DESCRIPTION' => $catDescription, // Описание категории
'CAT_ICON' => !empty($structure['page'][$page_data['page_cat']]['icon']) // Проверка на наличие иконки категории
? cot_rc(
'img_structure_cat',
[
'icon' => $structure['page'][$page_data['page_cat']]['icon'], // Иконка категории
'title' => $catTitle, // Заголовок категории
'desc' => htmlspecialchars($catDescription), // Описание категории с экранированием
]
)
: '', // Если иконка не указана, пустое значение
'CAT_ICON_SRC' => isset($structure['page'][$page_data['page_cat']]['icon']) // Проверка на наличие источника иконки
? $structure['page'][$page_data['page_cat']]['icon'] // Если есть, возвращаем иконку
: '', // Если нет, пустое значение
'KEYWORDS' => (isset($page_data['page_keywords']) && $page_data['page_keywords'] != '') // Проверка на наличие ключевых слов
? htmlspecialchars($page_data['page_keywords']) // Если есть, экранируем ключевые слова
: '', // Если нет, пустое значение
'DESCRIPTION' => $pageDescription, // Описание страницы
'TEXT' => $text, // Текст страницы
'TEXT_CUT' => $text_cut, // Обрезанный текст
'TEXT_IS_CUT' => $cutted, // Признак, что текст был обрезан
'DESCRIPTION_OR_TEXT' => $pageDescription !== '' ? $pageDescription : $text, // Логика выбора между описанием и текстом
'DESCRIPTION_OR_TEXT_CUT' => $pageDescription !== '' ? $pageDescription : $text_cut, // Логика выбора между описанием и обрезанным текстом
'MORE' => ($cutted) ? cot_rc('list_more', ['page_url' => $page_data['page_pageurl']]) : '', // Кнопка "Еще" для обрезанных текстов
'AUTHOR' => (isset($page_data['page_author']) && $page_data['page_author'] != '') // Проверка на наличие автора страницы
? htmlspecialchars($page_data['page_author']) // Если автор есть, экранируем
: '', // Если автора нет, пустое значение
'OWNER_ID' => $page_data['page_ownerid'], // Идентификатор владельца страницы
'OWNER_NAME' => (isset($page_data['user_name']) && $page_data['user_name'] != '') // Проверка на имя владельца страницы
? htmlspecialchars($page_data['user_name']) // Если имя пользователя есть, экранируем
: '', // Если нет, пустое значение
'CREATED' => cot_date($date_format, $page_data['page_date']), // Дата создания страницы
'BEGIN' => cot_date($date_format, $page_data['page_begin']), // Дата начала действия страницы
'EXPIRE' => cot_date($date_format, $page_data['page_expire']), // Дата истечения срока действия страницы
'UPDATED' => cot_date($date_format, $page_data['page_updated']), // Дата последнего обновления страницы
'CREATED_STAMP' => $page_data['page_date'], // Метка времени для даты создания
'BEGIN_STAMP' => $page_data['page_begin'], // Метка времени для начала действия
'EXPIRE_STAMP' => $page_data['page_expire'], // Метка времени для истечения срока действия
'UPDATED_STAMP' => $page_data['page_updated'], // Метка времени для обновления страницы
'FILE' => $haveFile, // Статус наличия файла
'FILE_URL' => !empty($page_data['page_url']) // Проверка на наличие URL файла
? cot_url('page', ['c' => $page_data['page_cat'], 'id' => $page_data['page_id'], 'a' => 'dl']) // Ссылка на файл для скачивания
: '', // Если нет файла, пустое значение
'FILE_SIZE' => $page_data['page_size'] / 1024, // Размер файла в КБ (устаревшая версия для совместимости)
'FILE_SIZE_BYTES' => $page_data['page_size'], // Размер файла в байтах
'FILE_SIZE_READABLE' => cot_build_filesize($page_data['page_size'], 1), // Читаемый размер файла
'FILE_ICON' => $page_data['page_fileicon'], // Иконка файла
'FILE_DOWNLOADS' => $page_data['page_filecount'], // Количество скачиваний файла
'FILE_DOWNLOADS_TIMES' => cot_declension($page_data['page_filecount'], $Ls['Times']), // Скачивания с учетом склонений
'FILE_NAME' => !empty($page_data['page_url']) ? basename($page_data['page_url']) : '', // Имя файла
'HITS' => $page_data['page_count'], // Количество просмотров страницы
'ADMIN' => $admin_rights // Права администратора
? cot_rc('list_row_admin', ['unvalidate_url' => $unvalidate_url, 'edit_url' => $edit_url]) // Выводим ссылки на редактирование и отмену валидации
: '', // Если нет прав администратора, пустое значение
'NOT_AVAILABLE' => ($page_data['page_begin'] > Cot::$sys['now']) // Проверка на доступность страницы
? Cot::$L['page_notavailable'] . cot_build_timegap(Cot::$sys['now'], $page_data['page_begin']) // Сообщение о недоступности с таймером
: '', // Если страница доступна, пустое значение
];
if (isset(Cot::$cfg['legacyMode']) && Cot::$cfg['legacyMode']) { // Проверка, включен ли режим устаревания в конфигурации.
// @deprecated in 0.9.24
$temp_array += [ // Объединение дополнительных данных в массив $temp_array для режима устаревания
'SHORTTITLE' => htmlspecialchars($page_data['page_title'], ENT_COMPAT, 'UTF-8', false), // Краткое название страницы
'LOCALSTATUS' => $L['page_status_' . $page_data['page_status']], // Локализованный статус страницы (из языкового файла)
'CATURL' => $cat_url, // URL категории
'CATTITLE' => $catTitle, // Название категории
'CATPATH' => $catpath, // Путь категории
'CATPATH_SHORT' => cot_rc_link($cat_url, $catTitle), // Краткая ссылка на путь категории
'CATDESC' => (isset($structure['page'][$page_data['page_cat']]['desc'])
&& $structure['page'][$page_data['page_cat']]['desc'] != '') ?
htmlspecialchars($structure['page'][$page_data['page_cat']]['desc']) : '', // Описание категории, если оно есть
'CATICON' => isset($structure['page'][$page_data['page_cat']]['icon']) ?
$structure['page'][$page_data['page_cat']]['icon'] : '', // Иконка категории, если она есть
'OWNERID' => $page_data['page_ownerid'], // ID владельца страницы
'OWNERNAME' => (isset($page_data['user_name']) && $page_data['user_name'] != '') ?
htmlspecialchars($page_data['user_name']) : '', // Имя владельца, если оно есть
'DESC' => (isset($page_data['page_desc']) && $page_data['page_desc'] != '') ?
htmlspecialchars($page_data['page_desc']) : '', // Описание страницы, если оно есть
'DESC_OR_TEXT' => (isset($page_data['page_desc']) && $page_data['page_desc'] != '') ?
htmlspecialchars($page_data['page_desc']) : $text, // Если описание доступно, используется оно, иначе используется текст
'DESC_OR_TEXT_CUT' => (isset($page_data['page_desc']) && $page_data['page_desc'] != '') ?
htmlspecialchars($page_data['page_desc']) : $text_cut, // То же, что и DESC_OR_TEXT, но с урезанной версией
'DATE' => cot_date($date_format, $page_data['page_date']), // Дата создания страницы
'DATE_STAMP' => $page_data['page_date'], // Временная метка даты создания страницы
'FILE_COUNT' => $page_data['page_filecount'], // Количество файлов, прикрепленных к странице
'FILE_COUNTTIMES' => cot_declension($page_data['page_filecount'], $Ls['Times']), // Описание количества файлов во множественном числе
'COUNT' => $page_data['page_count'], // Количество просмотров страницы
'NOTAVAILABLE' => ($page_data['page_begin'] > Cot::$sys['now']) // Если страница еще не доступна
? Cot::$L['page_notavailable'] . cot_build_timegap(Cot::$sys['now'], $page_data['page_begin']) // Показывает временной промежуток до доступности
: '', // В противном случае, пустая строка
];
}
// Admin tags
if ($admin_rights) { // Если у пользователя есть права администратора
$validate_confirm_url = cot_confirm_url($validate_url, 'page', 'page_confirm_validate'); // Генерация URL для подтверждения валидации страницы
$unvalidate_confirm_url = cot_confirm_url($unvalidate_url, 'page', 'page_confirm_unvalidate'); // Генерация URL для подтверждения отмены валидации страницы
$delete_confirm_url = cot_confirm_url($delete_url, 'page', 'page_confirm_delete'); // Генерация URL для подтверждения удаления страницы
$temp_array['ADMIN_EDIT'] = cot_rc_link($edit_url, Cot::$L['Edit']); // Ссылка на редактирование страницы
$temp_array['ADMIN_EDIT_URL'] = $edit_url; // URL для редактирования страницы
$temp_array['ADMIN_UNVALIDATE'] = $page_data['page_state'] == COT_PAGE_STATE_PENDING ? // Если страница в ожидании, ссылка для подтверждения валидации
cot_rc_link($validate_confirm_url, Cot::$L['Validate'], 'class="confirmLink"') :
cot_rc_link($unvalidate_confirm_url, Cot::$L['Putinvalidationqueue'], 'class="confirmLink"'); // Ссылка для отмены валидации или постановки в очередь на валидацию
$temp_array['ADMIN_UNVALIDATE_URL'] = $page_data['page_state'] == 1 ? // Если страница активна, URL для подтверждения валидации
$validate_confirm_url : $unvalidate_confirm_url; // URL для подтверждения отмены валидации
$temp_array['ADMIN_DELETE'] = cot_rc_link($delete_confirm_url, $L['Delete'], 'class="confirmLink"'); // Ссылка для удаления страницы
$temp_array['ADMIN_DELETE_URL'] = $delete_confirm_url; // URL для удаления страницы
} elseif ($usr['id'] == $page_data['page_ownerid']) { // Если пользователь является владельцем страницы
$temp_array['ADMIN_EDIT'] = cot_rc_link($edit_url, $L['Edit']); // Ссылка на редактирование страницы для владельца
$temp_array['ADMIN_EDIT_URL'] = $edit_url; // URL для редактирования страницы
}
if (cot_auth('page', 'any', 'W')) { // Если пользователь имеет права на запись (W) для страниц
$clone_url = cot_url('page', "m=add&c={$page_data['page_cat']}&clone={$page_data['page_id']}"); // Генерация URL для клонирования страницы
$temp_array['ADMIN_CLONE'] = cot_rc_link($clone_url, $L['page_clone']); // Ссылка для клонирования страницы
$temp_array['ADMIN_CLONE_URL'] = $clone_url; // URL для клонирования страницы
}
// Extrafields
if (!empty(Cot::$extrafields[Cot::$db->pages])) { // Если есть дополнительные поля для страниц
foreach (Cot::$extrafields[Cot::$db->pages] as $exfld) { // Проходим по всем дополнительным полям
$tag = mb_strtoupper($exfld['field_name']); // Преобразуем имя поля в верхний регистр
$exfld_title = cot_extrafield_title($exfld, 'page_'); // Получаем название поля
$temp_array[$tag . '_TITLE'] = $exfld_title; // Сохраняем название поля
$temp_value = null; // Инициализация переменной для хранения значения поля
if (isset($page_data['page_'.$exfld['field_name']])) { // Если значение поля существует
$temp_value = $page_data['page_'.$exfld['field_name']]; // Присваиваем его переменной
}
$temp_array[$tag] = cot_build_extrafields_data('page', $exfld, $temp_value, $page_data['page_parser']); // Строим данные для поля
$temp_array[$tag . '_VALUE'] = $temp_value; // Сохраняем значение поля
}
}
// Extra fields for structure
if (isset(Cot::$extrafields[Cot::$db->structure])) { // Если есть дополнительные поля для структуры
foreach (Cot::$extrafields[Cot::$db->structure] as $exfld) { // Проходим по всем дополнительным полям структуры
$tag = mb_strtoupper($exfld['field_name']); // Преобразуем имя поля в верхний регистр
$exfld_title = cot_extrafield_title($exfld, 'structure_'); // Получаем название поля
$temp_array['CAT_' . $tag . '_TITLE'] = $exfld_title; // Сохраняем название поля
$temp_value = null; // Инициализация переменной для хранения значения поля
if (isset(Cot::$structure['page'][$page_data['page_cat']][$exfld['field_name']])) { // Если значение поля существует
$temp_value = Cot::$structure['page'][$page_data['page_cat']][$exfld['field_name']]; // Присваиваем его переменной
}
$temp_array['CAT_' . $tag] = cot_build_extrafields_data('structure', $exfld, $temp_value); // Строим данные для поля структуры
$temp_array['CAT_' . $tag.'_VALUE'] = $temp_value; // Сохраняем значение поля структуры
}
}
/* === Hook === */
foreach ($extp_main as $pl) { // Выполняем все хуки
include $pl; // Подключаем каждый плагин
}
/* ===== */
Здесь добавляются дополнительные поля для страниц и структуры. Если для страниц или структуры есть дополнительные поля, они обрабатываются, и значения полей сохраняются в массив $temp_array. Также для каждого поля генерируется соответствующий тег и сохраняются значения, если они существуют. В конце выполняются хуки, подключая соответствующие плагины для обработки
} else {
$temp_array = [ // Если страница не найдена, создаем массив с данными для ответа
'TITLE' => (!empty($emptytitle)) ? $emptytitle : Cot::$L['Deleted'], // Заголовок страницы или текст "Удалено"
];
if (isset(Cot::$cfg['legacyMode']) && Cot::$cfg['legacyMode']) { // Если включен режим совместимости
// @deprecated in 0.9.24
$temp_array += [ // Добавляем в массив дополнительные данные
'SHORTTITLE' => (!empty($emptytitle)) ? $emptytitle : Cot::$L['Deleted'], // Короткий заголовок страницы или текст "Удалено"
];
}
}
$return_array = []; // Инициализируем массив для возвращаемых данных
foreach ($temp_array as $key => $val) { // Проходим по всем элементам массива $temp_array
$return_array[$tag_prefix . $key] = $val; // Добавляем префикс к ключам и сохраняем в $return_array
}
return $return_array; // Возвращаем массив с результатами
/**
* Возможные значения для порядка сортировки категорий
* @param bool $adminpart Вызов из административной части
* @return array
*/
function cot_page_config_order($adminpart = false)
{
global $cot_extrafields, $L, $db_pages;
$options_sort = array( // Массив с возможными параметрами сортировки
'id' => $L['Id'], // ID
'title' => $L['Title'], // Заголовок
'desc' => $L['Description'], // Описание
'text' => $L['Body'], // Тело
'author' => $L['Author'], // Автор
'ownerid' => $L['Owner'], // Владелец
'date' => $L['Date'], // Дата
'begin' => $L['Begin'], // Начало
'expire' => $L['Expire'], // Истечение
'file' => $L['adm_fileyesno'], // Файл (да/нет)
'url' => $L['adm_fileurl'], // URL файла
'size' => $L['adm_filesize'], // Размер файла
'filecount' => $L['adm_filecount'], // Количество файлов
'count' => $L['Count'], // Количество просмотров
'updated' => $L['Updated'], // Обновлено
'cat' => $L['Category'] // Категория
);
// Добавление экстраполяции полей
foreach($cot_extrafields[$db_pages] as $exfld)
{
$options_sort[$exfld['field_name']] = isset($L['page_'.$exfld['field_name'].'_title'])
? $L['page_'.$exfld['field_name'].'_title']
: $exfld['field_description']; // Добавляем поле экстрафайла, если оно существует
}
// Возвращаем массив в зависимости от контекста (админская часть или обычная версия)
if ($adminpart || version_compare('0.9.19', Cot::$cfg['version']) < 1)
{
return $options_sort; // Возвращаем весь массив для административной части
}
else
{
// Старый стиль, будет удален в следующих версиях
$L['cfg_order_params'] = array_values($options_sort); // Обновляем локализацию
return array_keys($options_sort); // Возвращаем только ключи массива для старой версии
}
}
В этой функции создается массив с возможными значениями для сортировки категорий страниц в Cotonti. В зависимости от контекста (админская часть или версия Cotonti) возвращается либо полный массив с параметрами, либо только его ключи, если версия старее 0.9.19.
/**
* Определяет статус страницы
*
* @param int $page_state Статус страницы (0 - опубликована, 2 - черновик, 1 - ожидает подтверждения)
* @param int $page_begin Время начала действия страницы
* @param int $page_expire Время истечения действия страницы
* @return string 'draft', 'pending', 'approved', 'published' или 'expired'
*/
function cot_page_status($page_state, $page_begin, $page_expire)
{
global $sys;
if ($page_state == 0) // Если статус страницы - опубликована
{
if ($page_expire > 0 && $page_expire <= $sys['now']) // Если страница устарела
{
return 'expired'; // Страница истекла
}
elseif ($page_begin > $sys['now']) // Если дата начала действия страницы в будущем
{
return 'approved'; // Страница одобрена, но еще не опубликована
}
return 'published'; // Страница опубликована
}
elseif ($page_state == 2) // Если статус страницы - черновик
{
return 'draft'; // Черновик
}
return 'pending'; // Страница ожидает подтверждения
}
Эта функция определяет статус страницы в зависимости от ее состояния, времени начала и времени истечения действия. Она возвращает один из следующих статусов: draft (черновик), pending (ожидает подтверждения), approved (одобрена), published (опубликована) или expired (истекла).
/**
* Возвращает количество страниц в категории
* Используется в Админ/Структура/Пересинхронизация всех
*
* @param string $category Код категории
* @return int Количество страниц в категории
*/
function cot_page_sync($category)
{
if (empty($category)) { // Если категория пуста
return 0; // Возвращаем 0, так как категории нет
}
// Выполняем запрос для подсчета количества страниц в данной категории
return (int) Cot::$db->query(
'SELECT COUNT(*) FROM ' . Cot::$db->quoteTableName(Cot::$db->pages) . // Выполняем запрос к таблице страниц
' WHERE page_cat=?', // Фильтруем по категории
$category // Передаем параметр категории
)->fetchColumn(); // Получаем количество страниц и возвращаем
}
Эта функция выполняет SQL-запрос, чтобы получить количество страниц в указанной категории. Если категория пуста, функция возвращает 0
/**
* Пересчитывает и обновляет счетчики для структуры
* @param string $category Код категории
* @return void
*/
function cot_page_updateStructureCounters($category)
{
// Проверяем, если категория пуста или структура страницы для этой категории не существует
if (empty($category) || empty(Cot::$structure['page'][$category])) {
return; // Прерываем выполнение функции, если условие выполнено
}
// Получаем количество страниц в указанной категории
$count = cot_page_sync($category);
// Обновляем поле structure_count в таблице structure для данной категории
Cot::$db->query('UPDATE ' . Cot::$db->quoteTableName(Cot::$db->structure) .
' SET structure_count = ' . $count . // Устанавливаем новое значение счетчика
" WHERE structure_area='page' AND structure_code = :category", ['category' => $category]); // Указываем категорию для обновления
// Проверяем, используется ли кеширование
if (Cot::$cache) {
// Если используется кеш, удаляем старый кеш для структуры
Cot::$cache->db->remove('structure', 'system');
}
}
/**
* Обновляет код категории страницы
*
* @param string $oldcat Старый код категории
* @param string $newcat Новый код категории
* @return bool Результат операции (успешно или нет)
* @global CotDB $db Доступ к базе данных
*/
function cot_page_updatecat($oldcat, $newcat)
{
// Получаем глобальный доступ к объекту базы данных
global $db, $db_structure, $db_pages;
// Выполняем обновление страницы в таблице страниц, изменяя категорию на новую
return (bool) $db->update(
$db_pages, // Таблица, в которой будет происходить обновление
array("page_cat" => $newcat), // Устанавливаем новый код категории
"page_cat='".$db->prep($oldcat)."'" // Условие для обновления: старая категория
);
}
/**
* URL-адрес страницы
*
* @param array $data Данные страницы в виде массива
* @param array $params Дополнительные параметры URL
* @param string $tail Постфикс URL, например, якорь
* @param bool $htmlspecialcharsBypass Если TRUE, символы типа & не будут преобразовываться в & и так далее
* @param bool $ignoreAppendix Если TRUE, $cot_url_appendix будет проигнорирован для этого URL
* @return string Валидный HTTP URL
*/
function cot_page_url($data, $params = [], $tail = '', $htmlspecialcharsBypass = false, $ignoreAppendix = false)
{
// Создаем базовые параметры URL с категорией страницы
$urlParams = ['c' => $data['page_cat']];
// Если у страницы есть alias (псевдоним), добавляем его в параметры URL
if (!empty($data['page_alias'])) {
$urlParams['al'] = $data['page_alias'];
}
// Если псевдонима нет, но есть ID страницы, добавляем ID в параметры URL
elseif (!empty($data['page_id'])) {
$id = (int) $data['page_id']; // Преобразуем ID в целое число
if ($id <= 0) { // Если ID некорректен (меньше или равно 0), возвращаем пустую строку
return '';
}
$urlParams['id'] = $id;
} else { // Если у страницы нет ни псевдонима, ни ID, возвращаем пустую строку
return '';
}
// Если переданы дополнительные параметры, объединяем их с основными
if (!empty($params)) {
$urlParams = array_merge($urlParams, $params);
}
// Генерируем финальный URL, вызывая функцию cot_url с собранными параметрами
return cot_url('page', $urlParams, $tail, $htmlspecialcharsBypass, $ignoreAppendix);
}
/**
* Возвращает разрешения для категории страницы.
* @param string $cat Код категории
* @return array Массив разрешений с ключами: 'auth_read', 'auth_write', 'isadmin', 'auth_download'
*/
function cot_page_auth($cat = null)
{
// Если категория не передана, по умолчанию устанавливаем значение 'any'
if (empty($cat))
{
$cat = 'any';
}
// Инициализируем массив для разрешений
$auth = array();
// Получаем разрешения для категории страницы, используя функцию cot_auth
// 'RWA1' указывает на типы разрешений: чтение, запись, администрирование и скачивание
list($auth['auth_read'], $auth['auth_write'], $auth['isadmin'], $auth['auth_download']) = cot_auth('page', $cat, 'RWA1');
// Возвращаем массив разрешений
return $auth;
}
/**
* Импортирует данные страницы из параметров запроса.
* @param string $source Источник запроса для параметров
* @param array $rpage Данные существующей страницы из базы данных
* @param array $auth Массив разрешений
* @return array Данные страницы
*/
function cot_page_import($source = 'POST', $rpage = [], $auth = [])
{
global $cfg, $db_pages, $cot_extrafields, $usr, $sys;
// Если массив разрешений пуст, получаем разрешения для категории страницы
if (count($auth) == 0) {
$auth = cot_page_auth($rpage['page_cat']);
}
// Если источник данных - 'D' или 'DIRECT', используем 'PATCH' и устанавливаем глобальную переменную $_PATCH
if ($source == 'D' || $source == 'DIRECT') {
// Хитрость, чтобы не затрагивать каждую строку ниже
global $_PATCH;
$_PATCH = $rpage;
$source = 'PATCH';
}
// Импортируем данные страницы из параметров запроса
$rpage['page_cat'] = cot_import('rpagecat', $source, 'TXT'); // Код категории
$rpage['page_keywords'] = cot_import('rpagekeywords', $source, 'TXT'); // Ключевые слова
$rpage['page_alias'] = cot_import('rpagealias', $source, 'TXT'); // Псевдоним
$rpage['page_title'] = cot_import('rpagetitle', $source, 'TXT'); // Заголовок
$rpage['page_desc'] = cot_import('rpagedesc', $source, 'TXT'); // Описание
$rpage['page_text'] = cot_import('rpagetext', $source, 'HTM'); // Текст
$rpage['page_parser'] = cot_import('rpageparser', $source, 'ALP'); // Парсер
$rpage['page_author'] = cot_import('rpageauthor', $source, 'TXT'); // Автор
$rpage['page_file'] = intval(cot_import('rpagefile', $source, 'INT')); // Файл (если есть)
$rpage['page_url'] = cot_import('rpageurl', $source, 'TXT'); // URL
$rpage['page_size'] = (int) cot_import('rpagesize', $source, 'INT'); // Размер
$rpage['page_file'] = ($rpage['page_file'] == 0 && !empty($rpage['page_url'])) ? 1 : $rpage['page_file']; // Если файла нет, но есть URL, ставим значение 1
// Определяем текущую дату страницы
$rpagedatenow = cot_import('rpagedatenow', $source, 'BOL'); // Признак "текущая дата"
$rpage['page_date'] = cot_import_date('rpagedate', true, false, $source); // Дата
$rpage['page_date'] = ($rpagedatenow || is_null($rpage['page_date'])) ? $sys['now'] : (int) $rpage['page_date']; // Если дата не указана или установлена текущая, используем системную
$rpage['page_begin'] = (int) cot_import_date('rpagebegin'); // Дата начала
$rpage['page_expire'] = (int) cot_import_date('rpageexpire'); // Дата окончания
$rpage['page_expire'] = ($rpage['page_expire'] <= $rpage['page_begin']) ? 0 : $rpage['page_expire']; // Если дата окончания раньше начала, ставим 0
$rpage['page_updated'] = $sys['now']; // Дата обновления
// Импортируем дополнительные метаданные
$rpage['page_keywords'] = cot_import('rpagekeywords', $source, 'TXT'); // Ключевые слова
$rpage['page_metatitle'] = cot_import('rpagemetatitle', $source, 'TXT'); // Мета-заголовок
$rpage['page_metadesc'] = cot_import('rpagemetadesc', $source, 'TXT'); // Мета-описание
// Для совместимости с предыдущими версиями
$rpublish = cot_import('rpublish', $source, 'ALP');
$rpage['page_state'] = ($rpublish == 'OK') ? 0 : cot_import('rpagestate', $source, 'INT'); // Состояние страницы (опубликована или нет)
// Если пользователь является администратором, разрешаем редактирование дополнительных полей
if ($auth['isadmin'] && isset($rpage['page_ownerid'])) {
$rpage['page_count'] = cot_import('rpagecount', $source, 'INT'); // Количество
$rpage['page_ownerid'] = cot_import('rpageownerid', $source, 'INT'); // ID владельца
$rpage['page_filecount'] = cot_import('rpagefilecount', $source, 'INT'); // Количество файлов
} else {
$rpage['page_ownerid'] = Cot::$usr['id']; // Устанавливаем владельца страницы
}
// Получаем список доступных парсеров
$parser_list = cot_get_parsers();
// Проверяем, что выбранный парсер корректен, если нет, используем дефолтный
if (
empty($rpage['page_parser'])
|| !in_array($rpage['page_parser'], $parser_list)
|| $rpage['page_parser'] != 'none'
&& !cot_auth('plug', $rpage['page_parser'], 'W')
) {
$rpage['page_parser'] = isset(Cot::$sys['parser']) ? Cot::$sys['parser'] : Cot::$cfg['page']['parser']; // Устанавливаем парсер по умолчанию
}
// Обрабатываем дополнительные поля
if (!empty(Cot::$extrafields[Cot::$db->pages])) {
foreach (Cot::$extrafields[Cot::$db->pages] as $exfld) {
// Получаем значение дополнительного поля
$value = isset($rpage['page_' . $exfld['field_name']]) ? $rpage['page_' . $exfld['field_name']] : null ;
// Импортируем данные для дополнительного поля
$rpage['page_' . $exfld['field_name']] = cot_import_extrafields('rpage' . $exfld['field_name'], $exfld,
$source, $value, 'page_');
}
}
// Возвращаем массив данных страницы
return $rpage;
}
/**
* Validates page data.
* @param array $rpage Imported page data
* @return boolean TRUE if validation is passed or FALSE if errors were found
*/
function cot_page_validate($rpage)
{
global $cfg, $structure;
// Проверка на отсутствие категории страницы
cot_check(empty($rpage['page_cat']), 'page_catmissing', 'rpagecat');
// Если категория страницы заблокирована
if ($structure['page'][$rpage['page_cat']]['locked']) {
global $L;
require_once cot_langfile('message', 'core');
cot_error('msg602_body', 'rpagecat'); // Ошибка: категория страницы заблокирована
}
// Проверка на слишком короткое название страницы
cot_check(mb_strlen($rpage['page_title']) < 2, 'page_titletooshort', 'rpagetitle');
// Проверка на наличие запрещённых символов в алиасе
cot_check(!empty($rpage['page_alias']) && preg_match('`[+/?%#&]`', $rpage['page_alias']), 'page_aliascharacters', 'rpagealias');
// Определение, разрешено ли пустое текстовое поле для указанной категории страницы
$allowemptytext = isset($cfg['page']['cat_' . $rpage['page_cat']]['allowemptytext']) ?
$cfg['page']['cat_' . $rpage['page_cat']]['allowemptytext'] : $cfg['page']['cat___default']['allowemptytext'];
// Проверка на пустое текстовое поле, если оно не разрешено
cot_check(!$allowemptytext && empty($rpage['page_text']), 'page_textmissing', 'rpagetext');
// Возвращаем результат проверки: TRUE если ошибок нет, иначе FALSE
return !cot_error_found(); // Проверка на наличие ошибок
}
/**
* Добавляет новую страницу в CMS.
* @param array $rpage Данные страницы
* @param array $auth Массив прав доступа
* @return ?int Новый ID страницы или NULL в случае ошибки
*/
function cot_page_add(&$rpage, $auth = [])
{
// Для хуков требуются переменные $L, $Ls, $R
global $L, $Ls, $R;
// Если обнаружены ошибки, возвращаем false
if (cot_error_found()) {
return false;
}
// Если массив прав не передан, загружаем права для указанной категории
if (count($auth) == 0) {
$auth = cot_page_auth($rpage['page_cat']);
}
// Если указан алиас страницы, проверяем на уникальность
if (!empty($rpage['page_alias'])) {
$page_count = Cot::$db->query(
'SELECT COUNT(*) FROM ' . Cot::$db->pages . ' WHERE page_alias = ?',
$rpage['page_alias']
)->fetchColumn();
if ($page_count > 0) {
// Если алиас не уникален, добавляем случайное число
$rpage['page_alias'] = $rpage['page_alias'] . rand(1000, 9999);
}
}
// Если страница опубликована и администратор не включил автоматическую валидацию, ставим статус "на утверждении"
if (
$rpage['page_state'] == COT_PAGE_STATE_PUBLISHED
&& !($auth['isadmin'] && Cot::$cfg['page']['autovalidate'])
) {
$rpage['page_state'] = COT_PAGE_STATE_PENDING;
}
/* === Хук === */
// Подключение плагинов для обработки перед добавлением
foreach (cot_getextplugins('page.add.add.query') as $pl) {
include $pl;
}
/* ===== */
// Вставляем данные страницы в базу данных
if (Cot::$db->insert(Cot::$db->pages, $rpage)) {
$id = (int) Cot::$db->lastInsertId();
cot_extrafield_movefiles(); // Перемещение файлов экстраполей
cot_page_updateStructureCounters($rpage['page_cat']); // Обновляем счетчики для структуры страниц
} else {
$id = null;
}
/* === Хук === */
// Подключение плагинов после добавления страницы
foreach (cot_getextplugins('page.add.add.done') as $pl) {
include $pl;
}
/* ===== */
// Если страница опубликована и кэш включен
if ($rpage['page_state'] == COT_PAGE_STATE_PUBLISHED && Cot::$cache) {
// Очищаем кэш для страницы
if (Cot::$cfg['cache_page']) {
Cot::$cache->static->clearByUri(cot_page_url($rpage)); // Очищаем кэш по URL страницы
Cot::$cache->static->clearByUri(cot_url('page', ['c' => $rpage['page_cat']])); // Очищаем кэш для категории
}
// Очищаем индексный кэш
if (Cot::$cfg['cache_index']) {
Cot::$cache->static->clear('index');
}
}
cot_shield_update(30, "r page"); // Обновляем защиту
cot_log('Add page #' . $id, 'page', 'add', 'done'); // Логируем добавление страницы
return $id; // Возвращаем ID новой страницы
}
/**
* Удаляет страницу из CMS.
* @param int $id ID страницы
* @param array $rpage Данные страницы
* @return bool|string Сообщение "deleted" при успехе, FALSE при ошибке
*/
function cot_page_delete($id, $rpage = [])
{
// Для хуков требуются переменные $L, $Ls, $R
global $L, $Ls, $R;
// Проверка, что ID страницы валиден
if (!is_numeric($id) || $id <= 0) {
return false;
}
$id = (int) $id;
// Если данные страницы не переданы, загружаем их из базы
if (empty($rpage)) {
$rpage = Cot::$db->query('SELECT * FROM ' . Cot::$db->pages . " WHERE page_id = ?", $id)->fetch();
// Если страница не найдена, возвращаем false
if (!$rpage) {
return false;
}
}
// Удаляем файлы, связанные с экстраполями страницы
foreach (Cot::$extrafields[Cot::$db->pages] as $exfld) {
cot_extrafield_unlinkfiles($rpage['page_' . $exfld['field_name']], $exfld);
}
// Удаляем запись страницы из базы данных
Cot::$db->delete(Cot::$db->pages, 'page_id = ?', $id);
cot_log("Deleted page #" . $id, 'page', 'delete', 'done'); // Логируем удаление страницы
cot_page_updateStructureCounters($rpage['page_cat']); // Обновляем счетчики для структуры страниц
$pageDeletedMessage = ['deleted' => Cot::$L['page_deleted']]; // Сообщение об успешном удалении
/* === Хук === */
// Подключение плагинов после удаления страницы
foreach (cot_getextplugins('page.edit.delete.done') as $pl) {
include $pl;
}
/* ===== */
// Если кэширование включено, очищаем кэш
if (Cot::$cache) {
if (Cot::$cfg['cache_page']) {
Cot::$cache->static->clearByUri(cot_page_url($rpage)); // Очищаем кэш для страницы
Cot::$cache->static->clearByUri(cot_url('page', ['c' => $rpage['page_cat']])); // Очищаем кэш для категории
}
if (Cot::$cfg['cache_index']) {
Cot::$cache->static->clear('index'); // Очищаем индексный кэш
}
}
// Возвращаем сообщение об успешном удалении страницы
return is_array($pageDeletedMessage) ? implode('; ', $pageDeletedMessage) : $pageDeletedMessage;
}
Пояснение:
- Проверка валидности ID — Если переданный ID страницы не является положительным числом, функция возвращает
false. - Загрузка данных страницы — Если данные страницы не переданы, они извлекаются из базы данных.
- Удаление экстраполей — Для каждого экстраполя, связанного с удаляемой страницей, удаляются связанные файлы через
cot_extrafield_unlinkfiles. - Удаление страницы из базы — Страница удаляется из базы данных с помощью метода
delete. - Логирование — Процесс удаления страницы логируется через
cot_log. - Обновление счетчиков — После удаления страницы обновляются счетчики для категории этой страницы.
- Хуки — Используются хуки, подключая плагины, если они есть, после завершения удаления страницы.
- Кэширование — Если кэширование включено, очищаются кэши страницы, категории и индексного кэша.
- Возврат сообщения — Возвращается строка с сообщением об успешном удалении страницы.
/**
* Обновляет страницу в CMS.
* @param int $id ID страницы
* @param array $rpage Данные страницы
* @param array $auth Массив прав доступа
* @return bool TRUE при успехе, FALSE при ошибке
*/
function cot_page_update($id, &$rpage, $auth = [])
{
// Для хуков требуются переменные $L, $Ls, $R
global $L, $Ls, $R;
// Если есть ошибки, возвращаем false
if (cot_error_found()) {
return false;
}
// Если массив прав пустой, то извлекаем права по категории страницы
if (count($auth) == 0) {
$auth = cot_page_auth($rpage['page_cat']);
}
// Если указано псевдоним страницы, проверяем, что такой псевдоним не используется другой страницей
if (!empty($rpage['page_alias'])) {
$page_count = Cot::$db->query('SELECT COUNT(*) FROM ' . Cot::$db->pages .
' WHERE page_alias = ? AND page_id != ?', array($rpage['page_alias'], $id))->fetchColumn();
// Если такой псевдоним уже существует, добавляем к нему случайные цифры
if ($page_count > 0) {
$rpage['page_alias'] = $rpage['page_alias'] . rand(1000, 9999);
}
}
// Загружаем текущие данные страницы для дальнейшей обработки
$row_page = \Cot::$db->query('SELECT * FROM ' . \Cot::$db->pages . ' WHERE page_id = ?', $id)->fetch();
// Если страница публикуется, но не проходит автоподтверждение, ставим статус "ожидает"
if (
$rpage['page_state'] == COT_PAGE_STATE_PUBLISHED
&& !($auth['isadmin'] && \Cot::$cfg['page']['autovalidate'])
) {
$rpage['page_state'] = COT_PAGE_STATE_PENDING;
}
// Очищаем кэш структуры
Cot::$cache && Cot::$cache->db->remove('structure', 'system');
// Обновляем страницу в базе данных
if (!Cot::$db->update(Cot::$db->pages, $rpage, 'page_id = ?', $id)) {
return false;
}
// Логируем изменения страницы
cot_log("Edited page #" . $id, 'page', 'edit', 'done');
// Перемещаем файлы экстраполей
cot_extrafield_movefiles();
/* === Хук === */
// Подключаем плагины после обновления страницы
foreach (cot_getextplugins('page.edit.update.done') as $pl) {
include $pl;
}
/* ===== */
if (
($rpage['page_state'] == COT_PAGE_STATE_PUBLISHED || $rpage['page_cat'] != $row_page['page_cat']) // Если страница опубликована или категория страницы изменилась
&& Cot::$cache // И если используется кэш
) {
// Если включен кэш для страниц
if (Cot::$cfg['cache_page']) {
// Очищаем кэш для текущей страницы по её URL
Cot::$cache->static->clearByUri(cot_page_url($rpage));
// Очищаем кэш для страницы в её новой категории
Cot::$cache->static->clearByUri(cot_url('page', ['c' => $rpage['page_cat']]));
// Если категория страницы изменилась, очищаем кэш для старой категории
if ($rpage['page_cat'] != $row_page['page_cat']) {
Cot::$cache->static->clearByUri(cot_page_url($row_page)); // Очищаем кэш для старой страницы
Cot::$cache->static->clearByUri(cot_url('page', ['c' => $row_page['page_cat']])); // Очищаем кэш для старой категории
}
}
// Если включен кэш для главной страницы
if (Cot::$cfg['cache_index']) {
// Очищаем кэш главной страницы
Cot::$cache->static->clear('index');
}
}
return true;
Пояснение:
- Проверка на ошибки — Если при предыдущих операциях были ошибки, функция сразу возвращает
false. - Права доступа — Если массив прав пустой, извлекаются права для указанной категории страницы.
- Псевдоним страницы — Если указан псевдоним страницы, проверяется, не используется ли он для другой страницы. Если да, к псевдониму добавляются случайные цифры.
- Получение текущих данных страницы — Загружаются данные страницы из базы для дальнейших операций.
- Публикация страницы — Если страница публикуется, но не прошла автоподтверждение, статус страницы меняется на "ожидает".
- Очистка кэша — Если используется кэш, очищается кэш структуры.
- Обновление данных в базе — Обновляются данные страницы в базе.
- Логирование — Процесс обновления страницы логируется.
- Перемещение файлов экстраполей — Если есть экстраполя, связанные с файлы, они перемещаются.
- Хуки — Если есть подключенные плагины, они вызываются после завершения обновления.
/**
* Generates page list widget
* @param string|string[] $categories Custom parent categories code
* @param int $count Number of items to show. 0 - all items
* @param string $template Path for template file
* @param string $order Sorting order (SQL)
* @param string $condition Custom selection filter (SQL)
* @param bool $active_only Custom parent category code
* @param bool $use_subcat Include subcategories TRUE/FALSE
* @param bool $exclude_current Exclude the current page from the rowset for pages.
* @param string $blacklist Category black list, semicolon separated
* @param string $pagination Pagination symbol
* @param int $cache_ttl Cache lifetime in seconds, 0 disables cache
* @return string Parsed HTML
*/
function cot_page_enum(
$categories = '', // Параметр категорий страниц
$count = 0, // Количество элементов для отображения (0 - все)
$template = '', // Путь к файлу шаблона
$order = '', // Параметр сортировки (SQL)
$condition = '', // Пользовательское условие для выборки (SQL)
$active_only = true, // Показ только активных страниц
$use_subcat = true, // Включать подкатегории (TRUE/FALSE)
$exclude_current = false, // Исключить текущую страницу из выборки
$blacklist = '', // Черный список категорий (через запятую)
$pagination = '', // Параметр для постраничной навигации
$cache_ttl = null // Время жизни кэша в секундах, 0 - без кэша
) {
// Глобальные переменные, необходимые для обработки плагинов
global $L, $Ls, $R, $db, $db_pages, $db_users, $structure, $cfg, $sys, $lang, $cache;
// Обработка черного списка категорий
if (!is_array($blacklist)) {
$blacklist = str_replace(' ', '', $blacklist); // Убираем пробелы
$blacklist = (!empty($blacklist)) ? explode(',', $blacklist) : array(); // Преобразуем строку в массив
}
// Получаем категории
if (!empty($categories)) { // Если переданы категории
if (!is_array($categories)) {
$categories = str_replace(' ', '', $categories); // Убираем пробелы
$categories = explode(',', $categories); // Преобразуем строку в массив
}
$categories = array_unique($categories); // Убираем дубли
if ($use_subcat) { // Если необходимо включить подкатегории
$total_categories = [];
foreach ($categories as $cat) {
// Получаем все подкатегории для каждой категории
$cats = cot_structure_children('page', $cat, $use_subcat);
$total_categories = array_merge($total_categories, $cats);
}
$categories = array_unique($total_categories); // Убираем дубли
}
// Исключаем черные категории
$categories = (count($blacklist) > 0 ) ? array_diff($categories, $blacklist) : $categories;
$where['cat'] = "page_cat IN ('" . implode("','", $categories) . "')"; // Создаем условие для выборки по категориям
} elseif (count($blacklist)) { // Если черный список категорий не пуст
$where['cat_black'] = "page_cat NOT IN ('" . implode("','", $blacklist) . "')"; // Исключаем черные категории
}
// Условия для выборки
$where['condition'] = $condition;
// Исключаем текущую страницу из выборки
if ($exclude_current && defined('COT_PAGES') && !defined('COT_LIST')) {
global $id;
$tmp = 0;
if (!empty($id)) {
$tmp = (int) $id;
}
if (!empty($tmp)) {
$where['page_id'] = "page_id != $tmp"; // Условие для исключения текущей страницы
}
}
// Показываем только активные страницы
if ($active_only) {
$where['state'] = 'page_state = ' . COT_PAGE_STATE_PUBLISHED; // Только опубликованные страницы
$where['date'] = "page_begin <= {$sys['now']} AND (page_expire = 0 OR page_expire > {$sys['now']})"; // Проверка срока действия страницы
}
// Получаем номер страницы для постраничной навигации
if (!empty($pagination)) {
list($pg, $d, $durl) = cot_import_pagenav($pagination, $count); // Импортируем навигацию
} else {
$d = 0;
}
// Загружаем шаблон
$mskin = (!empty($template) && file_exists($template)) ?
$template : cot_tplfile(array('page', 'enum', $template), 'module');
$cns_join_tables = ''; // Присоединяемые таблицы
$cns_join_columns = ''; // Присоединяемые столбцы
/* === Hook === */
foreach (cot_getextplugins('page.enum.query') as $pl) {
include $pl; // Подключаем плагины
}
/* ===== */
// Если плагин комментариев активен
if (cot_plugin_active('comments')) {
global $db_com;
require_once cot_incfile('comments', 'plug');
// Добавляем количество комментариев к запросу
$cns_join_columns .= ", (SELECT COUNT(*) FROM `$db_com` WHERE com_area = 'page' AND com_code = p.page_id) AS com_count";
}
// Формируем SQL-запросы
$sql_order = empty($order) ? 'ORDER BY page_date DESC' : "ORDER BY $order"; // Параметр сортировки
$sql_limit = ($count > 0) ? "LIMIT $d, $count" : ''; // Ограничение по количеству
$where = array_filter($where); // Фильтруем пустые условия
$where = ($where) ? 'WHERE ' . implode(' AND ', $where) : ''; // Строка условий
// Запрос для подсчета общего количества элементов
$sql_total = "SELECT COUNT(*) FROM $db_pages AS p $cns_join_tables $where";
// Основной запрос для получения данных страниц
$sql_query = "SELECT p.*, u.* $cns_join_columns FROM $db_pages AS p LEFT JOIN $db_users AS u ON p.page_ownerid = u.user_id
$cns_join_tables $where $sql_order $sql_limit";
// Создаем объект шаблона
$t = new XTemplate($mskin);
isset($md5hash) || $md5hash = 'page_enum_'.md5(str_replace($sys['now'], '_time_', $mskin.$lang.$sql_query));
// Получаем HTML из кэша (если включен кэш)
if ($cache && (int) $cache_ttl > 0) {
$page_query_html = $cache->disk->get($md5hash, 'page', (int) $cache_ttl);
if (!empty($page_query_html)) {
return $page_query_html; // Возвращаем кэшированный результат
}
}
// Запрос к базе данных для подсчета общего числа элементов
$totalitems = $db->query($sql_total)->fetchColumn();
// Выполняем основной запрос
$sql = $db->query($sql_query);
// Получаем все строки результата
$sql_rowset = $sql->fetchAll();
$jj = 0;
foreach ($sql_rowset as $pag) {
$jj++;
// Присваиваем данные страницы в шаблон
$t->assign(cot_generate_pagetags($pag, 'PAGE_ROW_', Cot::$cfg['page']['cat___default']['truncatetext']));
// Присваиваем дополнительные данные
$t->assign([
'PAGE_ROW_NUM' => $jj,
'PAGE_ROW_ODDEVEN' => cot_build_oddeven($jj),
'PAGE_ROW_RAW' => $pag,
]);
// Присваиваем теги пользователя
$t->assign(cot_generate_usertags($pag, 'PAGE_ROW_OWNER_'));
/* === Hook === */
foreach (cot_getextplugins('page.enum.loop') as $pl) {
include $pl;
}
/* ===== */
// Если плагин комментариев активен
if (cot_plugin_active('comments')) {
// Формируем ссылку на комментарии
$rowe_urlp = empty($pag['page_alias'])
? ['c' => $pag['page_cat'], 'id' => $pag['page_id']]
: ['c' => $pag['page_cat'], 'al' => $pag['page_alias']];
// Присваиваем данные комментариев
$t->assign([
'PAGE_ROW_COMMENTS' => cot_comments_link('page', $rowe_urlp, 'page_id='.$pag['page_id']),
'PAGE_ROW_COMMENTS_COUNT' => cot_comments_count('page', $pag['page_id']),
]);
}
// Преобразуем данные в HTML
$t->parse('MAIN.PAGE_ROW');
}
// Формируем постраничную навигацию
if (!empty($pagination)) {
$t->assign([
'PAGE_ENUM_PAGINATION' => cot_pagenav('page', $pagination, $d, $totalitems, $count),
]);
}
/* === Hook === */
foreach (cot_getextplugins('page.enum.tags') as $pl) {
include $pl;
}
/* ===== */
// Сохраняем кэш (если включен кэш)
if ($cache && (int) $cache_ttl > 0) {
$cache->disk->store($md5hash, $t->text('MAIN'), 'page', (int) $cache_ttl);
}
// Возвращаем готовый HTML
return $t->text('MAIN');
}
список функций в файле page.functions.php:
-
function cot_cut_more
Обрезает текст до указанной длины, добавляя ссылку "Читать далее", если текст был обрезан. Это полезно для краткого отображения содержания на страницах, например, в списках. -
function cot_page_enum
Основная функция для выборки и вывода списка страниц с возможностью фильтрации по категориям, сортировки, ограничения количества страниц для отображения и других параметров. -
function cot_page_nav
Формирует навигацию по страницам (пагинация) для длинных списков страниц. Это позволяет делить содержимое на несколько страниц, улучшая восприятие пользователем. -
function cot_page_count
Подсчитывает количество страниц, подходящих под заданные фильтры. Это может использоваться для вывода статистики, например, количества страниц в категории. -
function cot_page_get_categories
Получает список категорий для страниц. Это может быть полезно для создания меню категорий или фильтров для выбора страниц по категориям. -
function cot_page_get_structure
Извлекает структуру страниц, возможно, для отображения родительских и дочерних страниц или создания древовидной навигации по страницам. -
function cot_generate_pagetags
Генерирует теги для страницы (например, мета-теги, URL и другие), которые могут быть использованы в шаблоне для корректного отображения информации о странице. -
function cot_page_comments_count
Получает количество комментариев для конкретной страницы. Эта функция полезна для отображения количества комментариев рядом с ссылкой на страницу. -
function cot_comments_link
Получает ссылку на страницу с комментариями для текущей страницы, если плагин комментариев активирован. Это позволяет пользователям перейти к комментариям к страницам. -
function cot_page_structure_children
Получает дочерние страницы для текущей страницы или категории. Это может использоваться для отображения страниц, связанных с текущей категорией или страницей. -
function cot_page_title
Генерирует заголовок для страницы, который может быть использован в шаблонах для отображения имени страницы в заголовке сайта. -
function cot_page_header
Генерирует мета-информацию для страницы, например, описание страницы и ключевые слова, что полезно для SEO. -
function cot_page_breadcrumbs
Формирует хлебные крошки для текущей страницы, что помогает пользователю понять, где он находится на сайте, и легко перемещаться по разделам. -
function cot_page_get_tags
Извлекает все теги для страницы. Теги могут быть использованы для дополнительной фильтрации или классификации контента. -
function cot_page_get_url
Генерирует URL для страницы. Это полезно для формирования ссылок на страницы, которые могут быть вставлены в другие части сайта.
Этот список включает основные функции, используемые для работы со страницами, их категориями, мета-информацией, комментариями и навигацией на сайте. Каждая из этих функций выполняет определенную задачу для динамического и гибкого вывода информации на сайте.
Комментарии (0)
Автор контента
Оффлайн
Sodium Carbonate
Последняя авторизация: 19.07.2026 01:57
- Страница размещена: 02.02.2025 21:08
- Последнее обновление: 11.02.2025 19:52