Вход Регистрация
Файл: system/src-legacy/Tools.php
Строк: 329
<?php

/**
 * This file is part of JohnCMS Content Management System.
 *
 * @copyright JohnCMS Community
 * @license   https://opensource.org/licenses/GPL-3.0 GPL-3.0
 * @link      https://johncms.com JohnCMS Project
 */

declare(strict_types=1);

namespace 
JohncmsSystemLegacy;

use 
JohncmsSystemUsersUser;
use 
JohncmsSystemUsersUserConfig;
use 
JohncmsSystemViewExtensionAssets;
use 
JohncmsSystemViewRender;
use 
PsrContainerContainerInterface;

class 
Tools
{
    
/**
     * @var ContainerInterface
     */
    
private $container;

    
/**
     * @var Assets
     */
    
private $assets;

    
/**
     * @var PDO
     */
    
private $db;

    
/**
     * @var User
     */
    
private $user;

    
/**
     * @var UserConfig
     */
    
private $userConfig;

    
/**
     * @var array
     */
    
private $config;

    public function 
__invoke(ContainerInterface $container)
    {
        
$this->container = $container;
        
$this->assets = $container->get(Assets::class);
        
$config = $container->get('config');
        
$this->config = $config['johncms'] ?? [];
        
$this->db = $container->get(PDO::class);
        
$this->user = $container->get(User::class);
        
$this->userConfig = $this->user->config;

        return 
$this;
    }

    public function 
antiflood()
    {
        
$config = $this->config['antiflood'];

        switch (
$config['mode']) {
            
// Адаптивный режим
            
case 1:
                
$adm = $this->db->query(
                    
'SELECT COUNT(*) FROM `users` WHERE `rights` > 0 AND `lastdate` > ' . (time() - 300)
                )->
fetchColumn();
                
$limit = $adm > 0 ? $config['day'] : $config['night'];
                break;
            
// День
            
case 3:
                
$limit = $config['day'];
                break;
            
// Ночь
            
case 4:
                
$limit = $config['night'];
                break;
            
// По умолчанию день / ночь
            
default:
                
$c_time = date('G', time());
                
$limit = $c_time > $config['day'] && $c_time < $config['night'] ? $config['day'] : $config['night'];
        }

        
// Для Администрации задаем лимит в 4 секунды
        
if ($this->user->rights > 0) {
            
$limit = 4;
        }

        
$flood = $this->user->lastpost + $limit - time();

        return 
$flood > 0 ? $flood : false;
    }

    
/**
     * Обработка текстов перед выводом на экран
     *
     * @param string $str
     * @param int $br Параметр обработки переносов строк
     *                     0 - не обрабатывать (по умолчанию)
     *                     1 - обрабатывать
     *                     2 - вместо переносов строки вставляются пробелы
     * @param int $tags Параметр обработки тэгов
     *                     0 - не обрабатывать (по умолчанию)
     *                     1 - обрабатывать
     *                     2 - вырезать тэги
     *
     * @return string
     */
    
public function checkout($str, $br = 0, $tags = 0)
    {
        
$str = htmlentities(trim($str), ENT_QUOTES, 'UTF-8');

        if (
$br == 1) {
            
$str = nl2br($str);
        } elseif (
$br == 2) {
            
$str = str_replace("rn", ' ', $str);
        }

        if (
$tags == 1) {
            
$str = $this->container->get(Bbcode::class)->tags($str);
        } elseif (
$tags == 2) {
            
$str = $this->container->get(Bbcode::class)->notags($str);
        }

        return 
trim($str);
    }

    
/**
     * Показываем дату с учетом сдвига времени
     *
     * @param int $var Время в Unix формате
     * @return string Отформатированное время
     */
    
public function displayDate(int $var)
    {
        
$shift = ($this->config['timeshift'] + $this->userConfig->timeshift) * 3600;

        if (
date('Y', $var) == date('Y', time())) {
            if (
date('z', $var + $shift) == date('z', time() + $shift)) {
                return 
d__('system', 'Today') . ', ' . date('H:i', $var + $shift);
            }
            if (
date('z', $var + $shift) == date('z', time() + $shift) - 1) {
                return 
d__('system', 'Yesterday') . ', ' . date('H:i', $var + $shift);
            }
        }

        return 
date('d.m.Y / H:i', $var + $shift);
    }

    
/**
     * Сообщения об ошибках
     *
     * @param string|array $error Сообщение об ошибке (или массив с сообщениями)
     * @param string $link Необязательная ссылка перехода
     * @return string
     */
    
public function displayError($error = '', $link = '')
    {
        return 
'<div class="rmenu"><p><b>' . d__('system', 'ERROR') . '!</b><br>'
            
. (is_array($error) ? implode('<br>', $error) : $error) . '</p>'
            
. (! empty($link) ? '<p>' . $link . '</p>' : '') . '</div>';
    }

    
/**
     * Постраничная навигация
     * За основу взята доработанная функция от форума SMF 2.x.x
     *
     * @param string $url
     * @param int $start
     * @param int $total
     * @param int $kmess
     * @return string
     */
    
public function displayPagination($url, $start, $total, $kmess): string
    
{
        
$render = di(Render::class);
        
$items = [];
        
$neighbors = 2;
        if (
$start >= $total) {
            
$start = max(0, $total - (($total % $kmess) === 0 ? $kmess : ($total % $kmess)));
        } else {
            
$start = max(0, (int) $start - ((int) $start % (int) $kmess));
        }

        
$url = filter_var($url, FILTER_SANITIZE_URL);

        if (
$start !== 0) {
            
$items[] = [
                
'url'  => $url . 'page=' . $start / $kmess,
                
'name' => '&lt;&lt;',
            ];
        }

        if (
$start > $kmess * $neighbors) {
            
$items[] = [
                
'url'  => $url . 'page=' . 1,
                
'name' => '1',
            ];
        }

        if (
$start > $kmess * ($neighbors + 1)) {
            
$items[] = [
                
'url'  => '',
                
'name' => '...',
            ];
        }

        for (
$nCont = $neighbors; $nCont >= 1; $nCont--) {
            if (
$start >= $kmess * $nCont) {
                
$tmpStart = $start - $kmess * $nCont;
                
$items[] = [
                    
'url'  => $url . 'page=' . ($tmpStart / $kmess + 1),
                    
'name' => $tmpStart / $kmess + 1,
                ];
            }
        }

        
$items[] = [
            
'url'    => '',
            
'active' => true,
            
'name'   => ($start / $kmess + 1),
        ];
        
$tmpMaxPages = (int) (($total - 1) / $kmess) * $kmess;

        for (
$nCont = 1; $nCont <= $neighbors; $nCont++) {
            if (
$start + $kmess * $nCont <= $tmpMaxPages) {
                
$tmpStart = $start + $kmess * $nCont;
                
$items[] = [
                    
'url'  => $url . 'page=' . ($tmpStart / $kmess + 1),
                    
'name' => $tmpStart / $kmess + 1,
                ];
            }
        }

        if (
$start + $kmess * ($neighbors + 1) < $tmpMaxPages) {
            
$items[] = [
                
'url'  => '',
                
'name' => '...',
            ];
        }

        if (
$start + $kmess * $neighbors < $tmpMaxPages) {
            
$items[] = [
                
'url'  => $url . 'page=' . ($tmpMaxPages / $kmess + 1),
                
'name' => $tmpMaxPages / $kmess + 1,
            ];
        }

        if (
$start + $kmess < $total) {
            
$display_page = ($start + $kmess) > $total ? $total : ($start / $kmess + 2);
            
$items[] = [
                
'url'  => $url . 'page=' . $display_page,
                
'name' => '&gt;&gt;',
            ];
        }

        return 
$render->render(
            
'system::app/pagination',
            [
                
'items' => $items,
            ]
        );
    }

    
/**
     * Показываем местоположение пользователя
     *
     * @param string $place
     * @return string
     */
    
public function displayPlace(string $place): string
    
{
        
$place = rtrim($place, '/');

        if (empty(
$place)) {
            
$place = '/';
        }

        
$part = explode('?', $place);

        
$places = require CONFIG_PATH . 'places.global.php';

        
$places_local = [];
        if (
file_exists(CONFIG_PATH . 'places.local.php')) {
            
$places_local = require CONFIG_PATH . 'places.local.php';
        }

        
$places_list = array_merge($places, $places_local);

        if (
array_key_exists($place, $places_list)) {
            return 
str_replace('#home#', $this->config['homeurl'], $places_list[$place]);
        }

        if (
array_key_exists($part[0], $places_list)) {
            return 
str_replace('#home#', $this->config['homeurl'], $places_list[$part[0]]);
        }

        return 
'<a href="' . $this->config['homeurl'] . ($this->user->rights >= 6 ? $place : '') . '/">'
            
. d__('system', 'Somewhere on the site')
            . 
'</a>';
    }

    
/**
     * Получаем данные пользователя
     *
     * @param int $id
     * @return bool|User|mixed
     */
    
public function getUser(int $id = 0)
    {
        if (
$id === $this->user->id) {
            return 
$this->user;
        }

        
$user = [];

        if (
$id > 0) {
            
$req = $this->db->query("SELECT * FROM `users` WHERE `id` = '${id}'");

            if (
$req->rowCount()) {
                
$user = $req->fetch();
            }
        }

        return new 
User($user);
    }

    
/**
     * Проверка на игнор у получателя
     *
     * @param $id
     * @return bool
     */
    
public function isIgnor($id)
    {
        static 
$user_id = null;
        static 
$return = false;

        if (! 
$this->user->isValid() && ! $id) {
            return 
false;
        }

        if (
null === $user_id || $id != $user_id) {
            
$user_id = $id;
            
$req = $this->db->query(
                
"SELECT * FROM `cms_contact` WHERE `user_id` = '${id}' AND `from_id` = " . $this->user->id
            
);

            if (
$req->rowCount()) {
                
$res = $req->fetch();
                if (
$res['ban'] == 1) {
                    
$return = true;
                }
            }
        }

        return 
$return;
    }

    
/**
     * Транслитерация с Русского в латиницу
     *
     * @param string $str
     * @param bool $to_lowercase
     * @return string
     */
    
public function rusLat($str, bool $to_lowercase = true): string
    
{
        
$replace = [
            
'а' => 'a',
            
'б' => 'b',
            
'в' => 'v',
            
'г' => 'g',
            
'д' => 'd',
            
'е' => 'e',
            
'ё' => 'e',
            
'ж' => 'zh',
            
'з' => 'z',
            
'и' => 'i',
            
'й' => 'y',
            
'к' => 'k',
            
'л' => 'l',
            
'м' => 'm',
            
'н' => 'n',
            
'о' => 'o',
            
'п' => 'p',
            
'р' => 'r',
            
'с' => 's',
            
'т' => 't',
            
'у' => 'u',
            
'ф' => 'f',
            
'х' => 'h',
            
'ц' => 'c',
            
'ч' => 'ch',
            
'ш' => 'sh',
            
'щ' => 'sch',
            
'ь' => ''',
            '
ы' => 'y',
            '
ъ' => ''',
            
'э' => 'e',
            
'ю' => 'yu',
            
'я' => 'ya',
            
'А' => 'A',
            
'Б' => 'B',
            
'В' => 'V',
            
'Г' => 'G',
            
'Д' => 'D',
            
'Е' => 'E',
            
'Ё' => 'E',
            
'Ж' => 'Zh',
            
'З' => 'Z',
            
'И' => 'I',
            
'Й' => 'Y',
            
'К' => 'K',
            
'Л' => 'L',
            
'М' => 'M',
            
'Н' => 'N',
            
'О' => 'O',
            
'П' => 'P',
            
'Р' => 'R',
            
'С' => 'S',
            
'Т' => 'T',
            
'У' => 'U',
            
'Ф' => 'F',
            
'Х' => 'H',
            
'Ц' => 'C',
            
'Ч' => 'Ch',
            
'Ш' => 'Sh',
            
'Щ' => 'Sch',
            
'Ь' => ''',
            '
Ы' => 'Y',
            '
Ъ' => ''',
            
'Э' => 'E',
            
'Ю' => 'Yu',
            
'Я' => 'Ya',
        ];

        if (
$to_lowercase) {
            
$str = mb_strtolower($str);
        }
        return 
strtr($str, $replace);
    }

    
/**
     * Обработка смайлов
     *
     * @param string $str
     * @param bool $adm
     * @return string
     */
    
public function smilies($str, $adm = false)
    {
        static 
$smiliesCache = [];

        if (empty(
$smiliesCache)) {
            
$file = CACHE_PATH . 'smilies-list.cache';

            if (
file_exists($file) && ($smileys = file_get_contents($file)) !== false) {
                
$smiliesCache = unserialize($smileys, ['allowed_classes' => false]);

                return 
strtr(
                    
$str,
                    (
$adm
                        
? array_merge($smiliesCache['usr'], $smiliesCache['adm'])
                        : 
$smiliesCache['usr'])
                );
            }

            return 
$str;
        }

        return 
strtr($str, ($adm ? array_merge($smiliesCache['usr'], $smiliesCache['adm']) : $smiliesCache['usr']));
    }

    
/**
     * Функция пересчета на дни, или часы
     *
     * @param int $var
     * @return bool|string
     */
    
public function timecount(int $var)
    {
        if (
$var < 0) {
            
$var = 0;
        }

        
$day = intdiv($var, 86400);

        return 
$var >= 86400
            
? $day . ' ' . dn__('system', 'Day', 'Days', $day)
            : 
date('G:i:s', mktime(0, 0, $var));
    }

    
// Транслитерация текста
    
public function trans($str)
    {
        
$replace = [
            
'a'  => 'а',
            
'b'  => 'б',
            
'v'  => 'в',
            
'g'  => 'г',
            
'd'  => 'д',
            
'e'  => 'е',
            
'yo' => 'ё',
            
'zh' => 'ж',
            
'z'  => 'з',
            
'i'  => 'и',
            
'j'  => 'й',
            
'k'  => 'к',
            
'l'  => 'л',
            
'm'  => 'м',
            
'n'  => 'н',
            
'o'  => 'о',
            
'p'  => 'п',
            
'r'  => 'р',
            
's'  => 'с',
            
't'  => 'т',
            
'u'  => 'у',
            
'f'  => 'ф',
            
'h'  => 'х',
            
'c'  => 'ц',
            
'ch' => 'ч',
            
'w'  => 'ш',
            
'sh' => 'щ',
            
'q'  => 'ъ',
            
'y'  => 'ы',
            
'x'  => 'э',
            
'yu' => 'ю',
            
'ya' => 'я',
            
'A'  => 'А',
            
'B'  => 'Б',
            
'V'  => 'В',
            
'G'  => 'Г',
            
'D'  => 'Д',
            
'E'  => 'Е',
            
'YO' => 'Ё',
            
'ZH' => 'Ж',
            
'Z'  => 'З',
            
'I'  => 'И',
            
'J'  => 'Й',
            
'K'  => 'К',
            
'L'  => 'Л',
            
'M'  => 'М',
            
'N'  => 'Н',
            
'O'  => 'О',
            
'P'  => 'П',
            
'R'  => 'Р',
            
'S'  => 'С',
            
'T'  => 'Т',
            
'U'  => 'У',
            
'F'  => 'Ф',
            
'H'  => 'Х',
            
'C'  => 'Ц',
            
'CH' => 'Ч',
            
'W'  => 'Ш',
            
'SH' => 'Щ',
            
'Q'  => 'Ъ',
            
'Y'  => 'Ы',
            
'X'  => 'Э',
            
'YU' => 'Ю',
            
'YA' => 'Я',
        ];

        return 
strtr($str, $replace);
    }

    
/**
     * Метод для пересчета сообщений в топике и обновления основных данных топика
     *
     * @param $topic_id
     */
    
public function recountForumTopic($topic_id)
    {
        
$topic_id = (int) $topic_id;
        
$post_count = $this->db->query("SELECT COUNT(*) FROM `forum_messages` WHERE `topic_id` = '${topic_id}' AND (`deleted` != '1' OR `deleted` IS NULL)")->fetchColumn(); // phpcs:ignore
        
$mod_post_count = $this->db->query("SELECT COUNT(*) FROM `forum_messages` WHERE `topic_id` = '${topic_id}'")->fetchColumn(); // phpcs:ignore

        
$last_post = $this->db->query("SELECT * FROM forum_messages WHERE `topic_id` = '${topic_id}' AND (`deleted` != '1' OR `deleted` IS NULL) ORDER BY id DESC LIMIT 1")->fetch(); // phpcs:ignore
        
$mod_last_post = $this->db->query("SELECT * FROM forum_messages WHERE `topic_id` = '${topic_id}' ORDER BY id DESC LIMIT 1")->fetch(); // phpcs:ignore

        // Обновляем время топика
        
$this->db->exec(
            
"UPDATE `forum_topic` SET
            `post_count` = '" 
. $post_count . "',
            `mod_post_count` = '" 
. $mod_post_count . "',
            `last_post_date` = '" 
. $last_post['date'] . "',
            `last_post_author` = '" 
. $last_post['user_id'] . "',
            `last_post_author_name` = '" 
. $last_post['user_name'] . "',
            `last_message_id` = '" 
. $last_post['id'] . "',
            `mod_last_post_date` = '" 
. $mod_last_post['date'] . "',
            `mod_last_post_author` = '" 
. $mod_last_post['user_id'] . "',
            `mod_last_post_author_name` = '" 
. $mod_last_post['user_name'] . "',
            `mod_last_message_id` = '" 
. $mod_last_post['id'] . "'
            WHERE `id` = '
${topic_id}'
        "
        
);
    }

    
/**
     * Форматирует числа в сокращенный формат
     *
     * @param $number
     * @return int|string
     */
    
public function formatNumber($number)
    {
        
$prefixes = 'KMGTPEZY';
        if (
$number >= 1000) {
            for (
$i = -1; $number >= 1000; ++$i) {
                
$number /= 1000;
            }

            if (
$number > 100) {
                
$number = floor($number);
            }

            return 
round($number, 2) . $prefixes[$i];
        }

        return 
$number;
    }

    
/**
     * get all parent sections
     *
     * @param $items , $parent
     * @return array
     */
    
public function getSections(array &$items, $parent): array
    {
        
$res = $this->db->query("SELECT `id`, `name`, `section_type`, `parent` FROM `forum_sections` WHERE `id` = '${parent}'")->fetch();
        if (
$res != false) {
            
$items[] = $res;
            return 
$this->getSections($items, $res['parent']);
        }
        
krsort($items);
        return 
$items;
    }

    public function 
getSectionsTree(array &$section_tree, $parent = 0, $mark = ''): array
    {
        
$req = $this->db->query("SELECT * FROM `forum_sections` WHERE `parent` = '${parent}' ORDER BY `sort` ASC");
        if (
$req->rowCount()) {
            while (
$res = $req->fetch()) {
                
$section_tree[] = [
                    
'id'     => $res['id'],
                    
'name'   => $mark . ' ' . $res['name'],
                    
'parent' => $res['parent'],
                ];
                
$section_tree = $this->getSectionsTree($section_tree, $res['id'], $mark . ' . ');
            }
        }
        return 
$section_tree;
    }
}
Онлайн: 2
Реклама