From dd0ece2cba948ff7fd77b326275642393eaee254 Mon Sep 17 00:00:00 2001
From: pafnuty
Date: Sat, 22 Feb 2020 19:16:43 +0400
Subject: [PATCH 1/5] 6.0.0 First iteration
---
CHANGELOG.md | 9 +-
README.md | 15 +-
blockpro.xml | 24 +
blockpro_install.php | 1537 -----------------
bp_check.php | 262 ---
engine/inc/blockpro.php | 2 +-
engine/modules/base/blockpro.php | 23 +-
engine/modules/base/core/base.php | 1096 ++++++------
engine/modules/base/core/bpModifiers.php | 1140 ++++++------
templates/Default/blockpro/css/index.htm | 8 -
templates/Default/blockpro/index.htm | 8 -
templates/Default/blockpro/js/blockpro.js | 64 +-
templates/Default/blockpro/js/blockpro_new.js | 197 ---
templates/Default/blockpro/js/index.htm | 8 -
14 files changed, 1252 insertions(+), 3141 deletions(-)
create mode 100644 blockpro.xml
delete mode 100644 blockpro_install.php
delete mode 100644 bp_check.php
delete mode 100644 templates/Default/blockpro/css/index.htm
delete mode 100644 templates/Default/blockpro/index.htm
delete mode 100644 templates/Default/blockpro/js/blockpro_new.js
delete mode 100644 templates/Default/blockpro/js/index.htm
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9646de7..a2a4a11 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,13 @@
+# 6.0.0
+- Теперь модуль не гарантирует совместимость со версиями DLE ниже, чем 13.x и скоро будет убрана их поддержка полностью.
+- Установка в виде плагина.
+- Исправлена ошибка с вариантом сортировки `randomLight`, когда новости не найдены.
+- Добавлен новый модификатор `sentence`, позволяющий вывести заданное количество предложений (до точки). Например `{$el.short_story|sentence:'2'}` - выведет два первых предложения из краткой новости.
+- Небольшие изменения и улучшения в коде.
+
# 5.1.5
- Исправлена ошибка `Error: Syntax error, unrecognized expression: Deprecated: Array and string offset access syntax with curly braces is deprecated` (#159)
-- Добавлен модификатор jsonDecode для более удобного перобразования кода в JSON (Используйте его, если не работает json_decode)
+- Добавлен модификатор `jsonDecode` для более удобного перобразования кода в JSON (Используйте его, если не работает json_decode)
# 5.1.4
- Исправлена работа постраничной навигации при `catId=this` (#144)
diff --git a/README.md b/README.md
index 10254bf..9170fe2 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,8 @@
# DLE-BlockPro — тот самый модуль для вывода новостей!
-
-
+
+
[](https://github.com/dle-modules/DLE-BlockPro/blob/master/LICENSE)
-- **ВНИМАНИЕ!** **Работа модуля в кодировке windows-1251 не гарантируется**
- Краткая информация о шаблонных тега прописана в шаблоне **{THEME}/blockpro/blockpro.tpl**, расширенный пример **{THEME}/blockpro/fullexample.tpl**
- Более детальная информация по используемому шаблонизатору модуля находится в [документации по шаблонизатору](https://github.com/bzick/fenom/blob/master/docs/ru/readme.md)
- Официальный сайт: [bp.pafnuty.name](http://bp.pafnuty.name/)
@@ -11,5 +10,11 @@
- [История изменений](https://github.com/dle-modules/DLE-BlockPro/blob/master/CHANGELOG.md)
## Установка модуля
-1. Залить содержимое папки **upload** в корень сайта.
-2. Запустить **/blockpro_install.php** и следовать инструкции.
+
+1. Устанавливаем как обычный плагин, файл **blockpro_plugin.zip** содержит всё необходимое для автоматической установки.
+2. Открыть файл `/templates/Default/main.tpl`
+3. Добавить после `{AJAX}` или после `{jsfiles}`:
+``
+4. Добавить после `{AJAX}` или после `{jsfiles}`:
+``
+
diff --git a/blockpro.xml b/blockpro.xml
new file mode 100644
index 0000000..d44b29d
--- /dev/null
+++ b/blockpro.xml
@@ -0,0 +1,24 @@
+
+
+ BlockPro
+ Модуль BlockPro предназначен для пользовательского вывода новостей на сайте под управлением CMS DataLife Engine и позиционируется как альтернатива {custom}, {top}, {related-news}.
+ engine/skins/images/blockpro.png
+ 6.0.0
+ 10.2
+ greater
+ http://blockpro.loc/check_updates.php
+ 1
+
+
+
+
+
+
\ No newline at end of file
diff --git a/blockpro_install.php b/blockpro_install.php
deleted file mode 100644
index 2c268c0..0000000
--- a/blockpro_install.php
+++ /dev/null
@@ -1,1537 +0,0 @@
- 'blockpro',
- // Название модуля - показывается как в установщике, так и в админке.
- 'moduleTitle' => 'BlockPro',
- // Описание модуля, для установщика и админки.
- 'moduleDescr' => 'Модуль вывода новостей для DLE',
- // Версия модуля, для установщика
- 'moduleVersion' => '5.1.5',
- // Дата выпуска модуля, для установщика
- 'moduleDate' => '01.12.2019',
- // Версии DLE, поддержваемые модулем, для установщика
- 'dleVersion' => '10.x',
- // ID групп, для которых доступно управление модулем в админке.
- 'allowGroups' => '1',
- // Массив с запросами, которые будут выполняться при установке
- 'queries' => [
- 1 => 'CREATE TABLE IF NOT EXISTS `' . PREFIX . '_blockpro_blocks` (
- `id` tinyint(6) NOT NULL AUTO_INCREMENT,
- `name` varchar(255) NOT NULL,
- `block_id` varchar(100) NOT NULL,
- `params` mediumtext NOT NULL,
- `date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
- PRIMARY KEY (`id`),
- KEY `block_id` (`block_id`)
-) ENGINE=MyISAM;',
- ],
- // Устанавливать админку (true/false). Включает показ кнопки установки и удаления админки.
- 'installAdmin' => true,
- // Отображать шаги утановки модуля
- 'steps' => true,
- // Показывать лицензионное соглашение?
- 'showLicense' => true,
-
-];
-
-// Определяем кодировку.
-$fileCharset = chasetConflict($cfg);
-
-// Лицензионное соглашение
-
-$licenseText = '
MIT License
Copyright (c) 2017 Модули для DataLife Engine
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
';
-
-// Лицензионное соглашение
-// Шаги установки модуля
-/** @var array $config */
-$steps = <<Редактирование файлов
-
-
- Добавить после {AJAX} или после {jsfiles}:
-
- или
-
- если хотите использовать возможность навигации по стрелкам браузера при ajax-переключении страниц модуля.
-
-
Выполнить установку админчасти и таблиц модуля (кнопка ниже).
';
- } // Если через $_POST ничего не передаётся, выводим форму для установки модуля
- else {
- // Выводим кнопку удаления модуля
- if ($cfg['installAdmin'] && $adminInstalled) {
- $uninstallForm = <<
-
-
Удаление админчасти модуля
-
-
-HTML;
- }
- // Выводим кнопку установки модуля с допзпросами
- if ($queries) {
- $installForm = <<
-
-
-
-HTML;
-
-
- }
-
- }
-
-
- // Если руки пользователя кривые, или он просто забыл перекодировать файлы - скажем ему об этом.
- if ($fileCharset['conflict']) {
- $output = '
Ошибка!
Кодировка файла установщика (' . $fileCharset['charset'] . ') не совпадает с кодировкой сайта (' . $config['charset'] . '). Установка не возможна. Перекодируйте все php файлы модуля и запустите установщик ещё раз.
';
- }
-
- // Функция возвращает то, что должно быть выведено
- return $output;
-}
-
-/**
- * Отлавливаем данные о кодировке файла (utf-8 или windows-1251);
- *
- * @param string $string - строка (или массив), в которой требуется определить кодировку.
- *
- * @return array - возвращает массив с определением конфликта кодировки строки и сайта, а так же сму кодировку
- * строки.
- */
-function chasetConflict($string) {
- global $config;
- if (is_array($string)) {
- $string = implode(' ', $string);
- }
- $detect = preg_match('%(?:
- [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
- |\xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
- |[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
- |\xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
- |\xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
- |[\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
- |\xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
- )+%xs', $string);
- $stringCharset = ($detect == '1') ? 'utf-8' : 'windows-1251';
- $config['charset'] = strtolower($config['charset']);
- $return = [];
- $return['conflict'] = ($stringCharset == $config['charset']) ? false : true;
- $return['charset'] = $stringCharset;
-
- return $return;
-}
-
-?>
-
-
-
-
-
-
-
-
-
-
-
Проверка совместимости текущего сайта и модуля BlockPro
-
-
-
-
-
-
-
Параметр
-
Требование
-
Наличие
-
- $check): ?>
-
-
-
-
-
-
-
-
- Если один или несколько пунктов отмечены красным цветом — модуль не
- запустится на вашем сайте при текущих настройках. Необходимо исправить несоответсвия.
-
HTML;
- return $rated;
+ return $rated;
- } elseif ($config['rating_type'] == "1") {
+ } elseif ($config['rating_type'] == "1") {
- if ($rating < 0) {
- $rating = 0;
- }
+ if ($rating < 0) {
+ $rating = 0;
+ }
- if ($allow) {
- $rated = "{$rating}";
- } else {
- $rated = "{$rating}";
- }
+ if ($allow) {
+ $rated
+ = "{$rating}";
+ } else {
+ $rated = "{$rating}";
+ }
- return $rated;
+ return $rated;
- } elseif ($config['rating_type'] == "2") {
+ } elseif ($config['rating_type'] == "2") {
- $extraclass = "ratingzero";
+ $extraclass = "ratingzero";
- if ($rating < 0) {
- $extraclass = "ratingminus";
- }
+ if ($rating < 0) {
+ $extraclass = "ratingminus";
+ }
- if ($rating > 0) {
- $extraclass = "ratingplus";
- $rating = "+" . $rating;
- }
+ if ($rating > 0) {
+ $extraclass = "ratingplus";
+ $rating = "+".$rating;
+ }
- if ($allow) {
- $rated = "{$rating}";
- } else {
- $rated = "{$rating}";
- }
+ if ($allow) {
+ $rated
+ = "{$rating}";
+ } else {
+ $rated = "{$rating}";
+ }
- return $rated;
+ return $rated;
- }
+ }
- return true;
+ return true;
}
function stripSlashesInArray($data) {
- if (is_array($data)) {
- $data = array_map('stripSlashesInArray', $data);
- } else {
- $data = stripslashes($data);
- }
+ if (is_array($data)) {
+ $data = array_map('stripSlashesInArray', $data);
+ } else {
+ $data = stripslashes($data);
+ }
- return $data;
+ return $data;
}
\ No newline at end of file
diff --git a/engine/modules/base/core/bpModifiers.php b/engine/modules/base/core/bpModifiers.php
index 90ef478..573ee3c 100644
--- a/engine/modules/base/core/bpModifiers.php
+++ b/engine/modules/base/core/bpModifiers.php
@@ -14,514 +14,638 @@
class bpModifiers extends base {
- /**
- * @param $data - контент
- * @param $limit
- * @param string $etc - Окончание обрезанного текста
- * @param bool $wordcut - жесткое ограничение символов
- * @param string $charset
- *
- * @return string $data - обрезанный результат
- */
- public static function textLimit($data, $limit, $etc = '…', $wordcut = false, $charset = 'utf-8') {
- $data = strip_tags($data, ' ');
- $data = trim(str_replace([' ', ' '], ' ', $data));
-
- if ($limit && dle_strlen($data, $charset) > $limit) {
- $data = dle_substr($data, 0, $limit, $charset) . $etc;
- if (!$wordcut && ($word_pos = dle_strrpos($data, ' ', $charset))) {
- $data = dle_substr($data, 0, $word_pos, $charset) . $etc;
- }
-
- }
-
- return $data;
- }
-
- /**
- * Функция ресайза картинок
- *
- * @param string $data Строка, из которой будем выдёргивать картинку
- * @param string $noimage Картинка-заглушка
- * @param string $imageType Тип картинки (small/original/intext) - для получения соответствующей картинки или массива картинок
- * @param integer /string $number Номер картинки в контенте или all для вывода всех картинок
- * @param string $size Размер картики (например 100 или 100x150)
- * @param string $quality Качество картинки (0-100)
- * @param string $resizeType Тип ресайза (exact, portrait, landscape, auto, crop)
- * @param boolean $grabRemote Грабить сторонние картинки к себе (true/false)
- * @param boolean $showSmall Обрабатывать уменьшенную копию, если есть
- * @param boolean $subdir Подпапка для картинок (иногда бывает нужно)
- * @param array $config Массив с конфигом DLE
- * @param string $service Сервис, серез который будем делать ресайз (local/tinypng/kraken)
- *
- * @return string Путь к уменьшенной или оригинальной картнке
- */
-
- public static function getImage($data, $noimage = '', $imageType = 'small', $number, $size, $quality, $resizeType = 'auto', $grabRemote = true, $showSmall = false, $subdir = false, $config = [], $service = 'local') {
-
- $resizeType = ($resizeType == '' || !$resizeType) ? 'auto' : $resizeType;
- $quality = ($quality == '' || !$quality) ? '100' : $quality;
- $noimage = str_replace($config['http_home_url'] . '/', $config['http_home_url'], $noimage);
-
- // Удалим из адреса сайта последний слеш.
- $config['http_home_url'] = (substr($config['http_home_url'], -1, 1) == '/') ? substr($config['http_home_url'], 0, -1) : $config['http_home_url'];
-
- // Задаём папку для загрзки картинок по умолчанию.
- $uploadDir = '/uploads/base/';
-
- // Задаём подпапку при необходимости
- if ($subdir) {
- // Если subdir начнается со слеша - значит это папка от корня сайта, а не подпапака в base.
- if (substr($subdir, 0, 1) == '/') {
- $uploadDir = $subdir;
- } else {
- $uploadDir = $uploadDir . $subdir . '/';
- }
- }
-
- // Задаём папку для картинок
- $imageDir = $uploadDir . $size . '/';
-
- $dir = ROOT_DIR . $imageDir;
-
- $data = stripslashes($data);
- $arImages = [];
-
- if (preg_match_all('/]*?)?\\bsrc\\s*=\\s*(?|"([^"]*)"|\'([^\']*)\'|([^<>\'"\\s]*))[^<>]*>/i', $data, $m)) {
-
- $i = 1; // Счётчик
- // Если регулярка нашла картинку — работаем.
- if (isset($m[1])) {
- foreach ($m[1] as $key => $url) {
- // Если это смайлик или спойлер — пропускаем.
- if (stripos($url, 'dleimages') !== false || stripos($url, 'engine/data/emoticons') !== false) {
- continue;
- }
- // Если номер картинки меньше, чем требуется — проходим мимо.
- if ($number != 'all' && $i < (int)$number) {
- // Не забываем прибавить счётчик.
- $i++;
- continue;
- }
- /** @var string $imageItem */
- $imageItem = $imgResized = '';
-
- // Если в настройках вызова указано выдёргивание оригинала — отдадим оригинал.
- if ($imageType == 'original') {
- $imageItem = str_ireplace(['/thumbs', '/medium'], '', $url);
- }
- // Если intext — отдадим то, что получили в тексте.
- if ($imageType == 'intext') {
- $imageItem = $url;
- }
- // Если small — то будем работать с картинкой.
- if ($imageType == 'small') {
- // Выдёргиваем оригинал, на случай если уменьшить надо до размеров больше, чем thumb или medium в новости и если это не запрещено в настройках.
- $imageItem = ($showSmall) ? $url : str_ireplace(['/thumbs', '/medium'], '', $url);
-
- // Удаляем текущий домен (в т.ч. с www) из строки.
- $urlShort = str_ireplace(['http://' . $_SERVER['HTTP_HOST'], 'http://www.' . $_SERVER['HTTP_HOST'], 'https://' . $_SERVER['HTTP_HOST'], 'https://www.' . $_SERVER['HTTP_HOST']], '', $imageItem);
-
- // Проверяем наша картинка или чужая.
- $isRemote = (preg_match('~^http(s)?://~', $urlShort)) ? true : false;
-
- // Проверяем разрешено ли тянуть сторонние картинки.
- $grabRemoteOn = ($grabRemote) ? true : false;
-
- // Отдаём заглушку, если ничего нет.
- if (!$urlShort) {
- /** @var string $imageItem */
- $imageItem = $noimage;
- continue;
- }
-
- // Если внешняя картинка и запрещего грабить картинки к себе — возвращаем её.
- if ($isRemote && !$grabRemoteOn) {
- /** @var string $imgResized */
- $imgResized = $urlShort;
- continue;
- }
-
- // Работаем с картинкой
- // Если есть параметр size — включаем ресайз картинок
- if ($size) {
- // Создаём и назначаем права, если нет таковых
- if (!is_dir($dir)) {
- @mkdir($dir, 0755, true);
- @chmod($dir, 0755);
- }
- if (!chmod($dir, 0755)) {
- @chmod($dir, 0755);
- }
-
- // Присваиваем переменной значение картинки (в т.ч. если это внешняя картинка)
- $imgResized = $urlShort;
-
- // Если не внешняя картинка — подставляем корневю дирректорию, чтоб ресайзер понял что ему дают.
- if (!$isRemote) {
- $imgResized = ROOT_DIR . $urlShort;
- }
-
- if ($service == 'tinypng' && $config['tinypng_key'] == '') {
- $service = 'local';
- }
- if ($service == 'kraken' && $config['kraken_key'] == '') {
- $service = 'local';
- }
-
- // Определяем новое имя файла
- $fileName = md5($size . '_' . $resizeType . '_' . $imgResized) . '_' . $service . '.' . pathinfo($imgResized, PATHINFO_EXTENSION);
-
- $newFile = $dir . $fileName;
- // Если картинки нет в папке обработанных картинок, то попробуем её получить.
- if (!file_exists($newFile)) {
- // Если картинка локальная, или картинка внешняя, но разрешено её стянуть — работаем.
- if (!$isRemote || ($grabRemoteOn && $isRemote)) {
- self::getImageWith($service, $imgResized, $newFile, $size, $resizeType, $quality, $config);
- }
- }
-
- $imgResized = (file_exists($newFile)) ? $config['http_home_url'] . $imageDir . $fileName : $noimage;
-
- } else {
- // Если параметра imgSize нет - отдаём исходную картинку
- $imgResized = $urlShort;
- }
-
- // Отдаём дальше результат обработки.
- $imageItem = $imgResized;
-
- } // if($imageType == 'small')
- $arImages[$i] = $imageItem;
- if ($number == $i) {
- break;
- }
- $i++;
- }
-
- }
-
- } else {
- // Если регулярка не нашла картинку - отдадим заглушку
- $arImages[$number] = $noimage;
- }
-
- // Если хотим все картинки — не вопрос, получим массив.
- if ($number == 'all') {
-
- return $arImages;
- }
-
- // По умолчанию возвращаем отдну картинку (понимаю, что метод должен возвращать всегда один тип данных, но это сделано из-за совместимости версий)
- return $arImages[$number];
-
- }
-
- /**
- * @param string $service
- * @param $originalFile
- * @param $newFile
- * @param $size
- * @param $method
- * @param string $quality
- * @param array $config
- */
- public static function getImageWith($service = 'local', $originalFile, $newFile, $size, $method, $quality = '100', $config = []) {
- // Разделяем высоту и ширину
- $imgSize = explode('x', $size);
-
- // Если указана только одна величина - присваиваем второй первую, будет квадрат для exact, auto и crop, иначе класс ресайза жестоко тупит, ожидая вторую переменную.
- if (count($imgSize) == '1') {
- $imgSize[1] = $imgSize[0];
- }
-
- switch ($service) {
- // Тянем картинку через встроенный класс ресайза
- case 'local':
- // Определяемся с возможными методами уменьшения картинок.
- $arMethods = ['exact', 'portrait', 'landscape', 'auto', 'crop'];
- $resizeType = (in_array($method, $arMethods)) ? $method : 'auto';
-
- // Подрубаем локальный класс для картинок
- $resizeImg = new resize($originalFile);
- $resizeImg->resizeImage( // Создание уменьшенной копии
- $imgSize[0], // Размер картинки по ширине
- $imgSize[1], // Размер картинки по высоте
- $resizeType // Метод уменьшения (exact, portrait, landscape, auto, crop)
- );
- $resizeImg->saveImage($newFile, $quality); // Сохраняем картинку в заданную папку
- break;
-
- // Тянем картинку через tinyPNG
- case 'tinypng':
-
- // Подключаем необходимые классы (да, без composer в DLE тяжело живётся).
- require_once ENGINE_DIR . '/modules/base/resizers/tinypng/Tinify.php';
- require_once ENGINE_DIR . '/modules/base/resizers/tinypng/Tinify/Client.php';
- require_once ENGINE_DIR . '/modules/base/resizers/tinypng/Tinify/Exception.php';
- require_once ENGINE_DIR . '/modules/base/resizers/tinypng/Tinify/ResultMeta.php';
- require_once ENGINE_DIR . '/modules/base/resizers/tinypng/Tinify/Source.php';
- require_once ENGINE_DIR . '/modules/base/resizers/tinypng/Tinify/Result.php';
-
- // Определяемся с возможными методами уменьшения картинок.
- $arMethods = ['portrait', 'landscape', 'auto', 'crop'];
- $resizeType = (in_array($method, $arMethods)) ? $method : 'auto';
-
- // Определяемся с опциями обработки картинки
- $imgSize[0] = (int)$imgSize[0];
- $imgSize[1] = (int)$imgSize[1];
-
- $arTinyOptions = [];
-
- switch ($resizeType) {
- case 'portrait':
- $arTinyOptions = [
- 'method' => 'scale',
- 'height' => $imgSize[1],
- ];
- break;
-
- case 'landscape':
- $arTinyOptions = [
- 'method' => 'scale',
- 'width' => $imgSize[0],
- ];
- break;
-
- case 'auto':
- $arTinyOptions = [
- 'method' => 'fit',
- 'width' => $imgSize[0],
- 'height' => $imgSize[1],
- ];
- break;
-
- case 'crop':
- $arTinyOptions = [
- 'method' => 'cover',
- 'width' => $imgSize[0],
- 'height' => $imgSize[1],
- ];
- break;
- }
-
- // Вызываем класс и обрабатываем картинку
- \Tinify\setKey($config['tinypng_key']);
-
- $source = \Tinify\fromFile($originalFile);
- $resized = $source->resize($arTinyOptions);
- $resized->toFile($newFile);
-
- unset($source, $resized);
-
- break;
-
- // Тянем картинку через Kraken
- case 'kraken':
- // Определяемся с возможными методами уменьшения картинок.
- $arMethods = ['exact', 'portrait', 'landscape', 'auto', 'crop'];
- $resizeType = (in_array($method, $arMethods)) ? $method : 'auto';
- // У Kraken есть свой метод crop, но нам нужен fit
- if ($method == 'crop') {
- $resizeType = 'fit';
- }
-
- // Подключаем класс Kraken.
- require_once ENGINE_DIR . '/modules/base/resizers/kraken/Kraken.php';
-
- $kraken = new Kraken($config['kraken_key'], $config['kraken_secret']);
-
- // Проверяем наша картинка или чужая. Нужно для корректной передачи данных в kraken
- $isRemote = (preg_match('~^http(s)?://~', $originalFile)) ? true : false;
-
- // Параметры ресайза
- $krakenResize = [
- 'width' => $imgSize[0],
- 'height' => $imgSize[1],
- 'strategy' => $resizeType,
- ];
-
- if ($isRemote) {
- // Если картинка сторонняя
- $krakenParams = [
- 'url' => $originalFile,
- 'wait' => true,
- 'resize' => $krakenResize,
- ];
-
- $krakenData = $kraken->url($krakenParams);
- } else {
- // Если картинка наша
- $krakenParams = [
- 'file' => $originalFile,
- 'wait' => true,
- 'resize' => $krakenResize,
- ];
-
- $krakenData = $kraken->upload($krakenParams);
- }
-
- if ($krakenData['success']) {
- $newImg = self::curlGet($krakenData['kraked_url']);
- file_put_contents($newFile, $newImg);
- }
-
- break;
-
- // Тянем картинку через tinyPNG
- }
- }
-
- public static function curlGet($url) {
- $ch = curl_init();
- $default_curlopt = [
- CURLOPT_TIMEOUT => 15,
- CURLOPT_RETURNTRANSFER => 1,
- // CURLOPT_FOLLOWLOCATION => 1,
- CURLOPT_SSL_VERIFYPEER => false,
- CURLOPT_USERAGENT => "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0",
- ];
- $curlopt = [CURLOPT_URL => $url] + $default_curlopt;
- curl_setopt_array($ch, $curlopt);
- $response = curl_exec($ch);
- if ($response === false) {
- trigger_error(curl_error($ch));
- }
-
- curl_close($ch);
-
- return $response;
- }
-
-
- /**
- * Функция для правильного склонения слов
- *
- * @param int $n - число, для которого будет расчитано окончание
- * @param string $words - варианты окончаний для (1 комментарий, 2 комментария, 100 комментариев)
- *
- * @return string - слово с правильным окончанием
- */
- public static function declinationWords($n = 0, $words) {
- $words = explode('|', $words);
- $n = abs((int) $n); // abs на случай отрицательного значения
-
- return $n % 10 == 1 && $n % 100 != 11 ? $words[0] . $words[1] : ($n % 10 >= 2 && $n % 10 <= 4 && ($n % 100 < 10 || $n % 100 >= 20) ? $words[0] . $words[2] : $words[0] . $words[3]);
- }
-
- /**
- * Функция для вывода print_r в шаблон
- *
- * @param mixed $var входящие данные
- *
- * @return string print_r
- */
- public static function dump($var) {
- return print_r($var, true);
- }
-
- /**
- * @param $array
- * @param bool|false $fields
- * @param $db
- *
- * @return mixed
- */
- public static function getAuthors($array, $fields = false, $db) {
-
- $array = array_unique($array);
- if ($fields) {
- $fields = trim($fields);
- } else {
- $fields = '*';
- }
- if (count($array) == 1) {
- $select = 'SELECT ?p FROM ?n WHERE name = ?s';
- $array = $array[0];
- } else {
- $select = 'SELECT ?p FROM ?n WHERE name IN(?a)';
- }
-
- $_result = $db->getAll($select, $fields, USERPREFIX . '_users', $array);
-
- foreach ($_result as $key => $user) {
- unset($user['password']);
- $result[$user['name']] = $user;
- }
-
- /** @var array $result */
- return $result;
- }
-
- /**
- * Функция для вывода даты в формате "time ago"
- *
- *
- * @param string $date Дата новости
- * @param integer $precision Кол-во частей
- *
- * @return string отформатированная строка
- */
- public static function timeAgo($date, $precision = 2) {
- $precision = ($precision === 0 || $precision === 1) ? 1 : $precision;
- $times = [
- 31536000 => '|год|года|лет',
- 2592000 => 'месяц||а|ев',
- 604800 => 'недел|ю|и|ь',
- 86400 => '|день|дня|дней',
- 3600 => 'час||а|ов',
- 60 => 'минут|у|ы|',
- ];
-
- $timeDiff = time() - strtotime($date);
-
- if ($timeDiff < 60) {
- $output = 'меньше минуты';
- } else {
- $output = [];
- $precisionCount = 0;
-
- foreach ($times as $period => $name) {
-
- if ($precisionCount >= $precision || ($precisionCount > 0 && $period < 1)) {
- break;
- }
- $result = floor($timeDiff / $period);
-
- if ($result > 0) {
- $output[] = $result . ' ' . self::declinationWords($result, $name);
-
- $timeDiff -= $result * $period;
- $precisionCount++;
- } else {
- if ($precisionCount > 0) {
- $precisionCount++;
- }
- }
- }
-
- $last = array_slice($output, -1);
- $first = join(', ', array_slice($output, 0, -1));
- $both = array_filter(array_merge([$first], $last), 'strlen');
- $outputFormatted = join(' и ', $both);
-
-
- $output = $outputFormatted;
- }
-
- return $output . ' назад';
- }
-
- /**
- * Функция для конфертации строки в json на случай, если не работает модификатор json_decode
- * @param string $var "{"one":"val"}"
- *
- * @return array json-массив
- */
- public static function jsonDecode($var) {
- $decoded = html_entity_decode($var, ENT_COMPAT);
- return json_decode($decoded, true);
- }
+ /**
+ * @param $data - контент
+ * @param $limit
+ * @param string $etc - Окончание обрезанного текста
+ * @param bool $wordcut - жесткое ограничение символов
+ * @param string $charset
+ *
+ * @return string $data - обрезанный результат
+ */
+ public static function textLimit(
+ $data,
+ $limit,
+ $etc = '…',
+ $wordcut = false,
+ $charset = 'utf-8'
+ ) {
+ $data = bpModifiers::cleanTextContent($data);
+
+ if ($limit && dle_strlen($data, $charset) > $limit) {
+ $data = dle_substr($data, 0, $limit, $charset).$etc;
+ if (!$wordcut && ($word_pos = dle_strrpos($data, ' ', $charset))) {
+ $data = dle_substr($data, 0, $word_pos, $charset).$etc;
+ }
+
+ }
+
+ return $data;
+ }
+
+ /**
+ * Функция для очистки контента от лишнего текста
+ *
+ * @param string $data
+ *
+ * @return string $text
+ */
+ public static function cleanTextContent($data = '') {
+ $data = preg_replace('/\[attachment=(.*?)]/is', '', $data);
+ $data = preg_replace('/\[hide(.*?)](.+?)\[\/hide]/is', '', $data);
+ $data = preg_replace('//is', '', $data);
+ $data
+ = preg_replace('/(.+?)/is', '', $data);
+
+ $data = str_replace('><', '> <', $data);
+ $data = strip_tags($data, ' ');
+
+ $search = [' ', ' ', "\n", "\r"];
+ $replace = [' ', ' ', ' ', ''];
+ $data = trim(str_replace($search, $replace, $data));
+
+ $text = preg_replace('/\s+/u', ' ', $data);
+
+ return $text;
+ }
+
+ /**
+ * Функция для обрезки текста до заданного количества предложений (до точки)
+ *
+ * @param string $data - контент
+ * @param string $limit
+ *
+ * @return string $strSentences - обрезанный результат
+ */
+ public static function sentenceLimit($data, $limit) {
+ $text = bpModifiers::cleanTextContent($data);
+
+ $text = str_replace(['...', '..'], ['.', '.'], $text);
+
+ $splitShortStory = explode('. ', $text);
+
+ $sentences = [];
+
+ foreach ($splitShortStory as $key => $sentence) {
+ if (($limit - 1) >= $key) {
+ $sentences[] = trim($sentence).'.';
+ } else {
+ break;
+ }
+ }
+
+ $strSentences = implode(' ', $sentences);
+ $strSentences = str_replace('..', '.', $strSentences);
+
+ return $strSentences;
+ }
+
+ /**
+ * Функция ресайза картинок
+ *
+ * @param string $data Строка, из которой будем выдёргивать картинку
+ * @param string $noimage Картинка-заглушка
+ * @param string $imageType Тип картинки (small/original/intext) - для получения соответствующей картинки или
+ * массива картинок
+ * @param integer|string $number Номер картинки в контенте или all для вывода всех картинок
+ * @param string $size Размер картики (например 100 или 100x150)
+ * @param string $quality Качество картинки (0-100)
+ * @param string $resizeType Тип ресайза (exact, portrait, landscape, auto, crop)
+ * @param boolean $grabRemote Грабить сторонние картинки к себе (true/false)
+ * @param boolean $showSmall Обрабатывать уменьшенную копию, если есть
+ * @param boolean $subdir Подпапка для картинок (иногда бывает нужно)
+ * @param array $config Массив с конфигом DLE
+ * @param string $service Сервис, серез который будем делать ресайз (local/tinypng/kraken)
+ *
+ * @return string Путь к уменьшенной или оригинальной картнке
+ */
+ public static function getImage(
+ $data,
+ $noimage = '',
+ $imageType = 'small',
+ $number,
+ $size,
+ $quality,
+ $resizeType = 'auto',
+ $grabRemote = true,
+ $showSmall = false,
+ $subdir = false,
+ $config = [],
+ $service = 'local'
+ ) {
+
+ $resizeType = ($resizeType == '' || !$resizeType) ? 'auto' : $resizeType;
+ $quality = ($quality == '' || !$quality) ? '100' : $quality;
+ $noimage = str_replace($config['http_home_url'].'/', $config['http_home_url'], $noimage);
+
+ // Удалим из адреса сайта последний слеш.
+ $config['http_home_url'] = (substr($config['http_home_url'], -1, 1) == '/') ? substr($config['http_home_url'],
+ 0, -1) : $config['http_home_url'];
+
+ // Задаём папку для загрзки картинок по умолчанию.
+ $uploadDir = '/uploads/base/';
+
+ // Задаём подпапку при необходимости
+ if ($subdir) {
+ // Если subdir начнается со слеша - значит это папка от корня сайта, а не подпапака в base.
+ if (substr($subdir, 0, 1) == '/') {
+ $uploadDir = $subdir;
+ } else {
+ $uploadDir = $uploadDir.$subdir.'/';
+ }
+ }
+
+ // Задаём папку для картинок
+ $imageDir = $uploadDir.$size.'/';
+
+ $dir = ROOT_DIR.$imageDir;
+
+ $data = stripslashes($data);
+ $arImages = [];
+
+ if (preg_match_all('/]*?)?\\bsrc\\s*=\\s*(?|"([^"]*)"|\'([^\']*)\'|([^<>\'"\\s]*))[^<>]*>/i',
+ $data, $m)
+ ) {
+
+ $i = 1; // Счётчик
+ // Если регулярка нашла картинку — работаем.
+ if (isset($m[1])) {
+ foreach ($m[1] as $key => $url) {
+ // Если это смайлик или спойлер — пропускаем.
+ if (stripos($url, 'dleimages') !== false
+ || stripos($url, 'engine/data/emoticons') !== false
+ ) {
+ continue;
+ }
+ // Если номер картинки меньше, чем требуется — проходим мимо.
+ if ($number != 'all' && $i < (int)$number) {
+ // Не забываем прибавить счётчик.
+ $i++;
+ continue;
+ }
+ /** @var string $imageItem */
+ $imageItem = $imgResized = '';
+
+ // Если в настройках вызова указано выдёргивание оригинала — отдадим оригинал.
+ if ($imageType == 'original') {
+ $imageItem = str_ireplace(['/thumbs', '/medium'], '', $url);
+ }
+ // Если intext — отдадим то, что получили в тексте.
+ if ($imageType == 'intext') {
+ $imageItem = $url;
+ }
+ // Если small — то будем работать с картинкой.
+ if ($imageType == 'small') {
+ // Выдёргиваем оригинал, на случай если уменьшить надо до размеров больше, чем thumb или medium в новости и если это не запрещено в настройках.
+ $imageItem = ($showSmall) ? $url : str_ireplace(['/thumbs', '/medium'], '', $url);
+
+ // Удаляем текущий домен (в т.ч. с www) из строки.
+ $urlShort = str_ireplace([
+ 'http://'.$_SERVER['HTTP_HOST'],
+ 'http://www.'.$_SERVER['HTTP_HOST'],
+ 'https://'.$_SERVER['HTTP_HOST'],
+ 'https://www.'.$_SERVER['HTTP_HOST'],
+ ], '', $imageItem);
+
+ // Проверяем наша картинка или чужая.
+ $isRemote = (preg_match('~^http(s)?://~', $urlShort)) ? true : false;
+
+ // Проверяем разрешено ли тянуть сторонние картинки.
+ $grabRemoteOn = ($grabRemote) ? true : false;
+
+ // Отдаём заглушку, если ничего нет.
+ if (!$urlShort) {
+ /** @var string $imageItem */
+ $imageItem = $noimage;
+ continue;
+ }
+
+ // Если внешняя картинка и запрещего грабить картинки к себе — возвращаем её.
+ if ($isRemote && !$grabRemoteOn) {
+ /** @var string $imgResized */
+ $imgResized = $urlShort;
+ continue;
+ }
+
+ // Работаем с картинкой
+ // Если есть параметр size — включаем ресайз картинок
+ if ($size) {
+ // Создаём и назначаем права, если нет таковых
+ if (!is_dir($dir)) {
+ @mkdir($dir, 0755, true);
+ @chmod($dir, 0755);
+ }
+ if (!chmod($dir, 0755)) {
+ @chmod($dir, 0755);
+ }
+
+ // Присваиваем переменной значение картинки (в т.ч. если это внешняя картинка)
+ $imgResized = $urlShort;
+
+ // Если не внешняя картинка — подставляем корневю дирректорию, чтоб ресайзер понял что ему дают.
+ if (!$isRemote) {
+ $imgResized = ROOT_DIR.$urlShort;
+ }
+
+ if ($service == 'tinypng'
+ && $config['tinypng_key'] == ''
+ ) {
+ $service = 'local';
+ }
+ if ($service == 'kraken'
+ && $config['kraken_key'] == ''
+ ) {
+ $service = 'local';
+ }
+
+ // Определяем новое имя файла
+ $fileName = md5($size.'_'.$resizeType.'_'.$imgResized).'_'.$service.'.'
+ .pathinfo($imgResized, PATHINFO_EXTENSION);
+
+ $newFile = $dir.$fileName;
+ // Если картинки нет в папке обработанных картинок, то попробуем её получить.
+ if (!file_exists($newFile)) {
+ // Если картинка локальная, или картинка внешняя, но разрешено её стянуть — работаем.
+ if (!$isRemote
+ || ($grabRemoteOn
+ && $isRemote)
+ ) {
+ self::getImageWith($service, $imgResized, $newFile, $size, $resizeType, $quality,
+ $config);
+ }
+ }
+
+ $imgResized = (file_exists($newFile)) ? $config['http_home_url'].$imageDir.$fileName
+ : $noimage;
+
+ } else {
+ // Если параметра imgSize нет - отдаём исходную картинку
+ $imgResized = $urlShort;
+ }
+
+ // Отдаём дальше результат обработки.
+ $imageItem = $imgResized;
+
+ } // if($imageType == 'small')
+ $arImages[$i] = $imageItem;
+ if ($number == $i) {
+ break;
+ }
+ $i++;
+ }
+
+ }
+
+ } else {
+ // Если регулярка не нашла картинку - отдадим заглушку
+ $arImages[$number] = $noimage;
+ }
+
+ // Если хотим все картинки — не вопрос, получим массив.
+ if ($number == 'all') {
+
+ return $arImages;
+ }
+
+ // По умолчанию возвращаем отдну картинку (понимаю, что метод должен возвращать всегда один тип данных, но это сделано из-за совместимости версий)
+ return $arImages[$number];
+
+ }
+
+ /**
+ * @param string $service
+ * @param $originalFile
+ * @param $newFile
+ * @param $size
+ * @param $method
+ * @param string $quality
+ * @param array $config
+ */
+ public static function getImageWith(
+ $service = 'local',
+ $originalFile,
+ $newFile,
+ $size,
+ $method,
+ $quality = '100',
+ $config = []
+ ) {
+ // Разделяем высоту и ширину
+ $imgSize = explode('x', $size);
+
+ // Если указана только одна величина - присваиваем второй первую, будет квадрат для exact, auto и crop, иначе класс ресайза жестоко тупит, ожидая вторую переменную.
+ if (count($imgSize) == '1') {
+ $imgSize[1] = $imgSize[0];
+ }
+
+ switch ($service) {
+ // Тянем картинку через встроенный класс ресайза
+ case 'local':
+ // Определяемся с возможными методами уменьшения картинок.
+ $arMethods = [
+ 'exact',
+ 'portrait',
+ 'landscape',
+ 'auto',
+ 'crop',
+ ];
+ $resizeType = (in_array($method, $arMethods)) ? $method : 'auto';
+
+ // Подрубаем локальный класс для картинок
+ $resizeImg = new resize($originalFile);
+ $resizeImg->resizeImage( // Создание уменьшенной копии
+ $imgSize[0], // Размер картинки по ширине
+ $imgSize[1], // Размер картинки по высоте
+ $resizeType // Метод уменьшения (exact, portrait, landscape, auto, crop)
+ );
+ $resizeImg->saveImage($newFile, $quality); // Сохраняем картинку в заданную папку
+ break;
+
+ // Тянем картинку через tinyPNG
+ case 'tinypng':
+
+ // Подключаем необходимые классы (да, без composer в DLE тяжело живётся).
+ require_once ENGINE_DIR.'/modules/base/resizers/tinypng/Tinify.php';
+ require_once ENGINE_DIR.'/modules/base/resizers/tinypng/Tinify/Client.php';
+ require_once ENGINE_DIR.'/modules/base/resizers/tinypng/Tinify/Exception.php';
+ require_once ENGINE_DIR.'/modules/base/resizers/tinypng/Tinify/ResultMeta.php';
+ require_once ENGINE_DIR.'/modules/base/resizers/tinypng/Tinify/Source.php';
+ require_once ENGINE_DIR.'/modules/base/resizers/tinypng/Tinify/Result.php';
+
+ // Определяемся с возможными методами уменьшения картинок.
+ $arMethods = ['portrait', 'landscape', 'auto', 'crop'];
+ $resizeType = (in_array($method, $arMethods)) ? $method : 'auto';
+
+ // Определяемся с опциями обработки картинки
+ $imgSize[0] = (int)$imgSize[0];
+ $imgSize[1] = (int)$imgSize[1];
+
+ $arTinyOptions = [];
+
+ switch ($resizeType) {
+ case 'portrait':
+ $arTinyOptions = [
+ 'method' => 'scale',
+ 'height' => $imgSize[1],
+ ];
+ break;
+
+ case 'landscape':
+ $arTinyOptions = [
+ 'method' => 'scale',
+ 'width' => $imgSize[0],
+ ];
+ break;
+
+ case 'auto':
+ $arTinyOptions = [
+ 'method' => 'fit',
+ 'width' => $imgSize[0],
+ 'height' => $imgSize[1],
+ ];
+ break;
+
+ case 'crop':
+ $arTinyOptions = [
+ 'method' => 'cover',
+ 'width' => $imgSize[0],
+ 'height' => $imgSize[1],
+ ];
+ break;
+ }
+
+ // Вызываем класс и обрабатываем картинку
+ setKey($config['tinypng_key']);
+
+ $source = fromFile($originalFile);
+ $resized = $source->resize($arTinyOptions);
+ $resized->toFile($newFile);
+
+ unset($source, $resized);
+
+ break;
+
+ // Тянем картинку через Kraken
+ case 'kraken':
+ // Определяемся с возможными методами уменьшения картинок.
+ $arMethods = [
+ 'exact',
+ 'portrait',
+ 'landscape',
+ 'auto',
+ 'crop',
+ ];
+ $resizeType = (in_array($method, $arMethods)) ? $method : 'auto';
+ // У Kraken есть свой метод crop, но нам нужен fit
+ if ($method == 'crop') {
+ $resizeType = 'fit';
+ }
+
+ // Подключаем класс Kraken.
+ require_once ENGINE_DIR.'/modules/base/resizers/kraken/Kraken.php';
+
+ $kraken = new Kraken($config['kraken_key'], $config['kraken_secret']);
+
+ // Проверяем наша картинка или чужая. Нужно для корректной передачи данных в kraken
+ $isRemote = (preg_match('~^http(s)?://~', $originalFile)) ? true : false;
+
+ // Параметры ресайза
+ $krakenResize = [
+ 'width' => $imgSize[0],
+ 'height' => $imgSize[1],
+ 'strategy' => $resizeType,
+ ];
+
+ if ($isRemote) {
+ // Если картинка сторонняя
+ $krakenParams = [
+ 'url' => $originalFile,
+ 'wait' => true,
+ 'resize' => $krakenResize,
+ ];
+
+ $krakenData = $kraken->url($krakenParams);
+ } else {
+ // Если картинка наша
+ $krakenParams = [
+ 'file' => $originalFile,
+ 'wait' => true,
+ 'resize' => $krakenResize,
+ ];
+
+ $krakenData = $kraken->upload($krakenParams);
+ }
+
+ if ($krakenData['success']) {
+ $newImg = self::curlGet($krakenData['kraked_url']);
+ file_put_contents($newFile, $newImg);
+ }
+
+ break;
+
+ // Тянем картинку через tinyPNG
+ }
+ }
+
+ public static function curlGet($url) {
+ $ch = curl_init();
+ $default_curlopt = [
+ CURLOPT_TIMEOUT => 15,
+ CURLOPT_RETURNTRANSFER => 1,
+ // CURLOPT_FOLLOWLOCATION => 1,
+ CURLOPT_SSL_VERIFYPEER => false,
+ CURLOPT_USERAGENT => "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0",
+ ];
+ $curlopt = [CURLOPT_URL => $url] + $default_curlopt;
+ curl_setopt_array($ch, $curlopt);
+ $response = curl_exec($ch);
+ if ($response === false) {
+ trigger_error(curl_error($ch));
+ }
+
+ curl_close($ch);
+
+ return $response;
+ }
+
+ /**
+ * Функция для вывода print_r в шаблон
+ *
+ * @param mixed $var входящие данные
+ *
+ * @return string print_r
+ */
+ public static function dump($var) {
+ return print_r($var, true);
+ }
+
+ /**
+ * @param $array
+ * @param bool|false $fields
+ * @param $db
+ *
+ * @return mixed
+ */
+ public static function getAuthors($array, $fields = false, $db) {
+
+ $array = array_unique($array);
+ if ($fields) {
+ $fields = trim($fields);
+ } else {
+ $fields = '*';
+ }
+ if (count($array) == 1) {
+ $select = 'SELECT ?p FROM ?n WHERE name = ?s';
+ $array = $array[0];
+ } else {
+ $select = 'SELECT ?p FROM ?n WHERE name IN(?a)';
+ }
+
+ $_result = $db->getAll($select, $fields, USERPREFIX.'_users', $array);
+
+ foreach ($_result as $key => $user) {
+ unset($user['password']);
+ $result[$user['name']] = $user;
+ }
+
+ /** @var array $result */
+ return $result;
+ }
+
+ /**
+ * Функция для вывода даты в формате "time ago"
+ *
+ *
+ * @param string $date Дата новости
+ * @param integer $precision Кол-во частей
+ *
+ * @return string отформатированная строка
+ */
+ public static function timeAgo($date, $precision = 2) {
+ $precision = ($precision === 0 || $precision === 1) ? 1 : $precision;
+ $times = [
+ 31536000 => '|год|года|лет',
+ 2592000 => 'месяц||а|ев',
+ 604800 => 'недел|ю|и|ь',
+ 86400 => '|день|дня|дней',
+ 3600 => 'час||а|ов',
+ 60 => 'минут|у|ы|',
+ ];
+
+ $timeDiff = time() - strtotime($date);
+
+ if ($timeDiff < 60) {
+ $output = 'меньше минуты';
+ } else {
+ $output = [];
+ $precisionCount = 0;
+
+ foreach ($times as $period => $name) {
+
+ if ($precisionCount >= $precision
+ || ($precisionCount > 0
+ && $period < 1)
+ ) {
+ break;
+ }
+ $result = floor($timeDiff / $period);
+
+ if ($result > 0) {
+ $output[] = $result.' '.self::declinationWords($result, $name);
+
+ $timeDiff -= $result * $period;
+ $precisionCount++;
+ } else {
+ if ($precisionCount > 0) {
+ $precisionCount++;
+ }
+ }
+ }
+
+ $last = array_slice($output, -1);
+ $first = join(', ', array_slice($output, 0, -1));
+ $both = array_filter(array_merge([$first], $last), 'strlen');
+ $outputFormatted = join(' и ', $both);
+
+
+ $output = $outputFormatted;
+ }
+
+ return $output.' назад';
+ }
+
+ /**
+ * Функция для правильного склонения слов
+ *
+ * @param int $n - число, для которого будет расчитано окончание
+ * @param string $words - варианты окончаний для (1 комментарий, 2
+ * комментария, 100 комментариев)
+ *
+ * @return string - слово с правильным окончанием
+ */
+ public static function declinationWords($n = 0, $words) {
+ $words = explode('|', $words);
+ $n = abs((int)$n); // abs на случай отрицательного значения
+
+ return $n % 10 == 1 && $n % 100 != 11
+ ? $words[0].$words[1] : ($n % 10 >= 2 && $n % 10 <= 4 && ($n % 100 < 10 || $n % 100 >= 20) ? $words[0]
+ .$words[2]
+ : $words[0].$words[3]);
+ }
+
+ /**
+ * Функция для конфертации строки в json на случай, если не работает
+ * модификатор json_decode
+ *
+ * @param string $var "{"one":"val"}"
+ *
+ * @return array json-массив
+ */
+ public static function jsonDecode($var) {
+ $decoded = html_entity_decode($var, ENT_COMPAT);
+
+ return json_decode($decoded, true);
+ }
} // bpModifiers
diff --git a/templates/Default/blockpro/css/index.htm b/templates/Default/blockpro/css/index.htm
deleted file mode 100644
index 7d13843..0000000
--- a/templates/Default/blockpro/css/index.htm
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-Error!!!
-
-Error!!!
-
diff --git a/templates/Default/blockpro/index.htm b/templates/Default/blockpro/index.htm
deleted file mode 100644
index 7d13843..0000000
--- a/templates/Default/blockpro/index.htm
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-Error!!!
-
-Error!!!
-
diff --git a/templates/Default/blockpro/js/blockpro.js b/templates/Default/blockpro/js/blockpro.js
index 4e9b3e5..af4a239 100644
--- a/templates/Default/blockpro/js/blockpro.js
+++ b/templates/Default/blockpro/js/blockpro.js
@@ -37,29 +37,16 @@ $(document)
action = $this.data('action');
ShowLoading('');
- $.get(dle_root + 'engine/ajax/favorites.php', {
+ $.get(dle_root + 'engine/ajax/controller.php', {
fav_id: fav_id,
action: action,
- skin: dle_skin
+ skin: dle_skin,
+ mod: 'favorites',
+ alert: 1,
+ user_hash: dle_login_hash || ''
}, function (data) {
HideLoading('');
- var $img = $(data),
- src = $img.prop('src'),
- title = $img.prop('title'),
- imgAction = (action === 'plus') ? 'minus' : 'plus',
- l = src.split(imgAction).length;
- if (l === 2) {
- $('[data-favorite-id=' + fav_id + ']')
- .prop({
- alt: title,
- title: title,
- src: src
- })
- .data({
- action: imgAction,
- favoriteId: fav_id
- });
- }
+ DLEalert(data, dle_info);
});
});
@@ -87,45 +74,6 @@ function base_loader(id, method, className) {
}
}
-/**
- * Функция выставления рейтинга в модуле blockpro
- *
- * @author ПафНутиЙ
- *
- *
- * @return string Результат обработки рейтинга
- * @param rate
- * @param id
- */
-function base_rate(rate, id) {
- ShowLoading('');
-
- $.get(dle_root + 'engine/ajax/rating.php', {
- go_rate: rate,
- news_id: id,
- skin: dle_skin,
- user_hash: dle_login_hash || ''
- }, function (data) {
- HideLoading('');
- if (data.success) {
- var rating = data.rating;
-
- rating = rating.replace(/</g, '<');
- rating = rating.replace(/>/g, '>');
- rating = rating.replace(/&/g, '&');
-
- $('[data-rating-layer="' + id + '"]').html(rating);
- $('[data-vote-num-id="' + id + '"]').html(data.votenum);
-
- $('#ratig-layer-' + id).html(rating);
- $('#vote-num-id-' + id).html(data.votenum);
- } else if (data.error) {
- DLEalert(data.errorinfo, dle_info);
- }
-
- }, 'json');
-}
-
/**
* Выставление рейтинга для DLE 13
* @see base_rate
diff --git a/templates/Default/blockpro/js/blockpro_new.js b/templates/Default/blockpro/js/blockpro_new.js
deleted file mode 100644
index 6288399..0000000
--- a/templates/Default/blockpro/js/blockpro_new.js
+++ /dev/null
@@ -1,197 +0,0 @@
-/*!https://github.com/Mikhus/jsurl/blob/master/url.js*/
-var Url=function(){"use strict";var t={protocol:"protocol",host:"hostname",port:"port",path:"pathname",query:"search",hash:"hash"},r={ftp:21,gopher:70,http:80,https:443,ws:80,wss:443},o=function(o,e){var a=document,i=a.createElement("a"),e=e||a.location.href,n=e.match(/\/\/(.*?)(?::(.*?))?@/)||[];i.href=e;for(var h in t)o[h]=i[t[h]]||"";if(o.protocol=o.protocol.replace(/:$/,""),o.query=o.query.replace(/^\?/,""),o.hash=o.hash.replace(/^#/,""),o.user=n[1]||"",o.pass=n[2]||"",o.port=r[o.protocol]==o.port||0==o.port?"":o.port,o.protocol||/^([a-z]+:)?\/\//.test(e))o.path=o.path.replace(/^\/?/,"/");else{var p=new Url(a.location.href.match(/(.*\/)/)[0]),c=p.path.split("/"),f=o.path.split("/");c.pop();for(var h=0,u=["protocol","user","pass","host","port"],l=u.length;l>h;h++)o[u[h]]=p[u[h]];for(;".."==f[0];)c.pop(),f.shift();o.path=("/"!=e.substring(0,1)?c.join("/"):"")+"/"+f.join("/")}s(o)},e=function(t){return t=t.replace(/\+/g," "),t=t.replace(/%([ef][0-9a-f])%([89ab][0-9a-f])%([89ab][0-9a-f])/gi,function(t,r,o,e){var s=parseInt(r,16)-224,a=parseInt(o,16)-128;if(0==s&&32>a)return t;var i=parseInt(e,16)-128,n=(s<<12)+(a<<6)+i;return n>65535?t:String.fromCharCode(n)}),t=t.replace(/%([cd][0-9a-f])%([89ab][0-9a-f])/gi,function(t,r,o){var e=parseInt(r,16)-192;if(2>e)return t;var s=parseInt(o,16)-128;return String.fromCharCode((e<<6)+s)}),t=t.replace(/%([0-7][0-9a-f])/gi,function(t,r){return String.fromCharCode(parseInt(r,16))})},s=function(t){var r=t.query;t.query=new function(t){for(var r,o=/([^=&]+)(=([^&]*))?/g;r=o.exec(t);){var s=decodeURIComponent(r[1].replace(/\+/g," ")),a=r[3]?e(r[3]):"";null!=this[s]?(this[s]instanceof Array||(this[s]=[this[s]]),this[s].push(a)):this[s]=a}this.clear=function(){for(s in this)this[s]instanceof Function||delete this[s]},this.toString=function(){var t="",r=encodeURIComponent;for(var o in this)if(!(this[o]instanceof Function))if(this[o]instanceof Array){var e=this[o].length;if(e)for(var s=0;e>s;s++)t+=t?"&":"",t+=r(o)+"="+r(this[o][s]);else t+=(t?"&":"")+r(o)+"="}else t+=t?"&":"",t+=r(o)+"="+r(this[o]);return t}}(r)};return function(t){this.toString=function(){return(this.protocol&&this.protocol+"://")+(this.user&&this.user+(this.pass&&":"+this.pass)+"@")+(this.host&&this.host)+(this.port&&":"+this.port)+(this.path&&this.path)+(this.query.toString()&&"?"+this.query)+(this.hash&&"#"+this.hash)},o(this,t)}}();
-
-var thisUrl = window.location.pathname;
-
-$(document)
- .on('click touchstart browserNavigation', '[data-page-num]', function (event) {
- var $this = $(this),
- blockId = $this.parent().data('blockId'),
- pageNum = $this.data('pageNum'),
- $block = $('#' + blockId),
- u = new Url,
- url;
-
- u.query.bid = blockId;
- u.query.p = pageNum;
- url = u;
-
- base_loader(blockId, 'start');
-
- $.ajax({
- url: dle_root + 'engine/ajax/blockpro.php',
- dataType: 'html',
- data: {
- pageNum: pageNum,
- blockId: blockId,
- thisUrl: thisUrl
- }
- })
- .done(function (data) {
- $block.html($(data).html());
- if (history.pushState && event.type !== 'browserNavigation') {
- window.history.pushState(null, null, url);
- }
- })
- .fail(function () {
- base_loader(blockId, 'stop');
- console.log("error");
- })
- .always(function () {
- base_loader(blockId, 'stop');
- });
-
- })
- .on('click touchstart', '[data-favorite-id]', function (event) {
- event.preventDefault();
- var $this = $(this),
- fav_id = $this.data('favoriteId'),
- action = $this.data('action');
-
- ShowLoading('');
- $.get(dle_root + 'engine/ajax/favorites.php', {
- fav_id: fav_id,
- action: action,
- skin: dle_skin
- }, function (data) {
- HideLoading('');
- var $img = $(data),
- src = $img.prop('src'),
- title = $img.prop('title'),
- imgAction = (action === 'plus') ? 'minus' : 'plus',
- l = src.split(imgAction).length;
- if (l === 2) {
- $('[data-favorite-id=' + fav_id + ']')
- .prop({
- alt: title,
- title: title,
- src: src
- })
- .data({
- action: imgAction,
- favoriteId: fav_id
- });
- }
- });
-
- });
-
-$(window).on('popstate', function () {
- browseTrigger();
-});
-
-jQuery(document).ready(function () {
- browseTrigger();
-});
-
-/**
- * Переход к нужной странице навигации блока модуля blockpro
- */
-function browseTrigger() {
- var u = new Url(location.href);
- if (u.query.bid) {
- $('#' + u.query.bid).find('[data-page-num="' + u.query.p + '"]:first').trigger('browserNavigation');
- }
-}
-
-/**
- * Простейшая функция для реализации эффекта загрузки блока
- * Добавляет/удаляет заданный класс для заданного блока
- * вся работа по оформлению ложится на css
- *
- * @author ПафНутиЙ
- *
- * @param id
- * @param method
- * @param className
- */
-function base_loader(id, method, className) {
- var $block = $('#' + id),
- cname = (className) ? className : 'base-loader';
- if (method === 'start') {
- $block.addClass(cname);
- }
-
- if (method === 'stop') {
- $block.removeClass(cname);
- }
-}
-
-/**
- * Функция выставления рейтинга в модуле blockpro
- *
- * @author ПафНутиЙ
- *
- *
- * @return string Результат обработки рейтинга
- * @param rate
- * @param id
- */
-function base_rate(rate, id) {
- ShowLoading('');
-
- $.get(dle_root + 'engine/ajax/rating.php', {
- go_rate: rate,
- news_id: id,
- skin: dle_skin,
- user_hash: dle_login_hash || ''
- }, function (data) {
- HideLoading('');
- if (data.success) {
- var rating = data.rating;
-
- rating = rating.replace(/</g, '<');
- rating = rating.replace(/>/g, '>');
- rating = rating.replace(/&/g, '&');
-
- $('[data-rating-layer="' + id + '"]').html(rating);
- $('[data-vote-num-id="' + id + '"]').html(data.votenum);
-
- $('#ratig-layer-' + id).html(rating);
- $('#vote-num-id-' + id).html(data.votenum);
- } else if (data.error) {
- DLEalert(data.errorinfo, dle_info);
- }
-
- }, 'json');
-}
-
-/**
- * Выставление рейтинга для DLE 13
- * @see base_rate
- * @param rate
- * @param id
- */
-function base_rate13(rate, id) {
- ShowLoading('');
- $.get(dle_root + 'engine/ajax/controller.php?mod=rating', {
- go_rate: rate,
- news_id: id,
- skin: dle_skin,
- user_hash: dle_login_hash || ''
- }, function(data){
-
- HideLoading('');
-
- if (data.success) {
- var rating = data.rating;
-
- rating = rating.replace(/</g, '<');
- rating = rating.replace(/>/g, '>');
- rating = rating.replace(/&/g, '&');
-
- $('[data-rating-layer="' + id + '"]').html(rating);
- $('[data-vote-num-id="' + id + '"]').html(data.votenum);
-
- $('#ratig-layer-' + id).html(rating);
- $('#vote-num-id-' + id).html(data.votenum);
-
- $('#likes-id-' + id).html(data.likes);
- $('#dislikes-id-' + id).html(data.dislikes);
-
- } else if (data.error) {
- DLEalert(data.errorinfo, dle_info);
- }
-
- }, "json");
-}
\ No newline at end of file
diff --git a/templates/Default/blockpro/js/index.htm b/templates/Default/blockpro/js/index.htm
deleted file mode 100644
index 7d13843..0000000
--- a/templates/Default/blockpro/js/index.htm
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-Error!!!
-
-Error!!!
-
From a671372d728caf0a2fd2533856db14ed3af17f67 Mon Sep 17 00:00:00 2001
From: pafnuty
Date: Sat, 22 Feb 2020 21:23:18 +0400
Subject: [PATCH 2/5] =?UTF-8?q?6.0.0=20=D0=9F=D0=B5=D1=80=D0=B5=D0=BC?=
=?UTF-8?q?=D0=B5=D1=89=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=84=D0=B0=D0=B9=D0=BB?=
=?UTF-8?q?=D0=BE=D0=B2=20=D1=88=D0=B0=D0=B1=D0=BB=D0=BE=D0=BD=D0=BE=D0=B2?=
=?UTF-8?q?=20=D0=B2=20=D0=BF=D1=80=D0=B0=D0=B2=D0=B8=D0=BB=D1=8C=D0=BD?=
=?UTF-8?q?=D1=83=D1=8E=20=D0=BF=D0=B0=D0=BF=D0=BA=D1=83?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
templates/{Default => {THEME}}/blockpro/.htaccess | 0
.../{Default => {THEME}}/blockpro/base-loader.gif | Bin
.../{Default => {THEME}}/blockpro/blockpro.tpl | 0
templates/{Default => {THEME}}/blockpro/bp1.tpl | 0
.../{Default => {THEME}}/blockpro/bp_comments.tpl | 2 +-
.../{Default => {THEME}}/blockpro/cachevars.tpl | 0
.../{Default => {THEME}}/blockpro/css/.htaccess | 0
.../{Default => {THEME}}/blockpro/css/blockpro.css | 0
.../{Default => {THEME}}/blockpro/external.tpl | 0
.../{Default => {THEME}}/blockpro/fullexample.tpl | 0
.../{Default => {THEME}}/blockpro/getuserinfo.tpl | 0
templates/{Default => {THEME}}/blockpro/group.tpl | 0
templates/{Default => {THEME}}/blockpro/iframe.tpl | 0
.../{Default => {THEME}}/blockpro/js/.htaccess | 0
.../{Default => {THEME}}/blockpro/js/blockpro.js | 4 ++--
templates/{Default => {THEME}}/blockpro/list.tpl | 0
templates/{Default => {THEME}}/blockpro/noimage.png | Bin
.../{Default => {THEME}}/blockpro/noimage_big.png | Bin
templates/{Default => {THEME}}/blockpro/rss.tpl | 0
.../blockpro/template_inner.tpl | 0
.../blockpro/template_wrapper.tpl | 0
21 files changed, 3 insertions(+), 3 deletions(-)
rename templates/{Default => {THEME}}/blockpro/.htaccess (100%)
rename templates/{Default => {THEME}}/blockpro/base-loader.gif (100%)
rename templates/{Default => {THEME}}/blockpro/blockpro.tpl (100%)
rename templates/{Default => {THEME}}/blockpro/bp1.tpl (100%)
rename templates/{Default => {THEME}}/blockpro/bp_comments.tpl (89%)
rename templates/{Default => {THEME}}/blockpro/cachevars.tpl (100%)
rename templates/{Default => {THEME}}/blockpro/css/.htaccess (100%)
rename templates/{Default => {THEME}}/blockpro/css/blockpro.css (100%)
rename templates/{Default => {THEME}}/blockpro/external.tpl (100%)
rename templates/{Default => {THEME}}/blockpro/fullexample.tpl (100%)
rename templates/{Default => {THEME}}/blockpro/getuserinfo.tpl (100%)
rename templates/{Default => {THEME}}/blockpro/group.tpl (100%)
rename templates/{Default => {THEME}}/blockpro/iframe.tpl (100%)
rename templates/{Default => {THEME}}/blockpro/js/.htaccess (100%)
rename templates/{Default => {THEME}}/blockpro/js/blockpro.js (96%)
rename templates/{Default => {THEME}}/blockpro/list.tpl (100%)
rename templates/{Default => {THEME}}/blockpro/noimage.png (100%)
rename templates/{Default => {THEME}}/blockpro/noimage_big.png (100%)
rename templates/{Default => {THEME}}/blockpro/rss.tpl (100%)
rename templates/{Default => {THEME}}/blockpro/template_inner.tpl (100%)
rename templates/{Default => {THEME}}/blockpro/template_wrapper.tpl (100%)
diff --git a/templates/Default/blockpro/.htaccess b/templates/{THEME}/blockpro/.htaccess
similarity index 100%
rename from templates/Default/blockpro/.htaccess
rename to templates/{THEME}/blockpro/.htaccess
diff --git a/templates/Default/blockpro/base-loader.gif b/templates/{THEME}/blockpro/base-loader.gif
similarity index 100%
rename from templates/Default/blockpro/base-loader.gif
rename to templates/{THEME}/blockpro/base-loader.gif
diff --git a/templates/Default/blockpro/blockpro.tpl b/templates/{THEME}/blockpro/blockpro.tpl
similarity index 100%
rename from templates/Default/blockpro/blockpro.tpl
rename to templates/{THEME}/blockpro/blockpro.tpl
diff --git a/templates/Default/blockpro/bp1.tpl b/templates/{THEME}/blockpro/bp1.tpl
similarity index 100%
rename from templates/Default/blockpro/bp1.tpl
rename to templates/{THEME}/blockpro/bp1.tpl
diff --git a/templates/Default/blockpro/bp_comments.tpl b/templates/{THEME}/blockpro/bp_comments.tpl
similarity index 89%
rename from templates/Default/blockpro/bp_comments.tpl
rename to templates/{THEME}/blockpro/bp_comments.tpl
index eed6b15..060faef 100644
--- a/templates/Default/blockpro/bp_comments.tpl
+++ b/templates/{THEME}/blockpro/bp_comments.tpl
@@ -32,7 +32,7 @@
{/foreach}
{else}
- Этот шаблон следует вызывать подключать внутри цикла, используя такую конструкцию:
+ Этот шаблон следует подключать внутри цикла, используя такую конструкцию:
+ При включении параметра и если модуль MultiLanguage включен, то:
+
+
+ Будут учитываться настройки фильтрации новостей в соответсвии с настройками модуля MultiLanguage
+
+
+ Будет корректно формироваться ссылка на полную новость с учётом языка сайта
+
+
+ Заголовок, полная и краткая новость будет браться в соответствии с настройками модуля MultiLanguage
+
+
+
+
+
+
+
+ Языки, добавленные в модуле MultiLanguage от japing.pw
+
+
+
+
+
+ Коды языков, добавленный в модуле MultiLanguage. Язык по умолчанию указывать не нужно, нужны только те языки, которые были добавлены дополнительно (указывать через запятую, если я зыков несколько).
+
+
+
+
diff --git a/engine/modules/base/admin/blockpro/js/main.js b/engine/modules/base/admin/blockpro/js/main.js
index 50f286b..36c05c3 100644
--- a/engine/modules/base/admin/blockpro/js/main.js
+++ b/engine/modules/base/admin/blockpro/js/main.js
@@ -5,7 +5,6 @@ BlockPro
Автор: ПафНутиЙ
URL: http://pafnuty.name/
twitter: https://twitter.com/pafnuty_name
-google+: http://gplus.to/pafnuty
email: pafnuty10@gmail.com
=============================================================================
*/
diff --git a/engine/modules/base/admin/blockpro/vidgets.php b/engine/modules/base/admin/blockpro/vidgets.php
index 9afd9d0..feb1b77 100644
--- a/engine/modules/base/admin/blockpro/vidgets.php
+++ b/engine/modules/base/admin/blockpro/vidgets.php
@@ -6,7 +6,6 @@
Автор: ПафНутиЙ
URL: http://pafnuty.name/
twitter: https://twitter.com/pafnuty_name
-google+: http://gplus.to/pafnuty
email: pafnuty10@gmail.com
=============================================================================
*/
diff --git a/engine/modules/base/blockpro.php b/engine/modules/base/blockpro.php
index e092d66..db42196 100644
--- a/engine/modules/base/blockpro.php
+++ b/engine/modules/base/blockpro.php
@@ -6,15 +6,14 @@
Автор: ПафНутиЙ
URL: http://pafnuty.name/
twitter: https://twitter.com/pafnuty_name
-google+: http://gplus.to/pafnuty
email: pafnuty10@gmail.com
=============================================================================
*/
if (!defined('DATALIFEENGINE')) {
- header( "HTTP/1.1 403 Forbidden" );
- header ( 'Location: ../../' );
- die( "Hacking attempt!" );
+ header("HTTP/1.1 403 Forbidden");
+ header('Location: ../../');
+ die("Hacking attempt!");
}
/**
@@ -27,8 +26,8 @@
/** @var bool $showstat */
if ($showstat) {
- $start = microtime(true);
- $dbStat = '';
+ $start = microtime(true);
+ $dbStat = '';
}
/**
* Конфиг модуля
@@ -36,139 +35,13 @@
* @global array $isAjaxConfig
*/
if ($isAjaxConfig) {
- /** @var array $ajaxConfigArr */
- $cfg = $ajaxConfigArr;
+ /** @var array $ajaxConfigArr */
+ $cfg = $ajaxConfigArr;
} else {
- $cfg = [
- 'moderate' => !empty($moderate) ? $moderate : false,
- // Показывать только новости на модерации
-
- 'template' => !empty($template) ? $template : 'blockpro/blockpro',
- // Название шаблона (без расширения)
-
- 'cachePrefix' => !empty($cachePrefix) ? $cachePrefix : 'news',
- // Префикс кеша
- 'cacheSuffixOff' => !empty($cacheSuffixOff) ? true : false,
- // Отключить суффикс кеша (будет создаваться один кеш-файл для всех пользователей). По умолчанию включен, т.е. для каждой группы пользователей будет создаваться свой кеш (на случай разного отображения контента разным юзерам).
-
- 'cacheNameAddon' => '',
- // Назначаем дополнение к имени кеша, если имеются переменные со значениями this, они будут дописаны в имя кеша, иначе для разных мест будет создаваться один и тот же файл кеша
-
- 'nocache' => !empty($nocache) ? $nocache : false,
- // Не использовать кеш
- 'cacheLive' => (!empty($cacheLive) && !$mcache) ? $cacheLive : false,
- // Время жизни кеша в минутах
-
- 'startFrom' => !empty($startFrom) ? $startFrom : '0',
- // C какой новости начать вывод
- 'limit' => !empty($limit) ? $limit : '10',
- // Количество новостей в блоке
- 'fixed' => !empty($fixed) ? $fixed : 'yes',
- // Обработка фиксированных новостей (yes/only/without показ всех/только фиксированных/только обычных новостей)
- 'allowMain' => !empty($allowMain) ? $allowMain : 'yes',
- // Обработка новостей, опубликованных на главной (yes/only/without показ всех/только на главной/только не на главной)
- 'postId' => !empty($postId) ? $postId : '',
- // ID новостей для вывода в блоке (через запятую, или черточку)
- 'notPostId' => !empty($notPostId) ? $notPostId : '',
- // ID игнорируемых новостей (через запятую, или черточку)
-
- 'author' => !empty($author) ? $author : '',
- // Логины авторов, для показа их новостей в блоке (через запятую)
- 'notAuthor' => !empty($notAuthor) ? $notAuthor : '',
- // Логины игнорируемых авторов (через запятую)
-
- 'xfilter' => !empty($xfilter) ? $xfilter : '',
- // Имена дополнительных полей для фильтрации новостей по ним (через запятую)
- 'notXfilter' => !empty($notXfilter) ? $notXfilter : '',
- // Имена дополнительных полей для игнорирования показа новостей (через запятую)
-
- 'xfSearch' => !empty($xfSearch) ? $xfSearch : false,
- // синтаксис передачи данных: &xfSearch=имя_поля|значение||имя_поля|значение
- 'notXfSearch' => !empty($notXfSearch) ? $notXfSearch : false,
- // синтаксис передачи данных: ¬XfSearch=имя_поля|значение||имя_поля|значение
- 'xfSearchLogic' => !empty($xfSearchLogic) ? $xfSearchLogic : 'OR',
- // Принимает OR или AND (по умолчанию OR)
-
- 'catId' => !empty($catId) ? $catId : '',
- // Категории для показа (через запятую, или черточку)
- 'subcats' => !empty($subcats) ? $subcats : false,
- // Выводить подкатегории указанных категорий (&subcats=y), работает и с диапазонами.
- 'notCatId' => !empty($notCatId) ? $notCatId : '',
- // Игнорируемые категории (через запятую, или черточку)
- 'notSubcats' => !empty($notSubcats) ? $notSubcats : false,
- // Игнорировать подкатегории игнорируемых категорий (¬Subcats=y), работает и с диапазонами.
- 'thisCatOnly' => !empty($thisCatOnly) ? $thisCatOnly : false,
- // Показывать новости ТОЛЬКО из текущей категории (имеет смысл при выводе похожих новостей и использоваии мультикатегорий).
-
- 'tags' => !empty($tags) ? $tags : '',
- // Теги из облака тегов для показа новостей, содержащих их (через запятую)
- 'notTags' => !empty($notTags) ? $notTags : '',
- // Игнорируемые теги (через запятую)
-
- 'day' => !empty($day) ? $day : false,
- // Временной период для отбора новостей
- 'dayCount' => !empty($dayCount) ? $dayCount : false,
- // Интервал для отбора (т.е. к примеру выбираем новости за прошлую недею так: &day=14&dayCount=7 )
- 'sort' => !empty($sort) ? $sort : 'top',
- // Сортировка (top, date, comms, rating, views, title, hit, random, randomLight, download, symbol, editdate или xf|xfieldname где xfieldname - имя дополнительного поля, field|p.name где p.name — кастомное поле)
- 'xfSortType' => !empty($xfSortType) ? $xfSortType : 'int',
- // Тип сортировки по допполю (string, int) - для корректной сортировки по строке используем string, по умолчанию сортируется как число (для цен полезно).
- 'order' => !empty($order) ? $order : 'new',
- // Направление сортировки (new, old, asis)
-
- 'avatar' => !empty($avatar) ? $avatar : false,
- // Вывод аватарки пользователя (немного усложнит запрос).
-
- 'showstat' => !empty($showstat) ? $showstat : false,
- // Показывать время и статистику по блоку
-
- 'related' => !empty($related) ? $related : false,
- // Включить режим вывода похожих новостей (по умолчанию нет)
- 'saveRelated' => !empty($saveRelated) ? $saveRelated : false,
- // Включить запись похожих новостей в БД
- 'showNav' => !empty($showNav) ? $showNav : false,
- // Включить постраничную навигацию
- 'navDefaultGet' => !empty($navDefaultGet) ? $navDefaultGet : false,
- // Слушать дефолтный get-параметр постраничной навигации
- 'pageNum' => !empty($pageNum) ? $pageNum : '1',
- // Текущая страница при постраничной конфигурации
- 'navStyle' => !empty($navStyle) ? $navStyle : 'classic',
- // Стиль навигации. Возможны следующие стили:
- /*
- classic: << Первая < 1 [2] 3 > Последняя >>
- digg: << Назад 1 2 ... 5 6 7 8 9 [10] 11 12 13 14 ... 25 26 Вперёд >>
- extended: << Назад | Страница 2 из 11 | Показаны новости 6-10 из 52 | Вперёд >>
- punbb: 1 ... 4 5 [6] 7 8 ... 15
- arrows: << Назад Вперёд >>
- */
- /**
- * @todo реализовать функционал с options и notOptions
- */
- 'options' => !empty($options) ? $options : false,
- // Опции, публикации новости для показа (Публиковать на главной, Разрешить рейтинг статьи, Разрешить комментарии, Запретить индексацию страницы для поисковиков, Зафиксировать новость) main|rating|comments|noindex
- 'notOptions' => !empty($notOptions) ? $notOptions : false,
- // Опции, публикации новости для исключения (Публиковать на главной, Разрешить рейтинг статьи, Разрешить комментарии, Запретить индексацию страницы для поисковиков, Зафиксировать новость) main|rating|comments|noindex
-
- 'future' => !empty($future) ? $future : false,
- // Выводить только новости, дата публикации которых не наступила (Полезно для афиш) &future=y
- 'cacheVars' => !empty($cacheVars) ? $cacheVars : false,
- // Значимые переменные в формировании кеша блока на случай разного вывода в зависимости от условий расположения модуля. Сюда можно передавать ключи, доступные через $_REQUEST или значения переменной $dle_module
- 'symbols' => !empty($symbols) ? $symbols : false,
- // Символьные коды для фильтрации по символьному каталогу. Перечисляем через запятую.
- 'notSymbols' => !empty($notSymbols) ? $notSymbols : false,
- // Символьные коды для исключающей фильтрации по символьному каталогу. Перечисляем через запятую или пишем this для текущего символьного кода
- 'fields' => !empty($fields) ? $fields : false,
- // Дополнение к выборке полей из БД (p.field,e.field)
- // setFilter=p.full_story|SEARCH|dle_media_begin|OR|p.full_story|SEARCH|dle_video_begin
- // setFilter=e.news_read|+|100||p.comm_num|-|20
- 'setFilter' => !empty($setFilter) ? $setFilter : '',
- // Собственная фильтрация полей БД
- 'experiment' => !empty($experiment) ? $experiment : false,
- // Включить экспериментальные функции
- ];
+ include ENGINE_DIR.'/modules/base/core/config.php';
}
-include ENGINE_DIR . '/data/blockpro.php';
+include ENGINE_DIR.'/data/blockpro.php';
// Объединяем массивы конфигов
/** @var array $bpConfig */
@@ -176,88 +49,132 @@ classic: << Первая < 1 [2] 3 > Последняя >>
// Получаем id текущей категории при AJAX навигации
if ($isAjaxConfig && ($cfg['catId'] == 'this' || $cfg['notCatId'] == 'this')) {
- /**
- * @var string $thisUrl
- * @see engine/ajax/blockpro.php
- */
- if (substr($thisUrl, -1, 1) == '/') {
- $thisUrl = substr($thisUrl, 0, -1);
- }
- $arThisUrl = explode('/', $thisUrl);
- $thisCatName = end($arThisUrl);
- if (trim($thisCatName) != '') {
- $category_id = get_ID($cat_info, $thisCatName);
- }
+ /**
+ * @var string $thisUrl
+ * @see engine/ajax/blockpro.php
+ */
+ if (substr($thisUrl, -1, 1) == '/') {
+ $thisUrl = substr($thisUrl, 0, -1);
+ }
+ $arThisUrl = explode('/', $thisUrl);
+ $thisCatName = end($arThisUrl);
+ if (trim($thisCatName) != '') {
+ $category_id = get_ID($cat_info, $thisCatName);
+ }
}
// Сохраняем текущее значение переменной, если она задана (fix #142)
$startCacheNameAddon = $cfg['cacheNameAddon'];
-$cfg['cacheNameAddon'] = [];
+$cfg['cacheNameAddon'] = [];
$cfg['cacheNameAddon'][] = $startCacheNameAddon;
// Если имеются переменные со значениями this, изменяем значение переменной cacheNameAddon
if ($cfg['catId'] == 'this') {
- $cfg['cacheNameAddon'][] = $category_id . 'cId_';
+ $cfg['cacheNameAddon'][] = $category_id.'cId_';
}
if ($cfg['notCatId'] == 'this') {
- $cfg['cacheNameAddon'][] = $category_id . 'nCId_';
+ $cfg['cacheNameAddon'][] = $category_id.'nCId_';
}
if ($cfg['postId'] == 'this') {
- $cfg['cacheNameAddon'][] = $_REQUEST['newsid'] . 'pId_';
+ $cfg['cacheNameAddon'][] = $_REQUEST['newsid'].'pId_';
}
if ($cfg['notPostId'] == 'this') {
- $cfg['cacheNameAddon'][] = $_REQUEST['newsid'] . 'nPId_';
+ $cfg['cacheNameAddon'][] = $_REQUEST['newsid'].'nPId_';
}
if ($cfg['author'] == 'this') {
- $cfg['cacheNameAddon'][] = $_REQUEST['user'] . 'a_';
+ $cfg['cacheNameAddon'][] = $_REQUEST['user'].'a_';
}
if ($cfg['notAuthor'] == 'this') {
- $cfg['cacheNameAddon'][] = $_REQUEST['user'] . 'nA_';
+ $cfg['cacheNameAddon'][] = $_REQUEST['user'].'nA_';
}
if ($cfg['tags'] == 'this') {
- $cfg['cacheNameAddon'][] = $_REQUEST['tag'] . 't_';
+ $cfg['cacheNameAddon'][] = $_REQUEST['tag'].'t_';
}
if ($cfg['notTags'] == 'this') {
- $cfg['cacheNameAddon'][] = $_REQUEST['tag'] . 'nT_';
+ $cfg['cacheNameAddon'][] = $_REQUEST['tag'].'nT_';
}
if ($cfg['symbols'] == 'this') {
- $cfg['cacheNameAddon'][] = $_REQUEST['catalog'] . 's_';
+ $cfg['cacheNameAddon'][] = $_REQUEST['catalog'].'s_';
}
if ($cfg['notSymbols'] == 'this') {
- $cfg['cacheNameAddon'][] = $_REQUEST['catalog'] . 'nS_';
+ $cfg['cacheNameAddon'][] = $_REQUEST['catalog'].'nS_';
}
if ($cfg['related'] == 'this') {
- $cfg['cacheNameAddon'][] = $_REQUEST['newsid'] . 'r_';
+ $cfg['cacheNameAddon'][] = $_REQUEST['newsid'].'r_';
}
if ($cfg['xfilter'] == 'this') {
- $cfg['cacheNameAddon'][] = $_REQUEST['xf'] . 'xf_';
+ $cfg['cacheNameAddon'][] = $_REQUEST['xf'].'xf_';
}
if ($cfg['notXfilter'] == 'this') {
- $cfg['cacheNameAddon'][] = $_REQUEST['xf'] . 'nXf_';
+ $cfg['cacheNameAddon'][] = $_REQUEST['xf'].'nXf_';
}
if ($cfg['navDefaultGet']) {
- $cfg['cacheNameAddon'][] = $_REQUEST['cstart'] . 'cs_';
+ $cfg['cacheNameAddon'][] = $_REQUEST['cstart'].'cs_';
}
if ($cfg['cacheVars']) {
- // Если установлена переменная, добавим в имя кеша требуемые дополнения
- // Убираем пробелы, на всякий пожарный
- $cfg['cacheVars'] = str_replace(' ', '', $cfg['cacheVars']);
- // Разбиваем строку на массив
- $arCacheVars = explode(',', $cfg['cacheVars']);
- foreach ($arCacheVars as $cacheVar) {
- // Сверяем данные из массива с данными, доступными на странице
- if (isset($_REQUEST[$cacheVar])) {
- $cfg['cacheNameAddon'][] = $_REQUEST[$cacheVar] . $cacheVar . '_';
- }
- if ($dle_module == $cacheVar) {
- $cfg['cacheNameAddon'][] = $dle_module . '_';
- }
- }
+ // Если установлена переменная, добавим в имя кеша требуемые дополнения
+ // Убираем пробелы, на всякий пожарный
+ $cfg['cacheVars'] = str_replace(' ', '', $cfg['cacheVars']);
+ // Разбиваем строку на массив
+ $arCacheVars = explode(',', $cfg['cacheVars']);
+ foreach ($arCacheVars as $cacheVar) {
+ // Сверяем данные из массива с данными, доступными на странице
+ if (isset($_REQUEST[$cacheVar])) {
+ $cfg['cacheNameAddon'][] = $_REQUEST[$cacheVar].$cacheVar.'_';
+ }
+ if ($dle_module == $cacheVar) {
+ $cfg['cacheNameAddon'][] = $dle_module.'_';
+ }
+ }
+
+}
+
+// Поддержка модуля multiLang
+$multiLangEnabled = false;
+// По умолчанию язык пустой
+$langVariant = '';
+// Задаём пустой массив для конфига модуля MultiLanguage
+$lang_config = [];
+// Получаем список доступных языков в виде массива
+$langList = explode('|', $cfg['langList']);
+$multiLangAdditionalFields = $multiLangNewsFields = [];
+
+if ($cfg['multiLang'] && isset($_REQUEST['lang'])) {
+ $requestLang = trim($_REQUEST['lang']);
+
+ // Если язык доступен, работаем
+ if (in_array($requestLang, $langList)) {
+ // Импортируем конфиг модуля MultiLanguage
+ include ENGINE_DIR.'/data/multilanguage_config.php';
+
+ // Если модуль включен, работаем
+ if ($lang_config['mod_on']) {
+ // Добавляем параметры в кеш
+ $cfg['cacheNameAddon'][] = 'multiLang_'.$_REQUEST['lang'].'_';
+ // Устанавливаем нужный язык для дальнейшего использования в запросах
+ $langVariant = $requestLang;
+ $multiLangEnabled = true;
+
+ $multiLangAdditionalFields = [
+ '1' => 'p.title_'.$langVariant,
+ '2' => 'p.short_story_'.$langVariant,
+ '3' => 'p.full_story_'.$langVariant,
+ ];
+
+ $multiLangNewsFields = [
+ '1' => [0 => 'title', 1 => 'title_'.$langVariant],
+ '2' => [0 => 'short_story', 1 => 'short_story_'.$langVariant],
+ '3' => [0 => 'full_story', 1 => 'full_story_'.$langVariant],
+ ];
+
+ $multiLngEnabledFields = explode(',', $lang_config['fields_news']);
+ }
+ }
}
$cfg['cacheNameAddon'] = array_filter($cfg['cacheNameAddon']);
@@ -266,921 +183,985 @@ classic: << Первая < 1 [2] 3 > Последняя >>
$cfg['cacheNameAddon'] = implode('_', $cfg['cacheNameAddon']);
if ($cfg['cacheLive']) {
- // Меняем префикс кеша для того, чтобы он не чистился автоматически, если указано время жизни кеша.
- $cfg['cachePrefix'] = 'base';
+ // Меняем префикс кеша для того, чтобы он не чистился автоматически, если указано время жизни кеша.
+ $cfg['cachePrefix'] = 'base';
}
// Определяемся с шаблоном сайта
// Проверим куку пользователя и наличие параметра skin в реквесте.
-$currentSiteSkin = (isset($_COOKIE['dle_skin'])) ? trim(totranslit($_COOKIE['dle_skin'], false, false)) : ((isset($_REQUEST['skin'])) ? trim(totranslit($_REQUEST['skin'], false, false)) : $config['skin']);
+$currentSiteSkin = (isset($_COOKIE['dle_skin'])) ? trim(totranslit($_COOKIE['dle_skin'], false, false))
+ : ((isset($_REQUEST['skin'])) ? trim(totranslit($_REQUEST['skin'], false, false)) : $config['skin']);
// Если итоге пусто — назначим опять шаблон из конфига.
if ($currentSiteSkin == '') {
- $currentSiteSkin = $config['skin'];
+ $currentSiteSkin = $config['skin'];
}
// Если парки с шаблоном нет — дальше не работаем.
-if (!@is_dir(ROOT_DIR . '/templates/' . $currentSiteSkin)) {
- die('no_skin');
+if (!@is_dir(ROOT_DIR.'/templates/'.$currentSiteSkin)) {
+ die('no_skin');
}
// Формируем имя кеша
-$cacheName = implode('_', $cfg) . $currentSiteSkin;
+$cacheName = implode('_', $cfg).$currentSiteSkin;
// Определяем необходимость создания кеша для разных групп
$cacheSuffix = ($cfg['cacheSuffixOff']) ? false : true;
$clear_time_cache = false;
// Если установлено время жизни кеша
if ($cfg['cacheLive']) {
- // Формируем имя кеш-файла в соответствии с правилами формирования тагового стандартными средствами DLE, для последующей проверки на существование этого файла.
- $_end_file = (!$cfg['cacheSuffixOff']) ? ($is_logged) ? '_' . $member_id['user_group'] : '_0' : false;
- $filedate = ENGINE_DIR . '/cache/' . $cfg['cachePrefix'] . '_' . md5($cacheName) . $_end_file . '.tmp';
-
- // Определяем в чём измеять время жизни кеша, в минутах или секундах
- $cacheLiveTimer = (strpos($cfg['cacheLive'], 's')) ? (int)$cfg['cacheLive'] : $cfg['cacheLive'] * 60;
-
- if (@file_exists($filedate)) {
- $cache_time = time() - @filemtime($filedate);
- } else {
- $cache_time = $cacheLiveTimer;
- }
- if ($cache_time >= $cacheLiveTimer) {
- $clear_time_cache = true;
- }
+ // Формируем имя кеш-файла в соответствии с правилами формирования такового стандартными средствами DLE, для последующей проверки на существование этого файла.
+ $_end_file = (!$cfg['cacheSuffixOff']) ? ($is_logged) ? '_'.$member_id['user_group'] : '_0' : false;
+ $filedate = ENGINE_DIR.'/cache/'.$cfg['cachePrefix'].'_'.md5($cacheName).$_end_file.'.tmp';
+
+ // Определяем в чём измеять время жизни кеша, в минутах или секундах
+ $cacheLiveTimer = (strpos($cfg['cacheLive'], 's')) ? (int)$cfg['cacheLive'] : $cfg['cacheLive'] * 60;
+
+ if (@file_exists($filedate)) {
+ $cache_time = time() - @filemtime($filedate);
+ } else {
+ $cache_time = $cacheLiveTimer;
+ }
+ if ($cache_time >= $cacheLiveTimer) {
+ $clear_time_cache = true;
+ }
}
$output = false;
// Массив для записи возникающих ошибок
$outputLog = [
- 'errors' => [],
- 'info' => []
+ 'errors' => [],
+ 'info' => [],
];
// Если nocache не установлен - пытаемся вывести данные из кеша.
if (!$cfg['nocache']) {
- $output = dle_cache($cfg['cachePrefix'], $cacheName, $cacheSuffix);
+ $output = dle_cache($cfg['cachePrefix'], $cacheName, $cacheSuffix);
}
// Сбрасываем данные, если истекло время жизни кеша
if ($clear_time_cache) {
- $output = false;
+ $output = false;
}
if (!$output) {
- // Подключаем всё необходимое
- include_once 'core/base.php';
+ // Подключаем всё необходимое
+ include_once 'core/base.php';
- // Вызываем ядро
- $base = new base();
+ // Вызываем ядро
+ $base = new base();
- // Назначаем конфиг модуля
- $base->cfg = $base->setConfig($cfg);
+ // Назначаем конфиг модуля
+ $base->cfg = $base->setConfig($cfg);
- // Назначаем текущий шаблон сайта
- $base->dle_config['skin'] = $currentSiteSkin;
+ // Назначаем текущий шаблон сайта
+ $base->dle_config['skin'] = $currentSiteSkin;
- // Пустой массив для конфга шаблонизатора.
- $tplOptions = [];
+ // Пустой массив для конфга шаблонизатора.
+ $tplOptions = [];
- // Если кеширование блока отключено - будем автоматически проверять скомпилированный шаблон на изменения.
- if ($base->cfg['nocache']) {
- $tplOptions['auto_reload'] = true;
- }
+ // Если кеширование блока отключено - будем автоматически проверять скомпилированный шаблон на изменения.
+ if ($base->cfg['nocache']) {
+ $tplOptions['auto_reload'] = true;
+ }
- // Подключаем опции шаблонизатора
- $base->tplOptions = $base->setConfig($tplOptions);
- // Подключаем шаблонизатор
- $base->getTemplater($base->tplOptions);
+ // Подключаем опции шаблонизатора
+ $base->tplOptions = $base->setConfig($tplOptions);
+ // Подключаем шаблонизатор
+ $base->getTemplater($base->tplOptions);
- // Добавляем глобавльный тег $.blockPro
- $base->tpl->addAccessorSmart('blockPro', 'block_pro', Fenom::ACCESSOR_PROPERTY);
- $base->tpl->block_pro = $base;
+ // Добавляем глобавльный тег $.blockPro
+ $base->tpl->addAccessorSmart('blockPro', 'block_pro', Fenom::ACCESSOR_PROPERTY);
+ $base->tpl->block_pro = $base;
- // Определяем начало сегодняшнего дня и дату "прямо вот сейчас".
- if ($base->dle_config['version_id'] > 10.2) {
- date_default_timezone_set($base->dle_config['date_adjust']);
- $today = date('Y-m-d H:i:s', (mktime(0, 0, 0) + 86400));
- $rightNow = date('Y-m-d H:i:s', time());
- } else {
- $today = date('Y-m-d H:i:s', (mktime(0, 0, 0) + 86400 + $base->dle_config['date_adjust'] * 60));
- $rightNow = date('Y-m-d H:i:s', (time() + $base->dle_config['date_adjust'] * 60));
- }
-
- if ($base->cfg['navDefaultGet']) {
- $base->cfg['pageNum'] = (isset($_GET['cstart']) && (int)$_GET['cstart'] > 0) ? (int)$_GET['cstart'] : 1;
- }
-
- // Массив с условиями запроса
- $wheres = [];
-
- // По умолчанию имеем пустые дополнения в запрос.
- $ext_query_fields = $ext_query = '';
-
- // По умолчанию группировки нет (она нам понадобится при фильтрации по аттачментам).
- $groupBy = '';
-
- // Условие для отображения только постов, прошедших модерацию или находящихся на модерации
- $wheres[] = ($base->cfg['moderate']) ? 'approve = 0' : 'approve';
-
- // Добавляем пользовательскую фильтрацию
- if ($base->cfg['setFilter'] != '') {
-
- $arFilter = [];
-
- if (strpos($base->cfg['setFilter'], '||')) {
- $arFilter = explode('||', $base->cfg['setFilter']);
- } else {
- $arFilter[] = $base->cfg['setFilter'];
- }
-
-
- if (!empty($arFilter)) {
- foreach ($arFilter as $strItem) {
- $queryItem = $base->prepareFilterQuery($strItem);
-
- if($queryItem) {
- $wheres[] = $queryItem;
- }
-
- }
- }
- }
-
- // Определяем в какую сторону направлена сортировка
- $ordering = ($base->cfg['order'] == 'new') ? 'DESC' : 'ASC';
-
- // Если без сортировки - сбрасываем направление
- if ($base->cfg['sort'] == 'none') {
- $ordering = false;
- }
- // Массив, куда будем записывать сортировки
- $orderArr = [];
-
- // Учёт фиксированных новостей
- switch ($base->cfg['fixed']) {
- case 'only':
- $wheres[] = 'fixed = 1';
- break;
-
- case 'without':
- $wheres[] = 'fixed = 0';
- break;
-
- case 'ignore':
- $wheres[] = '';
- break;
-
- default:
- // Если включен режим афиши и установлена сортировка по убыванию даты, фиксированные новости должны отображаться в начале списка.
- $fixedNewsOrdering = ($base->cfg['future'] && $base->cfg['sort'] != 'new') ? 'DESC' : $ordering;
-
- if ($base->cfg['sort'] != 'random' && $base->cfg['sort'] != 'randomLight' && $base->cfg['sort'] != 'none' && $base->cfg['sort'] != 'editdate') {
- $orderArr[] = 'fixed ' . $fixedNewsOrdering;
- }
- break;
- }
-
- // Учёт новостей на главной
- switch ($base->cfg['allowMain']) {
- case 'only':
- $wheres[] = 'allow_main = 1';
- break;
-
- case 'without':
- $wheres[] = 'allow_main = 0';
- break;
-
- default:
- // по умолчанию показываем все
- break;
- }
- // Зададим произвольное имя для несуществующей сортировки
- $xfSortName = 'blockpro_undefined_sort_xfields';
- if (strpos($base->cfg['sort'], 'xf|') !== false) {
- // Если задана сортировка по значению допполя - то присвоим переменной имя этого поля и подкорректируем данные для swich
- $xfSortName = str_replace('xf|', '', $base->cfg['sort']);
- }
-
- $fieldSortName = 'blockpro_undefined_sort_field';
-
- if (strpos($base->cfg['sort'], 'field|') !== false) {
- // Если задана сортировка по кастомном полю - то присвоим переменной имя этого поля и подкорректируем данные для swich
- $fieldSortName = str_replace('field|', '', $base->cfg['sort']);
- }
-
- // Определяем тип сортировки
- switch ($base->cfg['sort']) {
- case 'none': // Не сортировать (можно использовать для вывода похожих новостей, аналогично стандарту DLE)
- // $orderArr[] = false;
- break;
-
- case 'date': // Дата
- $orderArr[] = 'p.date ' . $ordering;
- break;
-
- case 'rating': // Рейтинг
- $orderArr[] = 'e.rating ' . $ordering;
- break;
-
- case 'comms': // Комментарии
- $orderArr[] = 'p.comm_num ' . $ordering;
- break;
-
- case 'views': // Просмотры
- $orderArr[] = 'e.news_read ' . $ordering;
- break;
-
- case 'random': // Случайные
- $orderArr[] = 'RAND()';
- // randomLight ниже т.к. у него отдельный алгоритм
- break;
-
- case 'title': // По алфавиту
- $orderArr[] = 'p.title ' . $ordering;
- break;
-
- case 'download': // По количеству скачиваний
- $orderArr[] = 'dcount ' . $ordering;
- break;
-
- case 'symbol': // По символьному коду
- $orderArr[] = 'p.symbol ' . $ordering;
- break;
-
- case 'hit': // Правильный топ
- $wheres[] = 'e.rating > 0';
- $orderArr[] = '(e.rating*100+p.comm_num*10+e.news_read) ' . $ordering;
- break;
-
- case 'top': // Топ как в DLE (сортировка по умолчанию)
- $orderArr[] = 'e.rating ' . $ordering . ', p.comm_num ' . $ordering . ', e.news_read ' . $ordering;
- break;
-
- case 'editdate': // По дате редактрования
- $orderArr[] = 'e.editdate ' . $ordering;
- $wheres[] = 'e.editdate > 0';
- break;
-
- case 'xf|' . $xfSortName: // Сортировка по значению дополнительного поля
- if ($base->cfg['xfSortType'] == 'string') {
- $orderArr[] = 'sort_xfield ' . $ordering;
- } else {
- $orderArr[] = 'CAST(sort_xfield AS DECIMAL(12,2)) ' . $ordering;
- }
- $ext_query_fields .= ", SUBSTRING_INDEX(SUBSTRING_INDEX(p.xfields, '{$xfSortName}|', -1 ) , '||', 1 ) as sort_xfield ";
- break;
-
- case 'field|' . $fieldSortName: // Сортировка по кастомному полю
- $orderArr[] = $fieldSortName . ' ' . $ordering;
- break;
-
- }
-
- // Необходимо учитывать категорию для вывода похожих новостей, если категорию не задал пользователь.
- // https://github.com/dle-modules/DLE-BlockPro/issues/155
- if (!$base->cfg['catId'] && $base->cfg['related'] && $base->dle_config['related_only_cats']) {
- $base->cfg['catId'] = 'this';
- }
-
- // Эти переменные потребуются ниже, что бы корректно сформировать имя кеша, когда переданы
- // &catId=this или notCatId=this
- $isCatIdThis = false;
- $isNotCatIdThis = false;
-
- // Фильтрация КАТЕГОРИЙ по их ID
- if ($base->cfg['catId'] == 'this' && $category_id) {
- $isCatIdThis = true;
- /**
- * @see https://github.com/dle-modules/DLE-BlockPro/issues/159
- */
- $base->cfg['catId'] = $category_id;
- if($base->cfg['subcats']) {
- $base->cfg['catId'] = get_sub_cats($category_id);
- } elseif ($base->cfg['thisCatOnly']) {
- $base->cfg['catId'] = (int)$category_id;
- }
- }
- if ($base->cfg['notCatId'] == 'this' && $category_id) {
- $isNotCatIdThis = true;
- /**
- * @see https://github.com/dle-modules/DLE-BlockPro/issues/159
- */
- $base->cfg['notCatId'] = $category_id;
- if ($base->cfg['notSubcats']) {
- $base->cfg['notCatId'] = get_sub_cats($category_id);
- } elseif($base->cfg['thisCatOnly']) {
- $base->cfg['notCatId'] = (int)$category_id;
- }
- }
- // Дублирование кода вызвано необходимостью сочетания параметра notCatId и catId
- // Например: catId=this¬CatId=3
- if ($base->cfg['notCatId']) {
- $notCatArr = $base->getDiapazone($base->cfg['notCatId'], $base->cfg['notSubcats']);
- if ($notCatArr[0] > 0) {
- if ($base->dle_config['allow_multi_category'] && !$base->cfg['thisCatOnly']) {
- $notCatQPart = 'category regexp "[[:<:]](' . str_replace(',', '|', $notCatArr) . ')[[:>:]]"';
- } else {
- $notCatQPart = 'category IN (\'' . str_replace(',', "','", $notCatArr) . '\')';
- }
-
- $wheres[] = 'NOT ' . $notCatQPart;
- }
- }
-
- if ($base->cfg['catId']) {
- $catArr = $base->getDiapazone($base->cfg['catId'], $base->cfg['subcats']);
- if ($catArr[0] > 0) {
- if ($base->dle_config['allow_multi_category'] && !$base->cfg['thisCatOnly']) {
- $catQPart = 'category regexp "[[:<:]](' . str_replace(',', '|', $catArr) . ')[[:>:]]"';
- } else {
- $catQPart = 'category IN (\'' . str_replace(',', "','", $catArr) . '\')';
- }
-
- $wheres[] = $catQPart;
- }
- }
-
- // Фильтрация НОВОСТЕЙ по их ID
- if ($base->cfg['postId'] == 'this' && $_REQUEST['newsid']) {
- $base->cfg['postId'] = $_REQUEST['newsid'];
- }
- if ($base->cfg['notPostId'] == 'this' && $_REQUEST['newsid']) {
- $base->cfg['notPostId'] = $_REQUEST['newsid'];
- }
-
- if ($base->cfg['notPostId']) {
- $notPostsArr = $base->getDiapazone($base->cfg['notPostId']);
- if ($notPostsArr !== '0') {
- $wheres[] = 'id NOT IN (' . $notPostsArr . ')';
- }
- }
-
- if ($base->cfg['postId'] && $base->cfg['related'] == '') {
- $postsArr = $base->getDiapazone($base->cfg['postId']);
- if ($postsArr !== '0') {
- $wheres[] = 'id IN (' . $postsArr . ')';
- }
- }
-
- // Фильтрация новостей по АВТОРАМ
- if ($base->cfg['author'] == 'this' && isset($_REQUEST['user'])) {
- $base->cfg['author'] = $_REQUEST['user'];
- }
- if ($base->cfg['notAuthor'] == 'this' && isset($_REQUEST['user'])) {
- $base->cfg['notAuthor'] = $_REQUEST['user'];
- }
- if ($base->cfg['author'] || $base->cfg['notAuthor']) {
- $ignoreAuthors = ($base->cfg['notAuthor']) ? 'NOT ' : '';
- $authorsArr = ($base->cfg['notAuthor']) ? $base->cfg['notAuthor'] : $base->cfg['author'];
- if ($authorsArr !== 'this') {
- // Если в строке подключения &author=this и мы просматриваем страницу юзера, то сюда уже попадёт логин пользователя
- $authorsArr = explode(',', $authorsArr);
- $wheres[] = (count($authorsArr) === 1) ? $ignoreAuthors . 'autor = ' . $base->db->parse('?s', $authorsArr[0]) : $ignoreAuthors . 'autor regexp "[[:<:]](' . implode('|', $authorsArr) . ')[[:>:]]"';
- }
- }
-
- // Фильтрация новостей по ДОПОЛНИТЕЛЬНЫМ ПОЛЯМ (проверяется только на заполненность)
- $_currentXfield = false;
- if ($base->cfg['xfilter'] == 'this' && isset($_REQUEST['xf'])) {
- $base->cfg['xfilter'] = $base->db->parse('?s', '%' . $_REQUEST['xf'] . '%');
- $_currentXfield = true;
- }
- if ($base->cfg['notXfilter'] == 'this' && isset($_REQUEST['xf'])) {
- $base->cfg['notXfilter'] = $base->db->parse('?s', '%' . $_REQUEST['xf'] . '%');
- $_currentXfield = true;
- }
-
- if ($base->cfg['xfilter'] || $base->cfg['notXfilter']) {
- $ignoreXfilters = ($base->cfg['notXfilter']) ? 'NOT ' : '';
- $xfiltersArr = ($base->cfg['notXfilter']) ? $base->cfg['notXfilter'] : $base->cfg['xfilter'];
-
- if ($xfiltersArr !== 'this') {
- // Если в строке подключения &xfilter=this и мы просматриваем страницу допполя, то сюда уже попадёт имя этого поля
- $wheres[] = ($_currentXfield) ? $ignoreXfilters . 'xfields LIKE ' . $xfiltersArr : $ignoreXfilters . 'p.xfields regexp "[[:<:]](' . str_replace(',', '|', $xfiltersArr) . ')[[:>:]]"';
- }
- }
-
- // Фильтрация по ЗНАЧЕНИЮ ДОПОЛНИТЕЛЬНЫХ ПОЛЕЙ
- if ($base->cfg['xfSearch'] || $base->cfg['notXfSearch']) {
-
- // Массив для составления подзапроса
- $xfWheres = [];
-
- // Защита логики построения запроса от кривых рук (если прописать неправильно - будет логика OR)
- $_xfSearchLogic = (strtolower($base->cfg['xfSearchLogic']) == 'and') ? ' AND ' : ' OR ';
-
- // Определяем масивы с данными по фильтрации
- $xfSearchArray = ($base->cfg['xfSearch']) ? explode('||', $base->cfg['xfSearch']) : [];
- $notXfSearchArray = ($base->cfg['notXfSearch']) ? explode('||', $base->cfg['notXfSearch']) : [];
-
- $bXfNotResult = true;
- if ($base->dle_config['version_id'] >= '11' && $base->cfg['experiment']) {
- // Если версия DLE 11 и более и включена экспериментальная функция, то для увеличения скорости выборки запросим данные по допполям из отдельной таблицы.
-
- // Пробегаем по сформированным массивам
- foreach ($xfSearchArray as $xf) {
- $_xf = explode('|', $xf);
- $xfWheres[] = $base->db->parse('(tagname=?s AND tagvalue=?s)', $_xf[0], $_xf[1]);
- }
- foreach ($notXfSearchArray as $xf) {
- $_xf = explode('|', $xf);
- $xfWheres[] = $base->db->parse('(tagname=?s AND NOT tagvalue=?s)', $_xf[0], $_xf[1]);
- }
- // Подготавливаем запрос.
- $xfSearchQuery = implode($_xfSearchLogic, $xfWheres);
-
- // Получаем ID новостей
- $xfSearchIDs = $base->db->getCol('SELECT news_id FROM ?n WHERE ?p', PREFIX . '_xfsearch', $xfSearchQuery);
- // Если запрос вернул ID новостей — работаем.
- if (count($xfSearchIDs)) {
- // Оставляем только уникальные
- $xfSearchIDs = array_unique($xfSearchIDs);
-
- // Добавляем полученные данные в основной массив, формирующий запрос
- $wheres[] = 'p.id IN (' . implode(',', $xfSearchIDs) . ')';
-
- $bXfNotResult = false;
- } else {
- // Если ничего не найдено — сбросим массив с условиями т.к. строка подключения возможно содержит дополнительные условия выборки.
- $xfWheres = [];
- }
- }
-
- if ($bXfNotResult) {
- // Пробегаем по сформированным массивам
- // str_replace('|', '|%', $xf) необходимо для случаев, когда значение допполя идёт не первым в списке
- foreach ($xfSearchArray as $xf) {
- $xfWheres[] = $base->db->parse('p.xfields LIKE ?s', '%' . str_replace('|', '|%', $xf) . '%');
- }
- foreach ($notXfSearchArray as $xf) {
- $xfWheres[] = $base->db->parse('p.xfields NOT LIKE ?s', '%' . str_replace('|', '|%', $xf) . '%');
- }
-
- // Добавляем полученные данные (и логику) в основной массив, формирующий запрос
- $wheres[] = '(' . implode($_xfSearchLogic, $xfWheres) . ')';
- }
- }
-
- // Фильтрация новостей по ТЕГАМ
- $_currentTag = false;
- if ($base->cfg['tags'] == 'this' && isset($_REQUEST['tag']) && $_REQUEST['tag'] != '') {
- $base->cfg['tags'] = $base->db->parse('?s', $_REQUEST['tag']);
- $_currentTag = true;
- }
- if ($base->cfg['notTags'] == 'this' && isset($_REQUEST['tag']) && $_REQUEST['tag'] != '') {
- $base->cfg['notTags'] = $base->db->parse('?s', $_REQUEST['tag']);
- $_currentTag = true;
- }
-
- // Фильтрация новостей по тегам текущей новости, когда в строке подключения прописано &tags=thisNewsTags и мы просматриваем полную новость
- if ((int)$_REQUEST['newsid'] > 0) {
- if ($base->cfg['tags'] == 'thisNewsTags' || $base->cfg['notTags'] == 'thisNewsTags') {
- $curTagNewsId = $base->db->getRow('SELECT tags FROM ?n WHERE id=?i', PREFIX . '_post', $_REQUEST['newsid']);
- if (!empty($curTagNewsId['tags'])) {
- if ($base->cfg['tags'] == 'thisNewsTags') {
- // Заменяем запятую и пробел на просто запятую, иначе будет ошибка.
- $base->cfg['tags'] = str_replace(', ', ',', $curTagNewsId['tags']);
- }
- if ($base->cfg['notTags'] == 'thisNewsTags') {
- // Заменяем запятую и пробел на просто запятую, иначе будет ошибка.
- $base->cfg['notTags'] = str_replace(', ', ',', $curTagNewsId['notTags']);
- }
- }
- }
- }
-
- if ($base->cfg['tags'] || $base->cfg['notTags']) {
- $ignoreTags = ($base->cfg['notTags']) ? 'NOT ' : '';
- $tagsArr = ($base->cfg['notTags']) ? $base->cfg['notTags'] : $base->cfg['tags'];
-
-
- if ($tagsArr !== 'this') {
- // Если в строке подключения &tags=this и мы просматриваем страницу тегов, то сюда уже попадёт название тега
- $wherTag = ($_currentTag) ? $ignoreTags . 'tag = ' . $tagsArr : $ignoreTags . 'tag regexp "[[:<:]](' . str_replace(',', '|', $tagsArr) . ')[[:>:]]"';
- // Делаем запрос на получение ID новостей, содержащих требуемые теги
- $tagNews = $base->db->getCol('SELECT news_id FROM ?n WHERE ?p', PREFIX . '_tags', $wherTag);
- $tagNews = array_unique($tagNews);
-
- if (count($tagNews)) {
- $wheres[] = 'id ' . $ignoreTags . ' IN (' . implode(',', $tagNews) . ')';
- }
-
- }
- }
-
- // Фильтрация новостей по символьным кодам
- $_currentSymbol = false;
- if ($base->cfg['symbols'] == 'this' && isset($_REQUEST['catalog'])) {
- $base->cfg['symbols'] = $base->db->parse('?s', $_REQUEST['catalog']);
- $_currentSymbol = true;
- }
- if ($base->cfg['notSymbols'] == 'this' && isset($_REQUEST['catalog'])) {
- $base->cfg['notSymbols'] = $base->db->parse('?s', $_REQUEST['catalog']);
- $_currentSymbol = true;
- }
-
- if ($base->cfg['symbols'] || $base->cfg['notSymbols']) {
- $ignoreSymbols = ($base->cfg['notSymbols']) ? 'NOT ' : '';
- $symbolsArr = ($base->cfg['notSymbols']) ? $base->cfg['notSymbols'] : $base->cfg['symbols'];
- if ($symbolsArr !== 'this') {
- // Если в строке подключения &symbols=this и мы просматриваем страницу буквенного каталога, то сюда уже попадёт название буквы
- $wheres[] = ($_currentSymbol) ? $ignoreSymbols . 'symbol = ' . $symbolsArr : $ignoreSymbols . 'symbol regexp "[[:<:]](' . str_replace(',', '|', $symbolsArr) . ')[[:>:]]"';
- }
- }
-
- // Если включен режим вывода похожих новостей:
- $reltedFirstShow = false;
- if ($base->cfg['related']) {
- if ($base->cfg['related'] == 'this' && $_REQUEST['newsid'] == '') {
- $outputLog['errors'][] = 'Переменная related=this работает только в полной новости и не работает с ЧПУ 3 типа.';
- } else {
-
- $relatedId = ($base->cfg['related'] == 'this') ? $_REQUEST['newsid'] : $base->cfg['related'];
- $relatedRows = 'p.title, p.short_story, p.full_story, p.xfields';
- $relatedIdParsed = $base->db->parse('id = ?i', $relatedId);
-
- $relatedBody = $base->db->getRow('SELECT id, ?p FROM ?n p LEFT JOIN ?n e ON (p.id=e.news_id) WHERE ?p', 'p.title, p.short_story, p.full_story, p.xfields, e.related_ids', PREFIX . '_post', PREFIX . '_post_extras', $relatedIdParsed);
- // Фикс https://github.com/dle-modules/DLE-BlockPro/issues/78
- if ($relatedBody['id']) {
- /** @var bool $saveRelated */
- if ($relatedBody['related_ids'] && $saveRelated) {
- // Если есть запись id похожих новостей — добавим в условие запроса эти новости.
- $wheres[] = 'id IN(' . $relatedBody['related_ids'] . ')';
- // Отсортируем новости в том порядке, в котором они записаны в БД
- $orderArr = ['FIELD (p.id, ' . $relatedBody['related_ids'] . ')'];
- } else {
- // Если похожие новости не записывались — отберём их.
- $reltedFirstShow = true;
- $bodyToRelated = (dle_strlen($relatedBody['full_story'], $base->dle_config['charset']) < dle_strlen($relatedBody['short_story'], $base->dle_config['charset'])) ? $relatedBody['short_story'] : $relatedBody['full_story'];
-
- $bodyToRelated = strip_tags(stripslashes($relatedBody['title'] . ' ' . $bodyToRelated));
-
- // Фикс для https://github.com/pafnuty/BlockPro/issues/79
- // @see /engine/modules/show.full.php
- if (dle_strlen($bodyToRelated, $base->dle_config['charset']) > 1000) {
- $bodyToRelated = dle_substr($bodyToRelated, 0, 1000, $base->dle_config['charset']);
- }
-
- $bodyToRelated = $base->db->parse('?s', $bodyToRelated);
-
- // Добавляем улучшенный алгоритм поиска похожих новостей из DLE 13
- $ext_query_fields .= ', MATCH (p.title, p.short_story, p.full_story, p.xfields) AGAINST (' . $bodyToRelated . ') as score';
- $orderArr = ['score DESC'];
-
- // Формируем условие выборки
- $wheres[] = 'MATCH (' . $relatedRows . ') AGAINST (' . $bodyToRelated . ') AND id !=' . $relatedBody['id'];
- }
- } else {
- $outputLog['errors'][] = 'Новость с ID ' . $relatedIdParsed . ' не найдена в базе данных.';
- }
- }
-
-
- }
-
- // Определяем переменные, чтоб сто раз не писать одно и тоже
- $bDay = (int)$base->cfg['day'];
- $bDayCount = (int)$base->cfg['dayCount'];
-
- // Если в bDay и bDayCount передано '-1', значит требуется вывести новости только за сегодня.
- // Это обработка случая, когда включен вывод новостей на ненаступившую дату и надо вывести за сегодня
- // https://pafnuty.omnidesk.ru/staff/cases/record/181-466935/
- if ($bDay === -1 && $bDayCount === -1) {
- // Формируем вывод новостей только за сегодня
- $wheres[] = 'p.date >= "' . $today . '" - INTERVAL 1 DAY';
- $wheres[] = 'p.date < "' . $today . '"';
- } else {
- // Если future задан, то интервал не вычитаем, а прибавляем к текущему началу дня
- $intervalOperator = ($base->cfg['future']) ? ' + ' : ' - ';
-
- // Если режим афиши включен - выводим новости, дата которых ещё не наступила.
- if ($base->cfg['future'] && (!$bDay && !$bDayCount)) {
- $wheres[] = 'p.date > "' . $rightNow . '"';
- }
-
- // Если включен вывод новостей на ненаступившую дату в настройках DLE
- // и режим афиши не используется, то нельзя выводить новости дата которых не наступила до текущей секунды
- if (!$base->cfg['future'] && ($base->dle_config['news_future'] && $base->dle_config['news_future'] !== 'no')) {
- $wheres[] = 'p.date <= "' . $rightNow . '"';
- }
-
- // Разбираемся с временными рамками отбора новостей, если кол-во дней указано - ограничиваем выборку, если нет - выводим без ограничения даты
- if ($bDay) {
- $wheres[] = 'p.date >= "' . $today . '" ' . $intervalOperator . ' INTERVAL ' . (($base->cfg['future']) ? ($bDay - $bDayCount) : $bDay) . ' DAY';
- }
- // Если задана переменная dayCount и day, а так же day больше dayCount - отбираем новости за указанный интервал от указанного периода
- if ($bDay && $bDayCount && ($bDayCount <= $bDay)) {
- $wheres[] = 'p.date < "' . $today . '" ' . $intervalOperator . ' INTERVAL ' . (($base->cfg['future']) ? $bDay : ($bDay - $bDayCount)) . ' DAY';
- } else {
- // Условие для отображения только тех постов, дата публикации которых уже наступила
- $wheres[] = ($base->dle_config['no_date'] && !$base->dle_config['news_future'] && !$base->cfg['future']) ? 'p.date < "' . $rightNow . '"' : '';
- }
-
- }
-
- // Подчистим массив от пустых значений
- $wheres = array_filter($wheres);
-
- // Когда выбран вариант вывода случайных новостей (Лёгкий режим)
- if ($base->cfg['sort'] == 'randomLight') {
-
- // Складываем условия выборки для рандомных новостей
- $randWhere = (count($wheres)) ? ' WHERE ' . implode(' AND ', $wheres) : '';
- // Получим массив с id новостей
- $randDiapazone = $base->db->getCol('SELECT id FROM ?n AS p ?p', PREFIX . '_post', $randWhere);
- // Перемешаем
- shuffle($randDiapazone);
- // Возьмём только нужное количество элементов
- $randIds = array_slice($randDiapazone, 0, $base->cfg['limit']);
+ // Определяем начало сегодняшнего дня и дату "прямо вот сейчас".
+ if ($base->dle_config['version_id'] > 10.2) {
+ date_default_timezone_set($base->dle_config['date_adjust']);
+ $today = date('Y-m-d H:i:s', (mktime(0, 0, 0) + 86400));
+ $rightNow = date('Y-m-d H:i:s', time());
+ } else {
+ $today = date('Y-m-d H:i:s', (mktime(0, 0, 0) + 86400 + $base->dle_config['date_adjust'] * 60));
+ $rightNow = date('Y-m-d H:i:s', (time() + $base->dle_config['date_adjust'] * 60));
+ }
+
+ if ($base->cfg['navDefaultGet']) {
+ $base->cfg['pageNum'] = (isset($_GET['cstart']) && (int)$_GET['cstart'] > 0) ? (int)$_GET['cstart'] : 1;
+ }
+
+ // Массив с условиями запроса
+ $wheres = [];
+
+ // По умолчанию имеем пустые дополнения в запрос.
+ $ext_query_fields = $ext_query = '';
+
+ // По умолчанию группировки нет (она нам понадобится при фильтрации по аттачментам).
+ $groupBy = '';
+
+ // Условие для отображения только постов, прошедших модерацию или находящихся на модерации
+ $wheres[] = ($base->cfg['moderate']) ? 'approve = 0' : 'approve';
+
+ // Добавляем пользовательскую фильтрацию
+ if ($base->cfg['setFilter'] != '') {
+
+ $arFilter = [];
+
+ if (strpos($base->cfg['setFilter'], '||')) {
+ $arFilter = explode('||', $base->cfg['setFilter']);
+ } else {
+ $arFilter[] = $base->cfg['setFilter'];
+ }
+
+
+ if (!empty($arFilter)) {
+ foreach ($arFilter as $strItem) {
+ $queryItem = $base->prepareFilterQuery($strItem);
+
+ if ($queryItem) {
+ $wheres[] = $queryItem;
+ }
+
+ }
+ }
+ }
+
+ // Определяем в какую сторону направлена сортировка
+ $ordering = ($base->cfg['order'] == 'new') ? 'DESC' : 'ASC';
+
+ // Если без сортировки - сбрасываем направление
+ if ($base->cfg['sort'] == 'none') {
+ $ordering = false;
+ }
+ // Массив, куда будем записывать сортировки
+ $orderArr = [];
+
+ // Учёт фиксированных новостей
+ switch ($base->cfg['fixed']) {
+ case 'only':
+ $wheres[] = 'fixed = 1';
+ break;
+
+ case 'without':
+ $wheres[] = 'fixed = 0';
+ break;
+
+ case 'ignore':
+ $wheres[] = '';
+ break;
+
+ default:
+ // Если включен режим афиши и установлена сортировка по убыванию даты, фиксированные новости должны отображаться в начале списка.
+ $fixedNewsOrdering = ($base->cfg['future'] && $base->cfg['sort'] != 'new') ? 'DESC' : $ordering;
+
+ if ($base->cfg['sort'] != 'random' && $base->cfg['sort'] != 'randomLight' && $base->cfg['sort'] != 'none'
+ && $base->cfg['sort'] != 'editdate'
+ ) {
+ $orderArr[] = 'fixed '.$fixedNewsOrdering;
+ }
+ break;
+ }
+
+ // Учёт новостей на главной
+ switch ($base->cfg['allowMain']) {
+ case 'only':
+ $wheres[] = 'allow_main = 1';
+ break;
+
+ case 'without':
+ $wheres[] = 'allow_main = 0';
+ break;
+
+ default:
+ // по умолчанию показываем все
+ break;
+ }
+ // Зададим произвольное имя для несуществующей сортировки
+ $xfSortName = 'blockpro_undefined_sort_xfields';
+ if (strpos($base->cfg['sort'], 'xf|') !== false) {
+ // Если задана сортировка по значению допполя - то присвоим переменной имя этого поля и подкорректируем данные для swich
+ $xfSortName = str_replace('xf|', '', $base->cfg['sort']);
+ }
+
+ $fieldSortName = 'blockpro_undefined_sort_field';
+
+ if (strpos($base->cfg['sort'], 'field|') !== false) {
+ // Если задана сортировка по кастомном полю - то присвоим переменной имя этого поля и подкорректируем данные для swich
+ $fieldSortName = str_replace('field|', '', $base->cfg['sort']);
+ }
+
+ // Определяем тип сортировки
+ switch ($base->cfg['sort']) {
+ case 'none': // Не сортировать (можно использовать для вывода похожих новостей, аналогично стандарту DLE)
+ // $orderArr[] = false;
+ break;
+
+ case 'date': // Дата
+ $orderArr[] = 'p.date '.$ordering;
+ break;
+
+ case 'rating': // Рейтинг
+ $orderArr[] = 'e.rating '.$ordering;
+ break;
+
+ case 'comms': // Комментарии
+ $orderArr[] = 'p.comm_num '.$ordering;
+ break;
+
+ case 'views': // Просмотры
+ $orderArr[] = 'e.news_read '.$ordering;
+ break;
+
+ case 'random': // Случайные
+ $orderArr[] = 'RAND()';
+ // randomLight ниже т.к. у него отдельный алгоритм
+ break;
+
+ case 'title': // По алфавиту
+ $orderArr[] = 'p.title '.$ordering;
+ break;
+
+ case 'download': // По количеству скачиваний
+ $orderArr[] = 'dcount '.$ordering;
+ break;
+
+ case 'symbol': // По символьному коду
+ $orderArr[] = 'p.symbol '.$ordering;
+ break;
+
+ case 'hit': // Правильный топ
+ $wheres[] = 'e.rating > 0';
+ $orderArr[] = '(e.rating*100+p.comm_num*10+e.news_read) '.$ordering;
+ break;
+
+ case 'top': // Топ как в DLE (сортировка по умолчанию)
+ $orderArr[] = 'e.rating '.$ordering.', p.comm_num '.$ordering.', e.news_read '.$ordering;
+ break;
+
+ case 'editdate': // По дате редактрования
+ $orderArr[] = 'e.editdate '.$ordering;
+ $wheres[] = 'e.editdate > 0';
+ break;
+
+ case 'xf|'.$xfSortName: // Сортировка по значению дополнительного поля
+ if ($base->cfg['xfSortType'] == 'string') {
+ $orderArr[] = 'sort_xfield '.$ordering;
+ } else {
+ $orderArr[] = 'CAST(sort_xfield AS DECIMAL(12,2)) '.$ordering;
+ }
+ $ext_query_fields .= ", SUBSTRING_INDEX(SUBSTRING_INDEX(p.xfields, '{$xfSortName}|', -1 ) , '||', 1 ) as sort_xfield ";
+ break;
+
+ case 'field|'.$fieldSortName: // Сортировка по кастомному полю
+ $orderArr[] = $fieldSortName.' '.$ordering;
+ break;
+
+ }
+
+ // Необходимо учитывать категорию для вывода похожих новостей, если категорию не задал пользователь.
+ // https://github.com/dle-modules/DLE-BlockPro/issues/155
+ if (!$base->cfg['catId'] && $base->cfg['related'] && $base->dle_config['related_only_cats']) {
+ $base->cfg['catId'] = 'this';
+ }
+
+ // Эти переменные потребуются ниже, что бы корректно сформировать имя кеша, когда переданы
+ // &catId=this или notCatId=this
+ $isCatIdThis = false;
+ $isNotCatIdThis = false;
+
+ // Фильтрация КАТЕГОРИЙ по их ID
+ if ($base->cfg['catId'] == 'this' && $category_id) {
+ $isCatIdThis = true;
+ /**
+ * @see https://github.com/dle-modules/DLE-BlockPro/issues/159
+ */
+ $base->cfg['catId'] = $category_id;
+ if ($base->cfg['subcats']) {
+ $base->cfg['catId'] = get_sub_cats($category_id);
+ } elseif ($base->cfg['thisCatOnly']) {
+ $base->cfg['catId'] = (int)$category_id;
+ }
+ }
+ if ($base->cfg['notCatId'] == 'this' && $category_id) {
+ $isNotCatIdThis = true;
+ /**
+ * @see https://github.com/dle-modules/DLE-BlockPro/issues/159
+ */
+ $base->cfg['notCatId'] = $category_id;
+ if ($base->cfg['notSubcats']) {
+ $base->cfg['notCatId'] = get_sub_cats($category_id);
+ } elseif ($base->cfg['thisCatOnly']) {
+ $base->cfg['notCatId'] = (int)$category_id;
+ }
+ }
+ // Дублирование кода вызвано необходимостью сочетания параметра notCatId и catId
+ // Например: catId=this¬CatId=3
+ if ($base->cfg['notCatId']) {
+ $notCatArr = $base->getDiapazone($base->cfg['notCatId'], $base->cfg['notSubcats']);
+ if ($notCatArr[0] > 0) {
+ if ($base->dle_config['allow_multi_category'] && !$base->cfg['thisCatOnly']) {
+ $notCatQPart = 'category regexp "[[:<:]]('.str_replace(',', '|', $notCatArr).')[[:>:]]"';
+ } else {
+ $notCatQPart = 'category IN (\''.str_replace(',', "','", $notCatArr).'\')';
+ }
+
+ $wheres[] = 'NOT '.$notCatQPart;
+ }
+ }
+
+ if ($base->cfg['catId']) {
+ $catArr = $base->getDiapazone($base->cfg['catId'], $base->cfg['subcats']);
+ if ($catArr[0] > 0) {
+ if ($base->dle_config['allow_multi_category'] && !$base->cfg['thisCatOnly']) {
+ $catQPart = 'category regexp "[[:<:]]('.str_replace(',', '|', $catArr).')[[:>:]]"';
+ } else {
+ $catQPart = 'category IN (\''.str_replace(',', "','", $catArr).'\')';
+ }
+
+ $wheres[] = $catQPart;
+ }
+ }
+
+ // Фильтрация НОВОСТЕЙ по их ID
+ if ($base->cfg['postId'] == 'this' && $_REQUEST['newsid']) {
+ $base->cfg['postId'] = $_REQUEST['newsid'];
+ }
+ if ($base->cfg['notPostId'] == 'this' && $_REQUEST['newsid']) {
+ $base->cfg['notPostId'] = $_REQUEST['newsid'];
+ }
+
+ if ($base->cfg['notPostId']) {
+ $notPostsArr = $base->getDiapazone($base->cfg['notPostId']);
+ if ($notPostsArr !== '0') {
+ $wheres[] = 'id NOT IN ('.$notPostsArr.')';
+ }
+ }
+
+ if ($base->cfg['postId'] && $base->cfg['related'] == '') {
+ $postsArr = $base->getDiapazone($base->cfg['postId']);
+ if ($postsArr !== '0') {
+ $wheres[] = 'id IN ('.$postsArr.')';
+ }
+ }
+
+ // Фильтрация новостей по АВТОРАМ
+ if ($base->cfg['author'] == 'this' && isset($_REQUEST['user'])) {
+ $base->cfg['author'] = $_REQUEST['user'];
+ }
+ if ($base->cfg['notAuthor'] == 'this' && isset($_REQUEST['user'])) {
+ $base->cfg['notAuthor'] = $_REQUEST['user'];
+ }
+ if ($base->cfg['author'] || $base->cfg['notAuthor']) {
+ $ignoreAuthors = ($base->cfg['notAuthor']) ? 'NOT ' : '';
+ $authorsArr = ($base->cfg['notAuthor']) ? $base->cfg['notAuthor'] : $base->cfg['author'];
+ if ($authorsArr !== 'this') {
+ // Если в строке подключения &author=this и мы просматриваем страницу юзера, то сюда уже попадёт логин пользователя
+ $authorsArr = explode(',', $authorsArr);
+ $wheres[] = (count($authorsArr) === 1) ? $ignoreAuthors.'autor = '.$base->db->parse('?s', $authorsArr[0])
+ : $ignoreAuthors.'autor regexp "[[:<:]]('.implode('|', $authorsArr).')[[:>:]]"';
+ }
+ }
+
+ // Фильтрация новостей по ДОПОЛНИТЕЛЬНЫМ ПОЛЯМ (проверяется только на заполненность)
+ $_currentXfield = false;
+ if ($base->cfg['xfilter'] == 'this' && isset($_REQUEST['xf'])) {
+ $base->cfg['xfilter'] = $base->db->parse('?s', '%'.$_REQUEST['xf'].'%');
+ $_currentXfield = true;
+ }
+ if ($base->cfg['notXfilter'] == 'this' && isset($_REQUEST['xf'])) {
+ $base->cfg['notXfilter'] = $base->db->parse('?s', '%'.$_REQUEST['xf'].'%');
+ $_currentXfield = true;
+ }
+
+ if ($base->cfg['xfilter'] || $base->cfg['notXfilter']) {
+ $ignoreXfilters = ($base->cfg['notXfilter']) ? 'NOT ' : '';
+ $xfiltersArr = ($base->cfg['notXfilter']) ? $base->cfg['notXfilter'] : $base->cfg['xfilter'];
+
+ if ($xfiltersArr !== 'this') {
+ // Если в строке подключения &xfilter=this и мы просматриваем страницу допполя, то сюда уже попадёт имя этого поля
+ $wheres[] = ($_currentXfield) ? $ignoreXfilters.'xfields LIKE '.$xfiltersArr
+ : $ignoreXfilters.'p.xfields regexp "[[:<:]]('.str_replace(',', '|', $xfiltersArr).')[[:>:]]"';
+ }
+ }
+
+ // Фильтрация по ЗНАЧЕНИЮ ДОПОЛНИТЕЛЬНЫХ ПОЛЕЙ
+ if ($base->cfg['xfSearch'] || $base->cfg['notXfSearch']) {
+
+ // Массив для составления подзапроса
+ $xfWheres = [];
+
+ // Защита логики построения запроса от кривых рук (если прописать неправильно - будет логика OR)
+ $_xfSearchLogic = (strtolower($base->cfg['xfSearchLogic']) == 'and') ? ' AND ' : ' OR ';
+
+ // Определяем масивы с данными по фильтрации
+ $xfSearchArray = ($base->cfg['xfSearch']) ? explode('||', $base->cfg['xfSearch']) : [];
+ $notXfSearchArray = ($base->cfg['notXfSearch']) ? explode('||', $base->cfg['notXfSearch']) : [];
+
+ $bXfNotResult = true;
+ if ($base->dle_config['version_id'] >= '11' && $base->cfg['experiment']) {
+ // Если версия DLE 11 и более и включена экспериментальная функция, то для увеличения скорости выборки запросим данные по допполям из отдельной таблицы.
+
+ // Пробегаем по сформированным массивам
+ foreach ($xfSearchArray as $xf) {
+ $_xf = explode('|', $xf);
+ $xfWheres[] = $base->db->parse('(tagname=?s AND tagvalue=?s)', $_xf[0], $_xf[1]);
+ }
+ foreach ($notXfSearchArray as $xf) {
+ $_xf = explode('|', $xf);
+ $xfWheres[] = $base->db->parse('(tagname=?s AND NOT tagvalue=?s)', $_xf[0], $_xf[1]);
+ }
+ // Подготавливаем запрос.
+ $xfSearchQuery = implode($_xfSearchLogic, $xfWheres);
+
+ // Получаем ID новостей
+ $xfSearchIDs = $base->db->getCol('SELECT news_id FROM ?n WHERE ?p', PREFIX.'_xfsearch', $xfSearchQuery);
+ // Если запрос вернул ID новостей — работаем.
+ if (count($xfSearchIDs)) {
+ // Оставляем только уникальные
+ $xfSearchIDs = array_unique($xfSearchIDs);
+
+ // Добавляем полученные данные в основной массив, формирующий запрос
+ $wheres[] = 'p.id IN ('.implode(',', $xfSearchIDs).')';
+
+ $bXfNotResult = false;
+ } else {
+ // Если ничего не найдено — сбросим массив с условиями т.к. строка подключения возможно содержит дополнительные условия выборки.
+ $xfWheres = [];
+ }
+ }
+
+ if ($bXfNotResult) {
+ // Пробегаем по сформированным массивам
+ // str_replace('|', '|%', $xf) необходимо для случаев, когда значение допполя идёт не первым в списке
+ foreach ($xfSearchArray as $xf) {
+ $xfWheres[] = $base->db->parse('p.xfields LIKE ?s', '%'.str_replace('|', '|%', $xf).'%');
+ }
+ foreach ($notXfSearchArray as $xf) {
+ $xfWheres[] = $base->db->parse('p.xfields NOT LIKE ?s', '%'.str_replace('|', '|%', $xf).'%');
+ }
+
+ // Добавляем полученные данные (и логику) в основной массив, формирующий запрос
+ $wheres[] = '('.implode($_xfSearchLogic, $xfWheres).')';
+ }
+ }
+
+ // Фильтрация новостей по ТЕГАМ
+ $_currentTag = false;
+ if ($base->cfg['tags'] == 'this' && isset($_REQUEST['tag']) && $_REQUEST['tag'] != '') {
+ $base->cfg['tags'] = $base->db->parse('?s', $_REQUEST['tag']);
+ $_currentTag = true;
+ }
+ if ($base->cfg['notTags'] == 'this' && isset($_REQUEST['tag']) && $_REQUEST['tag'] != '') {
+ $base->cfg['notTags'] = $base->db->parse('?s', $_REQUEST['tag']);
+ $_currentTag = true;
+ }
+
+ // Фильтрация новостей по тегам текущей новости, когда в строке подключения прописано &tags=thisNewsTags и мы просматриваем полную новость
+ if ((int)$_REQUEST['newsid'] > 0) {
+ if ($base->cfg['tags'] == 'thisNewsTags' || $base->cfg['notTags'] == 'thisNewsTags') {
+ $curTagNewsId = $base->db->getRow('SELECT tags FROM ?n WHERE id=?i', PREFIX.'_post', $_REQUEST['newsid']);
+ if (!empty($curTagNewsId['tags'])) {
+ if ($base->cfg['tags'] == 'thisNewsTags') {
+ // Заменяем запятую и пробел на просто запятую, иначе будет ошибка.
+ $base->cfg['tags'] = str_replace(', ', ',', $curTagNewsId['tags']);
+ }
+ if ($base->cfg['notTags'] == 'thisNewsTags') {
+ // Заменяем запятую и пробел на просто запятую, иначе будет ошибка.
+ $base->cfg['notTags'] = str_replace(', ', ',', $curTagNewsId['notTags']);
+ }
+ }
+ }
+ }
+
+ if ($base->cfg['tags'] || $base->cfg['notTags']) {
+ $ignoreTags = ($base->cfg['notTags']) ? 'NOT ' : '';
+ $tagsArr = ($base->cfg['notTags']) ? $base->cfg['notTags'] : $base->cfg['tags'];
+
+
+ if ($tagsArr !== 'this') {
+ // Если в строке подключения &tags=this и мы просматриваем страницу тегов, то сюда уже попадёт название тега
+ $wherTag = ($_currentTag) ? $ignoreTags.'tag = '.$tagsArr
+ : $ignoreTags.'tag regexp "[[:<:]]('.str_replace(',', '|', $tagsArr).')[[:>:]]"';
+ // Делаем запрос на получение ID новостей, содержащих требуемые теги
+ $tagNews = $base->db->getCol('SELECT news_id FROM ?n WHERE ?p', PREFIX.'_tags', $wherTag);
+ $tagNews = array_unique($tagNews);
+
+ if (count($tagNews)) {
+ $wheres[] = 'id '.$ignoreTags.' IN ('.implode(',', $tagNews).')';
+ } else {
+ // Fix #160
+ $wheres[] = 'id = 0';
+ }
+
+ }
+ }
+
+ // Фильтрация новостей по символьным кодам
+ $_currentSymbol = false;
+ if ($base->cfg['symbols'] == 'this' && isset($_REQUEST['catalog'])) {
+ $base->cfg['symbols'] = $base->db->parse('?s', $_REQUEST['catalog']);
+ $_currentSymbol = true;
+ }
+ if ($base->cfg['notSymbols'] == 'this' && isset($_REQUEST['catalog'])) {
+ $base->cfg['notSymbols'] = $base->db->parse('?s', $_REQUEST['catalog']);
+ $_currentSymbol = true;
+ }
+
+ if ($base->cfg['symbols'] || $base->cfg['notSymbols']) {
+ $ignoreSymbols = ($base->cfg['notSymbols']) ? 'NOT ' : '';
+ $symbolsArr = ($base->cfg['notSymbols']) ? $base->cfg['notSymbols'] : $base->cfg['symbols'];
+ if ($symbolsArr !== 'this') {
+ // Если в строке подключения &symbols=this и мы просматриваем страницу буквенного каталога, то сюда уже попадёт название буквы
+ $wheres[] = ($_currentSymbol) ? $ignoreSymbols.'symbol = '.$symbolsArr
+ : $ignoreSymbols.'symbol regexp "[[:<:]]('.str_replace(',', '|', $symbolsArr).')[[:>:]]"';
+ }
+ }
+
+ // Если включен режим вывода похожих новостей:
+ $reltedFirstShow = false;
+ if ($base->cfg['related']) {
+ if ($base->cfg['related'] == 'this' && $_REQUEST['newsid'] == '') {
+ $outputLog['errors'][]
+ = 'Переменная related=this работает только в полной новости и не работает с ЧПУ 3 типа.';
+ } else {
+
+ $relatedId = ($base->cfg['related'] == 'this') ? $_REQUEST['newsid'] : $base->cfg['related'];
+ $relatedRows = 'p.title, p.short_story, p.full_story, p.xfields';
+ $relatedIdParsed = $base->db->parse('id = ?i', $relatedId);
+
+ $relatedBody = $base->db->getRow('SELECT id, ?p FROM ?n p LEFT JOIN ?n e ON (p.id=e.news_id) WHERE ?p',
+ 'p.title, p.short_story, p.full_story, p.xfields, e.related_ids', PREFIX.'_post', PREFIX.'_post_extras',
+ $relatedIdParsed);
+ // Фикс https://github.com/dle-modules/DLE-BlockPro/issues/78
+ if ($relatedBody['id']) {
+ /** @var bool $saveRelated */
+ if ($relatedBody['related_ids'] && $saveRelated) {
+ // Если есть запись id похожих новостей — добавим в условие запроса эти новости.
+ $wheres[] = 'id IN('.$relatedBody['related_ids'].')';
+ // Отсортируем новости в том порядке, в котором они записаны в БД
+ $orderArr = ['FIELD (p.id, '.$relatedBody['related_ids'].')'];
+ } else {
+ // Если похожие новости не записывались — отберём их.
+ $reltedFirstShow = true;
+ $bodyToRelated = (dle_strlen($relatedBody['full_story'], $base->dle_config['charset'])
+ < dle_strlen($relatedBody['short_story'], $base->dle_config['charset']))
+ ? $relatedBody['short_story'] : $relatedBody['full_story'];
+
+ $bodyToRelated = strip_tags(stripslashes($relatedBody['title'].' '.$bodyToRelated));
+
+ // Фикс для https://github.com/pafnuty/BlockPro/issues/79
+ // @see /engine/modules/show.full.php
+ if (dle_strlen($bodyToRelated, $base->dle_config['charset']) > 1000) {
+ $bodyToRelated = dle_substr($bodyToRelated, 0, 1000, $base->dle_config['charset']);
+ }
+
+ $bodyToRelated = $base->db->parse('?s', $bodyToRelated);
+
+ // Добавляем улучшенный алгоритм поиска похожих новостей из DLE 13
+ $ext_query_fields .= ', MATCH (p.title, p.short_story, p.full_story, p.xfields) AGAINST ('
+ .$bodyToRelated.') as score';
+ $orderArr = ['score DESC'];
+
+ // Формируем условие выборки
+ $wheres[] = 'MATCH ('.$relatedRows.') AGAINST ('.$bodyToRelated.') AND id !='.$relatedBody['id'];
+ }
+ } else {
+ $outputLog['errors'][] = 'Новость с ID '.$relatedIdParsed.' не найдена в базе данных.';
+ }
+ }
+
+
+ }
+
+ // Определяем переменные, чтоб сто раз не писать одно и тоже
+ $bDay = (int)$base->cfg['day'];
+ $bDayCount = (int)$base->cfg['dayCount'];
+
+ // Если в bDay и bDayCount передано '-1', значит требуется вывести новости только за сегодня.
+ // Это обработка случая, когда включен вывод новостей на ненаступившую дату и надо вывести за сегодня
+ // https://pafnuty.omnidesk.ru/staff/cases/record/181-466935/
+ if ($bDay === -1 && $bDayCount === -1) {
+ // Формируем вывод новостей только за сегодня
+ $wheres[] = 'p.date >= "'.$today.'" - INTERVAL 1 DAY';
+ $wheres[] = 'p.date < "'.$today.'"';
+ } else {
+ // Если future задан, то интервал не вычитаем, а прибавляем к текущему началу дня
+ $intervalOperator = ($base->cfg['future']) ? ' + ' : ' - ';
+
+ // Если режим афиши включен - выводим новости, дата которых ещё не наступила.
+ if ($base->cfg['future'] && (!$bDay && !$bDayCount)) {
+ $wheres[] = 'p.date > "'.$rightNow.'"';
+ }
+
+ // Если включен вывод новостей на ненаступившую дату в настройках DLE
+ // и режим афиши не используется, то нельзя выводить новости дата которых не наступила до текущей секунды
+ if (!$base->cfg['future'] && ($base->dle_config['news_future'] && $base->dle_config['news_future'] !== 'no')) {
+ $wheres[] = 'p.date <= "'.$rightNow.'"';
+ }
+
+ // Разбираемся с временными рамками отбора новостей, если кол-во дней указано - ограничиваем выборку, если нет - выводим без ограничения даты
+ if ($bDay) {
+ $wheres[] = 'p.date >= "'.$today.'" '.$intervalOperator.' INTERVAL '.(($base->cfg['future']) ? ($bDay
+ - $bDayCount) : $bDay).' DAY';
+ }
+ // Если задана переменная dayCount и day, а так же day больше dayCount - отбираем новости за указанный интервал от указанного периода
+ if ($bDay && $bDayCount && ($bDayCount <= $bDay)) {
+ $wheres[] = 'p.date < "'.$today.'" '.$intervalOperator.' INTERVAL '.(($base->cfg['future']) ? $bDay
+ : ($bDay - $bDayCount)).' DAY';
+ } else {
+ // Условие для отображения только тех постов, дата публикации которых уже наступила
+ $wheres[] = ($base->dle_config['no_date'] && !$base->dle_config['news_future'] && !$base->cfg['future'])
+ ? 'p.date < "'.$rightNow.'"' : '';
+ }
+
+ }
+
+ // Подчистим массив от пустых значений
+ $wheres = array_filter($wheres);
+
+ // Когда выбран вариант вывода случайных новостей (Лёгкий режим)
+ if ($base->cfg['sort'] == 'randomLight') {
+
+ // Складываем условия выборки для рандомных новостей
+ $randWhere = (count($wheres)) ? ' WHERE '.implode(' AND ', $wheres) : '';
+ // Получим массив с id новостей
+ $randDiapazone = $base->db->getCol('SELECT id FROM ?n AS p ?p', PREFIX.'_post', $randWhere);
+ // Перемешаем
+ shuffle($randDiapazone);
+ // Возьмём только нужное количество элементов
+ $randIds = array_slice($randDiapazone, 0, $base->cfg['limit']);
// Удалим из памяти ненужное
unset($randDiapazone);
unset($randWhere);
- // Если вдруг не получится набрать элементы в принципе
- if (count($randIds)) {
- $randIds = implode(',', $randIds);
- // Сбрасываем ненужные условия выборки
- $wheres = [];
- // Задаём условие выборки по предварительно полученным ID
- $wheres[] = 'id IN (' . $randIds . ')';
- // И выводим в том порядке, в ктором сформировались ID
- $orderArr = ['FIELD (p.id, ' . $randIds . ')'];
- }
-
- }
- // Складываем условия
- $where = (count($wheres)) ? ' WHERE ' . implode(' AND ', $wheres) : '';
-
- // Если нужен вывод аватарок - добавляем дополнительные условия в запрос
- if ($base->cfg['avatar']) {
- $ext_query_fields .= ', u.name, u.user_group, u.foto ';
- $ext_query .= $base->db->parse(' LEFT JOIN ?n u ON (p.autor=u.name) ', USERPREFIX . '_users');
- }
-
- // Если выбрана сортировка по кол-ву скачиваний прикрепленных файлов
- if ($base->cfg['sort'] == 'download') {
- $ext_query_fields .= ', d.news_id, sum(d.dcount) as dcount ';
- $ext_query .= $base->db->parse(' LEFT JOIN ?n d ON (p.id=d.news_id) ', PREFIX . '_files');
-
- // Группируем новости по ID т.к. иначе появятся дубликаты при нескольких атачметах в новости.
- $groupBy = ' GROUP BY p.id ';
- }
-
- if ($base->cfg['fields']) {
- $customFields = ', ' . trim($base->cfg['fields']);
- } else {
- $customFields = '';
- }
-
- // Поля, выбираемые из БД
- $selectRows = 'p.id, p.autor, p.date, p.short_story, p.full_story, p.xfields, p.title, p.category, p.alt_name, p.allow_comm, p.comm_num, p.fixed, p.allow_main, p.symbol, p.tags, e.news_read, e.allow_rate, e.rating, e.vote_num, e.votes, e.related_ids, e.view_edit, e.editdate, e.editor, e.reason' . $customFields . $ext_query_fields;
-
- /** @var array $postsArr */
- if ($base->cfg['order'] == 'asis' && $base->cfg['postId'] && $postsArr) {
- $orderArr = ['FIELD (p.id, ' . $postsArr . ')'];
- }
- // Определяем необходимость и данные для сортировки
- $orderBy = (count($orderArr)) ? 'ORDER BY ' . implode(', ', $orderArr) : '';
-
- // Запрос в БД (данные фильтруются в классе для работы с БД, так что можно не переживать), главное правильно сконструировать запрос.
- $query = 'SELECT ?p FROM ?n p LEFT JOIN ?n e ON (p.id=e.news_id) ?p ' . $groupBy . ' ' . $orderBy . ' LIMIT ?i, ?i';
-
- // Определяем с какой страницы начинать вывод (при постраничке, или если указано в строке).
- $_startFrom = ($base->cfg['pageNum'] >= 1) ? ($base->cfg['limit'] * $base->cfg['pageNum'] - $base->cfg['limit'] + $base->cfg['startFrom']) : 0;
-
- // Получаем новости
- $list = $base->db->getAll($query, $selectRows, PREFIX . '_post', PREFIX . '_post_extras', $ext_query . $where, $_startFrom, $base->cfg['limit']);
-
- // Обрабатываем данные функцией stripslashes рекурсивно.
- $list = stripSlashesInArray($list);
-
- // Путь к папке с текущим шаблоном
- $tplArr['theme'] = $base->dle_config['http_home_url'] . 'templates/' . $base->dle_config['skin'];
-
- // Делаем доступным конфиг DLE внутри шаблона
- $tplArr['dleConfig'] = $base->dle_config;
-
- // Делаем доступной переменную $dle_module в шаблоне
- $tplArr['dleModule'] = $dle_module;
-
- // Делаем доступной переменную $lang в шаблоне
- $tplArr['lang'] = $lang;
- $tplArr['cacheName'] = $cacheName;
- $tplArr['category_id'] = $category_id;
- $tplArr['cfg'] = $cfg;
- // Массив для аттачей и похожих новостей.
- $attachments = $relatedIds = [];
-
- // Обрабатываем данные в массиве.
- foreach ($list as $key => &$newsItem) {
- // Плучаем обработанные допполя.
- $newsItem['xfields'] = stripSlashesInArray(xfieldsdataload($newsItem['xfields']));
- // Собираем массив вложений
- $attachments[] = $relatedIds[] = $newsItem['id'];
-
- // Массив данных для формирования ЧПУ
- $urlArr = [
- 'category' => $newsItem['category'],
- 'id' => $newsItem['id'],
- 'alt_name' => $newsItem['alt_name'],
- 'date' => $newsItem['date'],
- ];
- // Записываем сформированный URL статьи в массив
- $newsItem['url'] = $base->getPostUrl($urlArr);
-
- // Добавляем тег edit
- if ($is_logged and (($member_id['name'] == $newsItem['autor'] and $user_group[$member_id['user_group']]['allow_edit']) or $user_group[$member_id['user_group']]['allow_all_edit'])) {
- $_SESSION['referrer'] = $_SERVER['REQUEST_URI'];
- $newsItem['allow_edit'] = true;
- $newsItem['editOnclick'] = 'onclick="return dropdownmenu(this, event, MenuNewsBuild(\'' . $newsItem['id'] . '\', \'short\'), \'170px\')"';
-
- } else {
- $newsItem['allow_edit'] = false;
- $newsItem['editOnclick'] = '';
- }
-
- // Записываем сформированные теги в массив
- $newsItem['tags'] = $base->tagsLink($newsItem['tags']);
-
- // Записываем в массив ссылку на аватар
- $newsItem['avatar'] = $tplArr['theme'] . '/dleimages/noavatar.png';
- // А если у юзера есть фотка - выводим её, или граватар.
- if ($newsItem['foto']) {
- $userFoto = $newsItem['foto'];
- if (count(explode('@', $userFoto)) == 2) {
- $newsItem['avatar'] = '//www.gravatar.com/avatar/' . md5(trim($userFoto)) . '?s=' . intval($user_group[$newsItem['user_group']]['max_foto']);
- } else {
- $userFotoWHost = (strpos($userFoto, '//') === 0) ? 'http:' . $userFoto : $userFoto;
- $arUserFoto = parse_url($userFotoWHost);
- if ($arUserFoto['host']) {
- $newsItem['avatar'] = $userFoto;
- } else {
- $newsItem['avatar'] = $base->dle_config['http_home_url'] . 'uploads/fotos/' . $userFoto;
- }
- unset($arUserFoto, $userFotoWHost);
- }
- }
-
- // Разбираемся с рейтингом
- $newsItem['showRating'] = '';
- $newsItem['showRatingCount'] = '';
- if ($newsItem['allow_rate']) {
- $newsItem['showRatingCount'] = '' . $newsItem['vote_num'] . '';
- $jsRAteFunctionName = ($base->dle_config['version_id'] >= 13) ? 'base_rate13' : 'base_rate';
-
- if ($base->dle_config['short_rating'] and $user_group[$member_id['user_group']]['allow_rating']) {
- $newsItem['showRating'] = baseShowRating($newsItem['id'], $newsItem['rating'], $newsItem['vote_num'], 1);
-
- $newsItem['ratingOnclickPlus'] = 'onclick="' . $jsRAteFunctionName .'(\'plus\', \'' . $newsItem['id'] . '\'); return false;"';
- $newsItem['ratingOnclickMinus'] = 'onclick="' . $jsRAteFunctionName .'(\'minus\', \'' . $newsItem['id'] . '\'); return false;"';
-
- } else {
- $newsItem['showRating'] = baseShowRating($newsItem['id'], $newsItem['rating'], $newsItem['vote_num'], 0);
-
- $newsItem['ratingOnclickPlus'] = '';
- $newsItem['ratingOnclickMinus'] = '';
- }
- }
- // Разбираемся с избранным
- $newsItem['favorites'] = '';
- if ($is_logged) {
- $fav_arr = explode(',', $member_id['favorites']);
-
- if (!in_array($newsItem['id'], $fav_arr) || $base->dle_config['allow_cache']) {
- $newsItem['favorites'] = '';
- } else {
- $newsItem['favorites'] = '';
- }
- }
- }
-
- // Полученный массив с данными для обработки в шаблоне
- $tplArr['list'] = $list;
-
- // Определяем группу пользователя
- $tplArr['member_group_id'] = $member_id['user_group'];
-
- // Устанавливаем пустое значение для постранички по умолчанию.
- $tplArr['pages'] = '';
- // Общее кол-во новостей без постранички.
- $tplArr['totalCount'] = count($list);
-
- if ($base->cfg['showNav']) {
- // Получаем общее количество новостей по заданным параметрам отбора
- $totalCount = $base->db->getOne('SELECT COUNT(*) as count FROM ?n as p LEFT JOIN ?n e ON (p.id=e.news_id) ?p', PREFIX . '_post', PREFIX . '_post_extras', $where);
- // Вычитаем переменную startFrom для корректного значения кол-ва новостей
- $totalCount = $totalCount - $base->cfg['startFrom'];
-
- // Общее кол-во новостей с постраничкой.
- $tplArr['totalCount'] = $totalCount;
-
- // Меняем для кеша id категории на this если параметр catId или notCatId равен this
- if ($isCatIdThis) {
- $base->cfg['catId'] = 'this';
- }
- if ($isNotCatIdThis) {
- $base->cfg['notCatId'] = 'this';
- }
-
- // Формируем имя кеш-файла с конфигом
- $pageCacheName = $base->cfg;
- // Удаляем номер страницы для того, что бы не создавался новый кеш для каждого блока постранички
- unset($pageCacheName['pageNum']);
-
- // Сокращаем немного имя файла :)
- $pageCacheName = 'bpa_' . crc32(implode('_', $pageCacheName));
-
- // Включаем кеширование DLE принудительно
- $cache_tmp = $base->dle_config['allow_cache'];
- $config['allow_cache'] = 'yes'; // 'yes' для совместимости со старыми версиями dle, т.к. там проверяется значение, а не наличие значения переменной.
-
- // Проверяем есть ли кеш с указанным именем
- $ajaxCache = dle_cache($pageCacheName);
- // Если кеша нет
- if (!$ajaxCache) {
- // Сериализуем конфиг для последующей записи в кеш
- $pageCacheText = serialize($base->cfg);
- // Создаём кеш
- create_cache($pageCacheName, $pageCacheText);
- }
-
- // Возвращаем значение кеша DLE обратно
- $config['allow_cache'] = $cache_tmp;
-
- // Массив с конфигурацией для формирования постранички
- $pagerConfig = [
- 'block_id' => $pageCacheName,
- 'total_items' => $totalCount,
- 'items_per_page' => $base->cfg['limit'],
- 'style' => $base->cfg['navStyle'],
- 'current_page' => $base->cfg['pageNum'],
- ];
- if ($base->cfg['navDefaultGet']) {
- $pagerConfig['is_default_dle_get'] = true;
- $pagerConfig['query_string'] = 'cstart';
- $pagerConfig['link_tag'] = ':name';
- $pagerConfig['current_tag'] = ':name';
- $pagerConfig['prev_tag'] = '‹ Назад';
- $pagerConfig['prev_text_tag'] = '‹ Назад';
- $pagerConfig['next_tag'] = 'Далее ›';
- $pagerConfig['next_text_tag'] = 'Далее ›';
- $pagerConfig['first_tag'] = 'Первая «';
- $pagerConfig['last_tag'] = '» Последняя';
- $pagerConfig['extended_pageof'] = 'Страница :current_page из :total_pages';
- $pagerConfig['extended_itemsof'] = 'Показаны новости :current_first_item — :current_last_item из :total_items';
- }
- // Если более 1 страницы
- if ($totalCount > $base->cfg['limit']) {
- $pagination = new Pager($pagerConfig);
-
- // Сформированный блок с постраничкой
- $tplArr['pages'] = $pagination->render();
- // Уникальный ID для вывода в шаблон
- }
- $tplArr['block_id'] = $pagerConfig['block_id'];
-
- } else {
- // Устанавливаем уникальный ID для блока по умолчанию
- $tplArr['block_id'] = 'bp_' . crc32(implode('_', $base->cfg));
- }
-
- // Результат обработки шаблона
- try {
- $output = $base->tpl->fetch($base->cfg['template'] . '.tpl', $tplArr);
- } catch (Exception $e) {
- $outputLog['errors'][] = $e->getMessage();
- $base->cfg['nocache'] = true;
- }
-
- // Записываем в БД id похожих новостей, если требуется
- if ($reltedFirstShow && $saveRelated) {
- /** @var integer $relatedId */
- $base->db->query('UPDATE ?n SET related_ids=?s WHERE news_id=?i', PREFIX . '_post_extras', implode(',', $relatedIds), $relatedId);
- }
-
- // Если есть ошбки и включен вывод статистики — оключаем кеш.
- if (count($outputLog['errors']) > 0 && $cfg['showstat']) {
- $base->cfg['nocache'] = true;
- }
-
- // Формируем данные о запросах для статистики, если требуется
- if ($base->cfg['showstat'] && $user_group[$member_id['user_group']]['allow_all_edit']) {
- $stat = $base->db->getStats();
- $statQ = [];
-
- foreach ($stat as $i => $q) {
- $statQ['q'] .= ' ' . '[' . ($i + 1) . '] ' . $q['query'] . ' [' . ($i + 1) . ' время:] ' . $q['timer'] . '';
- $statQ['t'] += $q['timer'];
- }
- $dbStat = 'Запрос(ы): ' . $statQ['q'] . ' Время выполнения запросов: ' . $statQ['t'] . ' ';
-
- unset($stat);
- }
-
- // Создаём кеш, если требуется
- if (!$base->cfg['nocache']) {
- create_cache($base->cfg['cachePrefix'], $output, $cacheName, $cacheSuffix);
- }
+ // Если вдруг не получится набрать элементы в принципе
+ if (count($randIds)) {
+ $randIds = implode(',', $randIds);
+ // Сбрасываем ненужные условия выборки
+ $wheres = [];
+ // Задаём условие выборки по предварительно полученным ID
+ $wheres[] = 'id IN ('.$randIds.')';
+ // И выводим в том порядке, в ктором сформировались ID
+ $orderArr = ['FIELD (p.id, '.$randIds.')'];
+ }
+
+ }
+
+ // Добавлем условия выборки для новостей на другом языке при включении поддержки MultiLanguage
+ if ($multiLangEnabled) {
+ if ($lang_config['hide_news_on']) {
+ foreach ($multiLngEnabledFields as $enabledField) {
+ $wheres[] = $multiLangAdditionalFields[$enabledField].' <> \'\'';
+ }
+ }
+ }
+
+ // Складываем условия
+ $where = (count($wheres)) ? ' WHERE '.implode(' AND ', $wheres) : '';
+
+ // Если нужен вывод аватарок - добавляем дополнительные условия в запрос
+ if ($base->cfg['avatar']) {
+ $ext_query_fields .= ', u.name, u.user_group, u.foto ';
+ $ext_query .= $base->db->parse(' LEFT JOIN ?n u ON (p.autor=u.name) ', USERPREFIX.'_users');
+ }
+
+ // Если выбрана сортировка по кол-ву скачиваний прикрепленных файлов
+ if ($base->cfg['sort'] == 'download') {
+ $ext_query_fields .= ', d.news_id, sum(d.dcount) as dcount ';
+ $ext_query .= $base->db->parse(' LEFT JOIN ?n d ON (p.id=d.news_id) ', PREFIX.'_files');
+
+ // Группируем новости по ID т.к. иначе появятся дубликаты при нескольких атачметах в новости.
+ $groupBy = ' GROUP BY p.id ';
+ }
+
+ $customFields = '';
+ if ($base->cfg['fields']) {
+ $customFields = ', '.trim($base->cfg['fields']);
+ }
+
+ // Добавляем дополнительные поля в запрос при включении поддержки MultiLanguage
+ if ($multiLangEnabled) {
+ $customFields = ', '.implode(', ', $multiLangAdditionalFields);
+ }
+
+ // Поля, выбираемые из БД
+ $selectRows
+ = 'p.id, p.autor, p.date, p.short_story, p.full_story, p.xfields, p.title, p.category, p.alt_name, p.allow_comm, p.comm_num, p.fixed, p.allow_main, p.symbol, p.tags, e.news_read, e.allow_rate, e.rating, e.vote_num, e.votes, e.related_ids, e.view_edit, e.editdate, e.editor, e.reason'
+ .$customFields.$ext_query_fields;
+
+ /** @var array $postsArr */
+ if ($base->cfg['order'] == 'asis' && $base->cfg['postId'] && $postsArr) {
+ $orderArr = ['FIELD (p.id, '.$postsArr.')'];
+ }
+ // Определяем необходимость и данные для сортировки
+ $orderBy = (count($orderArr)) ? 'ORDER BY '.implode(', ', $orderArr) : '';
+
+ // Запрос в БД (данные фильтруются в классе для работы с БД, так что можно не переживать), главное правильно сконструировать запрос.
+ $query = 'SELECT ?p FROM ?n p LEFT JOIN ?n e ON (p.id=e.news_id) ?p '.$groupBy.' '.$orderBy.' LIMIT ?i, ?i';
+
+ // Определяем с какой страницы начинать вывод (при постраничке, или если указано в строке).
+ $_startFrom = ($base->cfg['pageNum'] >= 1) ? ($base->cfg['limit'] * $base->cfg['pageNum'] - $base->cfg['limit']
+ + $base->cfg['startFrom']) : 0;
+
+ // Получаем новости
+ $list = $base->db->getAll($query, $selectRows, PREFIX.'_post', PREFIX.'_post_extras', $ext_query.$where,
+ $_startFrom, $base->cfg['limit']);
+
+ // Обрабатываем данные функцией stripslashes рекурсивно.
+ $list = stripSlashesInArray($list);
+
+ // Путь к папке с текущим шаблоном
+ $tplArr['theme'] = $base->dle_config['http_home_url'].'templates/'.$base->dle_config['skin'];
+
+ // Делаем доступным конфиг DLE внутри шаблона
+ $tplArr['dleConfig'] = $base->dle_config;
+
+ // Делаем доступной переменную $dle_module в шаблоне
+ $tplArr['dleModule'] = $dle_module;
+
+ // Делаем доступной переменную $lang в шаблоне
+ $tplArr['lang'] = $lang;
+ $tplArr['cacheName'] = $cacheName;
+ $tplArr['category_id'] = $category_id;
+ $tplArr['cfg'] = $cfg;
+ $tplArr['langVariant'] = $langVariant;
+ // Массив для аттачей и похожих новостей.
+ $attachments = $relatedIds = [];
+
+ // Обрабатываем данные в массиве.
+ foreach ($list as $key => &$newsItem) {
+ // Плучаем обработанные допполя.
+ $newsItem['xfields'] = stripSlashesInArray(xfieldsdataload($newsItem['xfields']));
+ // Собираем массив вложений
+ $attachments[] = $relatedIds[] = $newsItem['id'];
+
+ // Массив данных для формирования ЧПУ
+ $urlArr = [
+ 'category' => $newsItem['category'],
+ 'id' => $newsItem['id'],
+ 'alt_name' => $newsItem['alt_name'],
+ 'date' => $newsItem['date'],
+ ];
+ // Записываем сформированный URL статьи в массив
+ $newsItem['url'] = $base->getPostUrl($urlArr, $langVariant);
+
+ // Присваиваем полям необходимые значения в зависимости от языка
+ if ($multiLangEnabled) {
+ foreach ($multiLngEnabledFields as $enabledField) {
+ $newsItem[$multiLangNewsFields[$enabledField][0]] = $newsItem[$multiLangNewsFields[$enabledField][1]];
+ }
+ }
+
+ // Добавляем тег edit
+ if ($is_logged and (($member_id['name'] == $newsItem['autor']
+ and $user_group[$member_id['user_group']]['allow_edit'])
+ or $user_group[$member_id['user_group']]['allow_all_edit'])
+ ) {
+ $_SESSION['referrer'] = $_SERVER['REQUEST_URI'];
+ $newsItem['allow_edit'] = true;
+ $newsItem['editOnclick'] = 'onclick="return dropdownmenu(this, event, MenuNewsBuild(\''.$newsItem['id']
+ .'\', \'short\'), \'170px\')"';
+
+ } else {
+ $newsItem['allow_edit'] = false;
+ $newsItem['editOnclick'] = '';
+ }
+
+ // Записываем сформированные теги в массив
+ $newsItem['tags'] = $base->tagsLink($newsItem['tags']);
+
+ // Записываем в массив ссылку на аватар
+ $newsItem['avatar'] = $tplArr['theme'].'/dleimages/noavatar.png';
+ // А если у юзера есть фотка - выводим её, или граватар.
+ if ($newsItem['foto']) {
+ $userFoto = $newsItem['foto'];
+ if (count(explode('@', $userFoto)) == 2) {
+ $newsItem['avatar'] = '//www.gravatar.com/avatar/'.md5(trim($userFoto)).'?s='
+ .intval($user_group[$newsItem['user_group']]['max_foto']);
+ } else {
+ $userFotoWHost = (strpos($userFoto, '//') === 0) ? 'http:'.$userFoto : $userFoto;
+ $arUserFoto = parse_url($userFotoWHost);
+ if ($arUserFoto['host']) {
+ $newsItem['avatar'] = $userFoto;
+ } else {
+ $newsItem['avatar'] = $base->dle_config['http_home_url'].'uploads/fotos/'.$userFoto;
+ }
+ unset($arUserFoto, $userFotoWHost);
+ }
+ }
+
+ // Разбираемся с рейтингом
+ $newsItem['showRating'] = '';
+ $newsItem['showRatingCount'] = '';
+ if ($newsItem['allow_rate']) {
+ $newsItem['showRatingCount'] = ''
+ .$newsItem['vote_num'].'';
+ $jsRAteFunctionName = 'base_rate';
+
+ if ($base->dle_config['short_rating'] and $user_group[$member_id['user_group']]['allow_rating']) {
+ $newsItem['showRating'] = baseShowRating($newsItem['id'], $newsItem['rating'], $newsItem['vote_num'],
+ 1);
+
+ $newsItem['ratingOnclickPlus'] = 'onclick="'.$jsRAteFunctionName.'(\'plus\', \''.$newsItem['id']
+ .'\'); return false;"';
+ $newsItem['ratingOnclickMinus'] = 'onclick="'.$jsRAteFunctionName.'(\'minus\', \''.$newsItem['id']
+ .'\'); return false;"';
+
+ } else {
+ $newsItem['showRating'] = baseShowRating($newsItem['id'], $newsItem['rating'], $newsItem['vote_num'],
+ 0);
+
+ $newsItem['ratingOnclickPlus'] = '';
+ $newsItem['ratingOnclickMinus'] = '';
+ }
+ }
+ // Разбираемся с избранным
+ $newsItem['favorites'] = '';
+ if ($is_logged) {
+ $fav_arr = explode(',', $member_id['favorites']);
+
+ if (!in_array($newsItem['id'], $fav_arr) || $base->dle_config['allow_cache']) {
+ $newsItem['favorites'] = '';
+ } else {
+ $newsItem['favorites'] = '';
+ }
+ }
+ }
+
+ // Полученный массив с данными для обработки в шаблоне
+ $tplArr['list'] = $list;
+
+ // Определяем группу пользователя
+ $tplArr['member_group_id'] = $member_id['user_group'];
+
+ // Устанавливаем пустое значение для постранички по умолчанию.
+ $tplArr['pages'] = '';
+ // Общее кол-во новостей без постранички.
+ $tplArr['totalCount'] = count($list);
+
+ if ($base->cfg['showNav']) {
+ // Получаем общее количество новостей по заданным параметрам отбора
+ $totalCount = $base->db->getOne('SELECT COUNT(*) as count FROM ?n as p LEFT JOIN ?n e ON (p.id=e.news_id) ?p',
+ PREFIX.'_post', PREFIX.'_post_extras', $where);
+ // Вычитаем переменную startFrom для корректного значения кол-ва новостей
+ $totalCount = $totalCount - $base->cfg['startFrom'];
+
+ // Общее кол-во новостей с постраничкой.
+ $tplArr['totalCount'] = $totalCount;
+
+ // Меняем для кеша id категории на this если параметр catId или notCatId равен this
+ if ($isCatIdThis) {
+ $base->cfg['catId'] = 'this';
+ }
+ if ($isNotCatIdThis) {
+ $base->cfg['notCatId'] = 'this';
+ }
+
+ // Формируем имя кеш-файла с конфигом
+ $pageCacheName = $base->cfg;
+ // Удаляем номер страницы для того, что бы не создавался новый кеш для каждого блока постранички
+ unset($pageCacheName['pageNum']);
+
+ // Сокращаем немного имя файла :)
+ $pageCacheName = 'bpa_'.crc32(implode('_', $pageCacheName));
+
+ // Включаем кеширование DLE принудительно
+ $cache_tmp = $base->dle_config['allow_cache'];
+ $config['allow_cache']
+ = 'yes'; // 'yes' для совместимости со старыми версиями dle, т.к. там проверяется значение, а не наличие значения переменной.
+
+ // Проверяем есть ли кеш с указанным именем
+ $ajaxCache = dle_cache($pageCacheName);
+ // Если кеша нет
+ if (!$ajaxCache) {
+ // Сериализуем конфиг для последующей записи в кеш
+ $pageCacheText = serialize($base->cfg);
+ // Создаём кеш
+ create_cache($pageCacheName, $pageCacheText);
+ }
+
+ // Возвращаем значение кеша DLE обратно
+ $config['allow_cache'] = $cache_tmp;
+
+ // Массив с конфигурацией для формирования постранички
+ $pagerConfig = [
+ 'block_id' => $pageCacheName,
+ 'total_items' => $totalCount,
+ 'items_per_page' => $base->cfg['limit'],
+ 'style' => $base->cfg['navStyle'],
+ 'current_page' => $base->cfg['pageNum'],
+ ];
+ if ($base->cfg['navDefaultGet']) {
+ $pagerConfig['is_default_dle_get'] = true;
+ $pagerConfig['query_string'] = 'cstart';
+ $pagerConfig['link_tag'] = ':name';
+ $pagerConfig['current_tag'] = ':name';
+ $pagerConfig['prev_tag'] = '‹ Назад';
+ $pagerConfig['prev_text_tag'] = '‹ Назад';
+ $pagerConfig['next_tag'] = 'Далее ›';
+ $pagerConfig['next_text_tag'] = 'Далее ›';
+ $pagerConfig['first_tag'] = 'Первая «';
+ $pagerConfig['last_tag'] = '» Последняя';
+ $pagerConfig['extended_pageof'] = 'Страница :current_page из :total_pages';
+ $pagerConfig['extended_itemsof']
+ = 'Показаны новости :current_first_item — :current_last_item из :total_items';
+ }
+ // Если более 1 страницы
+ if ($totalCount > $base->cfg['limit']) {
+ $pagination = new Pager($pagerConfig);
+
+ // Сформированный блок с постраничкой
+ $tplArr['pages'] = $pagination->render();
+ // Уникальный ID для вывода в шаблон
+ }
+ $tplArr['block_id'] = $pagerConfig['block_id'];
+
+ } else {
+ // Устанавливаем уникальный ID для блока по умолчанию
+ $tplArr['block_id'] = 'bp_'.crc32(implode('_', $base->cfg));
+ }
+
+ // Результат обработки шаблона
+ try {
+ $output = $base->tpl->fetch($base->cfg['template'].'.tpl', $tplArr);
+ } catch (Exception $e) {
+ $outputLog['errors'][] = $e->getMessage();
+ $base->cfg['nocache'] = true;
+ }
+
+ // Записываем в БД id похожих новостей, если требуется
+ if ($reltedFirstShow && $saveRelated) {
+ /** @var integer $relatedId */
+ $base->db->query('UPDATE ?n SET related_ids=?s WHERE news_id=?i', PREFIX.'_post_extras',
+ implode(',', $relatedIds), $relatedId);
+ }
+
+ // Если есть ошбки и включен вывод статистики — оключаем кеш.
+ if (count($outputLog['errors']) > 0 && $cfg['showstat']) {
+ $base->cfg['nocache'] = true;
+ }
+
+ // Формируем данные о запросах для статистики, если требуется
+ if ($base->cfg['showstat'] && $user_group[$member_id['user_group']]['allow_all_edit']) {
+ $stat = $base->db->getStats();
+ $statQ = [];
+
+ foreach ($stat as $i => $q) {
+ $statQ['q'] .= ' '.'['.($i + 1).'] '.$q['query'].' ['.($i + 1).' время:] '.$q['timer']
+ .'';
+ $statQ['t'] += $q['timer'];
+ }
+ $dbStat = 'Запрос(ы): '.$statQ['q'].' Время выполнения запросов: '.$statQ['t'].' ';
+
+ unset($stat);
+ }
+
+ // Создаём кеш, если требуется
+ if (!$base->cfg['nocache']) {
+ create_cache($base->cfg['cachePrefix'], $output, $cacheName, $cacheSuffix);
+ }
}
@@ -1188,50 +1169,53 @@ classic: << Первая < 1 [2] 3 > Последняя >>
// Обрабатываем вложения
/** @var $base */
if ($base->dle_config['files_allow']) {
- if (strpos($output, '[attachment=') !== false) {
- /** @var array $attachments */
- $output = show_attach($output, $attachments);
- }
+ if (strpos($output, '[attachment=') !== false) {
+ /** @var array $attachments */
+ $output = show_attach($output, $attachments);
+ }
} else {
- $output = preg_replace("'\[attachment=(.*?)\]'si", '', $output);
+ $output = preg_replace("'\[attachment=(.*?)\]'si", '', $output);
}
if ($user_group[$member_id['user_group']]['allow_hide']) {
- $output = str_ireplace('[hide]', '', str_ireplace('[/hide]', '', $output));
+ $output = str_ireplace('[hide]', '', str_ireplace('[/hide]', '', $output));
} else {
- $output = preg_replace('#\[hide\](.+?)\[/hide\]#ims', '', $output);
+ $output = preg_replace('#\[hide\](.+?)\[/hide\]#ims', '', $output);
}
// Результат работы модуля
/** @var boolean $external */
if (!$external) {
- // Если блок не является внешним - выводим на печать
- if (count($outputLog['errors']) > 0) {
- // Выводим ошибки, если они есть
- $outputErrors = [];
- $outputErrors[] = '