diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index f0aeb1e9e..fe898660a 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,3 +1,3 @@ patreon: bugo ko_fi: dragomano -custom: ["https://paypal.me/bugo", "https://yasobe.ru/na/light_portal_development"] +custom: ["https://boosty.to/bugo"] diff --git a/README.md b/README.md index e89362094..82117a0ce 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ * **Author:** Bugo [dragomano.ru](https://dragomano.ru/mods/light-portal) * **License:** [GNU GPLv3](https://github.com/dragomano/Light-Portal/blob/master/LICENSE) * **Compatible with:** SMF 2.1 RC2+ / PHP 7.2+ -* **Tested on:** PHP 7.3.22, 7.4.10 / MySQL 5.7.25 / MariaDB 5.5.67, 10.4.13 / PostgreSQL 9.6.18 +* **Tested on:** PHP 7.4.12 / MySQL 5.7.25 / MariaDB 10.5.6 / PostgreSQL 9.6.18 * **Hooks only:** Yes * **Languages:** Spanish, Ukrainian, Polish, English, Russian diff --git a/Sources/LightPortal/Block.php b/Sources/LightPortal/Block.php index 82d9a46fe..14c8fb683 100644 --- a/Sources/LightPortal/Block.php +++ b/Sources/LightPortal/Block.php @@ -11,7 +11,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -33,7 +33,7 @@ public static function show() { global $context, $modSettings; - if (empty($context['template_layers']) || empty($context['lp_active_blocks'])) + if (empty($context['allow_light_portal_view']) || empty($context['template_layers']) || empty($context['lp_active_blocks'])) return; $blocks = self::getFilteredByAreas(); @@ -47,13 +47,13 @@ public static function show() continue; empty($data['content']) - ? Subs::prepareContent($data['content'], $data['type'], $data['id'], LP_CACHE_TIME) - : Subs::parseContent($data['content'], $data['type']); + ? Helpers::prepareContent($data['content'], $data['type'], $data['id'], LP_CACHE_TIME) + : Helpers::parseContent($data['content'], $data['type']); if (empty($data['title'][$context['user']['language']])) $data['title'][$context['user']['language']] = $context['lp_active_blocks'][$data['id']]['title'][$context['user']['language']] ?? ''; - if (empty($title = Helpers::getPublicTitle($data))) + if (empty($title = Helpers::getTitle($data))) $data['title_class'] = ''; $context['lp_blocks'][$data['placement']][$item] = $data; @@ -91,14 +91,14 @@ private static function getFilteredByAreas() $area = $context['current_action'] ?: (!empty($modSettings['lp_frontpage_mode']) ? 'portal' : 'forum'); if (!empty($modSettings['lp_standalone_mode']) && !empty($modSettings['lp_standalone_url'])) { - if (!empty($_SERVER['REQUEST_URL']) && $modSettings['lp_standalone_url'] == $_SERVER['REQUEST_URL']) { + if (Helpers::server()->filled('REQUEST_URL') && $modSettings['lp_standalone_url'] == Helpers::server('REQUEST_URL')) { $area = 'portal'; } elseif (empty($context['current_action'])) { $area = 'forum'; } } - if (!empty($context['current_board'])) + if (!empty($context['current_board']) || !empty($context['lp_page'])) $area = ''; return array_filter($context['lp_active_blocks'], function($block) use ($context, $area) { @@ -108,7 +108,7 @@ private static function getFilteredByAreas() if (isset($block['areas']['all']) || isset($block['areas'][$area])) return true; - if (empty($context['current_action']) && !empty($_GET['page']) && (isset($block['areas']['page=' . (string) $_GET['page']]) || isset($block['areas']['pages']))) + if (empty($context['current_action']) && Helpers::request()->filled('page') && (isset($block['areas']['page=' . Helpers::request('page')]) || isset($block['areas']['pages']))) return true; if (empty($context['current_board'])) diff --git a/Sources/LightPortal/Comment.php b/Sources/LightPortal/Comment.php index af75edcd9..b67ceb096 100644 --- a/Sources/LightPortal/Comment.php +++ b/Sources/LightPortal/Comment.php @@ -11,7 +11,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -45,21 +45,29 @@ public function __construct(string $alias = '') */ public function prepare() { - global $context, $txt, $modSettings, $scripturl; + global $context, $modSettings, $txt, $scripturl; if (empty($this->alias)) return; - if (Helpers::request()->filled('sa') && Helpers::request('sa') == 'new_comment') - $this->add(); + $context['lp_allowed_bbc'] = !empty($modSettings['lp_enabled_bbc_in_comments']) ? explode(',', $modSettings['lp_enabled_bbc_in_comments']) : []; - if (Helpers::request()->filled('sa') && Helpers::request('sa') == 'edit_comment') - $this->edit(); + if (Helpers::request()->filled('sa')) { + switch (Helpers::request('sa')) { + case 'new_comment': + $this->add(); - if (Helpers::request()->filled('sa') && Helpers::request('sa') == 'del_comment') - $this->remove(); + case 'edit_comment': + $this->edit(); - $comments = Helpers::getFromCache('page_' . $this->alias . '_comments', 'getAll', __CLASS__, LP_CACHE_TIME, $context['lp_page']['id']); + case 'del_comment': + $this->remove(); + } + } + + loadLanguage('Editor'); + + $comments = Helpers::cache('page_' . $this->alias . '_comments', 'getAll', __CLASS__, LP_CACHE_TIME, $context['lp_page']['id']); $comments = array_map( function ($comment) { $comment['created'] = Helpers::getFriendlyTime($comment['created_at']); @@ -85,7 +93,7 @@ function ($comment) { $context['page_index'] = constructPageIndex($page_index_url, Helpers::request()->get('start'), $total_comments, $limit); $start = Helpers::request('start'); - $context['page_info']['num_pages'] = floor(($total_comments - 1) / $limit) + 1; + $context['page_info']['num_pages'] = floor($total_comments / $limit) + 1; $context['page_info']['start'] = $context['page_info']['num_pages'] * $limit - $limit; if ($temp_start > $total_comments) @@ -103,7 +111,7 @@ function ($comment) { */ private function add() { - global $smcFunc, $user_info, $context, $modSettings, $txt; + global $smcFunc, $user_info, $context, $txt; $args = array( 'parent_id' => FILTER_VALIDATE_INT, @@ -111,7 +119,6 @@ private function add() 'level' => FILTER_VALIDATE_INT, 'page_id' => FILTER_VALIDATE_INT, 'page_title' => FILTER_SANITIZE_STRING, - 'page_alias' => FILTER_SANITIZE_STRING, 'page_url' => FILTER_SANITIZE_STRING, 'message' => FILTER_SANITIZE_STRING, 'start' => FILTER_VALIDATE_INT, @@ -128,9 +135,8 @@ private function add() $level = $data['level']; $page_id = $data['page_id']; $page_title = $data['page_title']; - $page_alias = $data['page_alias']; $page_url = $data['page_url']; - $message = $data['message']; + $message = Helpers::getShortenText($data['message']); $start = $data['start']; $commentator = $data['commentator']; @@ -143,7 +149,7 @@ private function add() 'parent_id' => 'int', 'page_id' => 'int', 'author_id' => 'int', - 'message' => 'string-' . Helpers::getMaxMessageLength(), + 'message' => 'string-' . MAX_MSG_LENGTH, 'created_at' => 'int' ), array( @@ -157,7 +163,7 @@ private function add() 1 ); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; $result['error'] = true; @@ -171,23 +177,23 @@ private function add() ) ); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; loadTemplate('LightPortal/ViewPage'); ob_start(); - $enabled_tags = !empty($modSettings['lp_enabled_bbc_in_comments']) ? explode(',', $modSettings['lp_enabled_bbc_in_comments']) : []; - show_single_comment([ 'id' => $item, - 'alias' => $page_alias, + 'alias' => $this->alias, + 'parent_id' => $parent, 'author_id' => $user_info['id'], 'author_name' => $user_info['name'], 'avatar' => $this->getUserAvatar(), - 'message' => empty($enabled_tags) ? $message : parse_bbc($message, true, 'light_portal_comments_' . $item, $enabled_tags), + 'message' => empty($context['lp_allowed_bbc']) ? $message : parse_bbc($message, true, 'light_portal_comments_' . $item, $context['lp_allowed_bbc']), 'created_at' => date('Y-m-d', $time), 'created' => Helpers::getFriendlyTime($time), + 'raw_message' => $message, 'can_edit' => true ], $counter + 1, $level + 1); @@ -199,7 +205,7 @@ private function add() 'comment' => $comment, 'created' => $time, 'title' => $txt['response_prefix'] . $page_title, - 'alias' => $page_alias, + 'alias' => $this->alias, 'page_url' => $page_url, 'start' => $start, 'commentator' => $commentator @@ -209,7 +215,7 @@ private function add() ? $this->makeNotify('new_comment', 'page_comment', $result) : $this->makeNotify('new_reply', 'page_comment_reply', $result); - Helpers::getFromCache('page_' . $page_alias . '_comments', null); + Helpers::cache()->forget('page_' . $this->alias . '_comments'); } exit(json_encode($result)); @@ -224,16 +230,16 @@ private function add() */ private function edit() { - global $smcFunc, $context, $modSettings; + global $smcFunc, $context; - $json = file_get_contents('php://input'); - $data = json_decode($json, true); + $json = file_get_contents('php://input'); + $data = json_decode($json, true); if (empty($data)) return; $item = $data['comment_id']; - $message = filter_var($data['message'], FILTER_SANITIZE_STRING); + $message = Helpers::validate(Helpers::getShortenText($data['message'])); if (empty($item) || empty($message)) return; @@ -250,46 +256,32 @@ private function edit() ) ); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; - $enabled_tags = !empty($modSettings['lp_enabled_bbc_in_comments']) ? explode(',', $modSettings['lp_enabled_bbc_in_comments']) : []; - $message = empty($enabled_tags) ? $message : parse_bbc($message, true, 'light_portal_comments_' . $item, $enabled_tags); + $message = empty($context['lp_allowed_bbc']) ? $message : parse_bbc($message, true, 'light_portal_comments_' . $item, $context['lp_allowed_bbc']); - Helpers::getFromCache('page_' . $this->alias . '_comments', null); + Helpers::cache()->forget('page_' . $this->alias . '_comments'); - exit; + exit(json_encode($message)); } /** - * Get user avatar image (html string) + * Get user avatar image * - * Получение аватарки пользователя (готовый HTML-код) + * Получение аватарки пользователя * * @return string */ private function getUserAvatar() { - global $modSettings, $user_info, $smcFunc, $scripturl; - - $user_avatar = []; - - if ((!empty($modSettings['gravatarEnabled']) && substr($user_info['avatar']['url'], 0, 11) == 'gravatar://') || !empty($modSettings['gravatarOverride'])) { - !empty($modSettings['gravatarAllowExtraEmail']) && stristr($user_info['avatar']['url'], 'gravatar://') && isset($user_info['avatar']['url'][12]) - ? $user_avatar['href'] = get_gravatar_url($smcFunc['substr']($user_info['avatar']['url'], 11)) - : $user_avatar['href'] = get_gravatar_url($user_info['email']); - } elseif ($user_info['avatar']['url'] == '' && !empty($user_info['avatar']['id_attach'])) { - $user_avatar['href'] = $user_info['avatar']['custom_dir'] ? $modSettings['custom_avatar_url'] . '/' . $user_info['avatar']['filename'] : $scripturl . '?action=dlattach;attach=' . $user_info['avatar']['id_attach'] . ';type=avatar'; - } elseif (strpos($user_info['avatar']['url'], 'http://') === 0 || strpos($user_info['avatar']['url'], 'https://') === 0) { - $user_avatar['href'] = $user_info['avatar']['url']; - } elseif ($user_info['avatar']['url'] != '') { - $user_avatar['href'] = $modSettings['avatar_url'] . '/' . $smcFunc['htmlspecialchars']($user_info['avatar']['url']); - } else - $user_avatar['href'] = $modSettings['avatar_url'] . '/default.png'; - - if (!empty($user_avatar)) - $user_avatar['image'] = '' . $user_info['name'] . ''; - - return $user_avatar['image']; + global $memberContext, $user_info; + + if (!isset($memberContext[$user_info['id']])) { + loadMemberData($user_info['id']); + loadMemberContext($user_info['id'], true); + } + + return $memberContext[$user_info['id']]['avatar']['image']; } /** @@ -317,33 +309,31 @@ private function makeNotify(string $type, string $action, array $options = []) 'task_data' => 'string' ), array( - '$sourcedir/LightPortal/Notify.php', - '\Bugo\LightPortal\Notify', - $smcFunc['json_encode']( - array( - 'time' => $options['created'], - 'sender_id' => $user_info['id'], - 'sender_name' => $user_info['name'], - 'author_id' => $context['lp_page']['author_id'], - 'commentator_id' => $options['commentator'], - 'content_type' => $type, - 'content_id' => $options['item'], - 'content_action' => $action, - 'extra' => $smcFunc['json_encode']([ - 'content_subject' => $options['title'], - 'content_link' => $options['page_url'] . 'start=' . $options['start'] . '#comment' . $options['item'] - ]) - ) - ) + 'task_file' => '$sourcedir/LightPortal/Notify.php', + 'task_class' => '\Bugo\LightPortal\Notify', + 'task_data' => $smcFunc['json_encode']([ + 'time' => $options['created'], + 'sender_id' => $user_info['id'], + 'sender_name' => $user_info['name'], + 'author_id' => $context['lp_page']['author_id'], + 'commentator_id' => $options['commentator'], + 'content_type' => $type, + 'content_id' => $options['item'], + 'content_action' => $action, + 'extra' => $smcFunc['json_encode']([ + 'content_subject' => $options['title'], + 'content_link' => $options['page_url'] . 'start=' . $options['start'] . '#comment' . $options['item'] + ]) + ]), ), array('id_task') ); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; } /** - * Deleting a comment (and all childs) + * Deleting a comment (and all children) * * Удаление комментария (и всех дочерних) * @@ -351,7 +341,7 @@ private function makeNotify(string $type, string $action, array $options = []) */ private function remove() { - global $smcFunc, $context; + global $smcFunc; $json = file_get_contents('php://input'); $data = json_decode($json, true); @@ -379,9 +369,9 @@ private function remove() ) ); - $context['lp_num_queries'] += 2; + $smcFunc['lp_num_queries'] += 2; - Helpers::getFromCache('page_' . $this->alias . '_comments', null); + Helpers::cache()->forget('page_' . $this->alias . '_comments'); exit; } @@ -396,7 +386,7 @@ private function remove() */ public static function getAll(int $page_id = 0) { - global $smcFunc, $memberContext, $modSettings, $context; + global $smcFunc, $memberContext, $context, $modSettings; if (empty($page_id)) return []; @@ -422,12 +412,6 @@ public static function getAll(int $page_id = 0) $avatar = $memberContext[$row['author_id']]['avatar']['image']; - // Temporaly fix - if (empty($modSettings['gravatarOverride']) && empty($modSettings['gravatarEnabled']) && stristr($memberContext[$row['author_id']]['avatar']['name'], 'gravatar://')) - $avatar = ''; - - $enabled_tags = !empty($modSettings['lp_enabled_bbc_in_comments']) ? explode(',', $modSettings['lp_enabled_bbc_in_comments']) : []; - $comments[$row['id']] = array( 'id' => $row['id'], 'page_id' => $row['page_id'], @@ -435,20 +419,21 @@ public static function getAll(int $page_id = 0) 'author_id' => $row['author_id'], 'author_name' => $row['author_name'], 'avatar' => $avatar, - 'message' => empty($enabled_tags) ? $row['message'] : parse_bbc($row['message'], true, 'light_portal_comments_' . $page_id, $enabled_tags), + 'message' => empty($context['lp_allowed_bbc']) ? $row['message'] : parse_bbc($row['message'], true, 'light_portal_comments_' . $page_id, $context['lp_allowed_bbc']), + 'raw_message' => $row['message'], 'created_at' => $row['created_at'], 'can_edit' => !empty($modSettings['lp_time_to_change_comments']) ? (time() - $row['created_at'] <= (int) $modSettings['lp_time_to_change_comments'] * 60) : false ); } $smcFunc['db_free_result']($request); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; return $comments; } /** - * Get comment tree (parents and childs) + * Get comment tree (parents and children) * * Получаем дерево комментариев * @@ -462,7 +447,7 @@ private function getTree(array $data) foreach ($data as $id => &$node) { empty($node['parent_id']) ? $tree[$id] = &$node - : $data[$node['parent_id']]['childs'][$id] = &$node; + : $data[$node['parent_id']]['children'][$id] = &$node; } return $tree; diff --git a/Sources/LightPortal/Credits.php b/Sources/LightPortal/Credits.php index 5c6f32677..824cd1c1c 100644 --- a/Sources/LightPortal/Credits.php +++ b/Sources/LightPortal/Credits.php @@ -11,7 +11,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -70,40 +70,51 @@ public static function getComponentList() { global $context; - $links = []; - - $links[] = array( - 'title' => 'Flexbox Grid', - 'link' => 'https://github.com/evgenyrodionov/flexboxgrid2', - 'author' => 'Kristofer Joseph', - 'license' => array( - 'name' => 'the Apache License', - 'link' => 'https://github.com/evgenyrodionov/flexboxgrid2/blob/master/LICENSE' - ) - ); - $links[] = array( - 'title' => 'Font Awesome Free', - 'link' => 'https://fontawesome.com/cheatsheet/free', - 'license' => array( - 'name' => 'the Font Awesome Free License', - 'link' => 'https://github.com/FortAwesome/Font-Awesome/blob/master/LICENSE.txt' - ) - ); - $links[] = array( - 'title' => 'Sortable.js', - 'link' => 'https://github.com/SortableJS/Sortable', - 'author' => 'All contributors to Sortable', - 'license' => array( - 'name' => 'the MIT License', - 'link' => 'https://github.com/SortableJS/Sortable/blob/master/LICENSE' - ) - ); - $links[] = array( - 'title' => 'Transliteration', - 'link' => 'https://github.com/dzcpy/transliteration', - 'license' => array( - 'name' => 'the MIT License', - 'link' => 'https://github.com/dzcpy/transliteration/blob/master/LICENSE.txt' + isAllowedTo('light_portal_view'); + + $links = array( + array( + 'title' => 'Flexbox Grid', + 'link' => 'https://github.com/evgenyrodionov/flexboxgrid2', + 'author' => 'Kristofer Joseph', + 'license' => array( + 'name' => 'the Apache License', + 'link' => 'https://github.com/evgenyrodionov/flexboxgrid2/blob/master/LICENSE' + ) + ), + array( + 'title' => 'Font Awesome Free', + 'link' => 'https://fontawesome.com/cheatsheet/free', + 'license' => array( + 'name' => 'the Font Awesome Free License', + 'link' => 'https://github.com/FortAwesome/Font-Awesome/blob/master/LICENSE.txt' + ) + ), + array( + 'title' => 'Sortable.js', + 'link' => 'https://github.com/SortableJS/Sortable', + 'author' => 'All contributors to Sortable', + 'license' => array( + 'name' => 'the MIT License', + 'link' => 'https://github.com/SortableJS/Sortable/blob/master/LICENSE' + ) + ), + array( + 'title' => 'Transliteration', + 'link' => 'https://github.com/dzcpy/transliteration', + 'license' => array( + 'name' => 'the MIT License', + 'link' => 'https://github.com/dzcpy/transliteration/blob/master/LICENSE.txt' + ) + ), + array( + 'title' => 'Choices', + 'link' => 'https://github.com/jshjohnson/Choices', + 'author' => 'Josh Johnson', + 'license' => array( + 'name' => 'the MIT License', + 'link' => 'https://github.com/jshjohnson/Choices/blob/master/LICENSE' + ) ) ); diff --git a/Sources/LightPortal/FrontPage.php b/Sources/LightPortal/FrontPage.php deleted file mode 100644 index 1f2acfd86..000000000 --- a/Sources/LightPortal/FrontPage.php +++ /dev/null @@ -1,612 +0,0 @@ - - * @copyright 2019-2020 Bugo - * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later - * - * @version 1.2 - */ - -if (!defined('SMF')) - die('Hacking attempt...'); - -class FrontPage -{ - /** - * Number of columns (layout) - * - * @var int - */ - private static $num_columns = 12; - - /** - * Show articles on the portal frontpage - * - * Выводим статьи на главной странице портала - * - * @return void - */ - public static function show() - { - global $modSettings, $context, $scripturl, $txt; - - isAllowedTo('light_portal_view'); - - switch ($modSettings['lp_frontpage_mode']) { - case 1: - return Page::show(); - case 2: - self::prepareArticles('topics'); - $context['sub_template'] = 'show_topics_as_articles'; - break; - case 3: - self::prepareArticles(); - $context['sub_template'] = 'show_pages_as_articles'; - break; - default: - self::prepareArticles('boards'); - $context['sub_template'] = 'show_boards_as_articles'; - } - - Subs::runAddons('frontpageCustomTemplate'); - - $context['lp_frontpage_layout'] = self::getNumColumns(); - $context['canonical_url'] = $scripturl; - - loadTemplate('LightPortal/ViewFrontPage'); - - $context['page_title'] = $modSettings['lp_frontpage_title'] ?: ($context['forum_name'] . ' - ' . $txt['lp_portal']); - $context['linktree'][] = array( - 'name' => $txt['lp_portal'] - ); - } - - /** - * Get the number columns for the frontpage layout - * - * Получаем количество колонок для макета главной страницы - * - * @return int - */ - public static function getNumColumns() - { - global $modSettings; - - $num_columns = self::$num_columns; - - if (!empty($modSettings['lp_frontpage_layout'])) { - switch ($modSettings['lp_frontpage_layout']) { - case '1': - $num_columns /= 2; - break; - case '2': - $num_columns /= 3; - break; - case '3': - $num_columns /= 4; - break; - default: - $num_columns /= 6; - } - } - - return $num_columns; - } - - /** - * Form an array of articles - * - * Формируем массив статей - * - * @param string $source (pages|topics|boards) - * @return void - */ - public static function prepareArticles(string $source = 'pages') - { - global $modSettings, $context, $scripturl; - - switch ($source) { - case 'topics': - $function = 'TopicsFromSelectedBoards'; - break; - case 'boards': - $function = 'SelectedBoards'; - break; - default: - $function = 'ActivePages'; - } - - $start =Helpers::request('start'); - $limit = $modSettings['lp_num_items_per_page'] ?? 12; - - $getTotalFunction = 'getTotal' . $function; - $total_items = self::$getTotalFunction(); - - if ($start >= $total_items) { - send_http_status(404); - $start = (floor(($total_items - 1) / $limit) + 1) * $limit - $limit; - } - - $getFunction = 'get' . $function; - $articles = self::$getFunction($start, $limit); - - $articles = array_map(function ($article) use ($modSettings) { - if (!empty($article['date'])) { - $article['datetime'] = date('Y-m-d', $article['date']); - $article['date'] = Helpers::getFriendlyTime($article['date']); - } - - if (isset($article['title'])) - $article['title'] = Helpers::getPublicTitle($article); - - if (empty($article['image']) && !empty($modSettings['lp_image_placeholder'])) - $article['image'] = $modSettings['lp_image_placeholder']; - - return $article; - }, $articles); - - $context['page_index'] = constructPageIndex($scripturl . '?action=portal', Helpers::request()->get('start'), $total_items, $limit); - $context['start'] = Helpers::request()->get('start'); - - $context['lp_frontpage_articles'] = $articles; - - Subs::runAddons('frontpageAssets'); - } - - /** - * Get topics from selected boards - * - * Получаем темы из выбранных разделов - * - * @param int $start - * @param int $limit - * @return array - */ - public static function getTopicsFromSelectedBoards(int $start, int $limit) - { - global $modSettings, $user_info, $smcFunc, $scripturl, $context; - - $selected_boards = !empty($modSettings['lp_frontpage_boards']) ? explode(',', $modSettings['lp_frontpage_boards']) : []; - - if (empty($selected_boards)) - return []; - - if (($topics = cache_get_data('light_portal_articles_u' . $user_info['id'] . '_' . $start . '_' . $limit, LP_CACHE_TIME)) === null) { - $custom_columns = []; - $custom_tables = []; - $custom_wheres = []; - - $custom_parameters = [ - 'current_member' => $user_info['id'], - 'is_approved' => 1, - 'id_poll' => 0, - 'id_redirect_topic' => 0, - 'attachment_type' => 0, - 'selected_boards' => $selected_boards, - 'start' => $start, - 'limit' => $limit - ]; - - $custom_sorting = [ - 't.id_last_msg DESC', - 'mf.poster_time DESC', - 'mf.poster_time', - ]; - - Subs::runAddons('frontTopics', array(&$custom_columns, &$custom_tables, &$custom_wheres, &$custom_parameters, &$custom_sorting)); - - $request = $smcFunc['db_query']('', ' - SELECT - t.id_topic, t.id_board, t.num_views, t.num_replies, t.is_sticky, t.id_first_msg, t.id_member_started, mf.subject, mf.body, mf.smileys_enabled, COALESCE(mem.real_name, mf.poster_name) AS poster_name, mf.poster_time, mf.id_member, ml.id_msg, ml.poster_time AS last_msg_time, b.name, ' . (!empty($modSettings['lp_show_images_in_articles']) ? '(SELECT id_attach FROM {db_prefix}attachments WHERE id_msg = t.id_first_msg AND width <> 0 AND height <> 0 AND approved = {int:is_approved} AND attachment_type = {int:attachment_type} ORDER BY id_attach LIMIT 1) AS id_attach, ' : '') . ($user_info['is_guest'] ? '0' : 'COALESCE(lt.id_msg, lmr.id_msg, -1) + 1') . ' AS new_from, ml.id_msg_modified' . (!empty($custom_columns) ? ', - ' . implode(', ', $custom_columns) : '') . ' - FROM {db_prefix}topics AS t - INNER JOIN {db_prefix}messages AS ml ON (t.id_last_msg = ml.id_msg) - INNER JOIN {db_prefix}messages AS mf ON (t.id_first_msg = mf.id_msg) - INNER JOIN {db_prefix}boards AS b ON (t.id_board = b.id_board) - LEFT JOIN {db_prefix}members AS mem ON (mf.id_member = mem.id_member)' . ($user_info['is_guest'] ? '' : ' - LEFT JOIN {db_prefix}log_topics AS lt ON (t.id_topic = lt.id_topic AND lt.id_member = {int:current_member}) - LEFT JOIN {db_prefix}log_mark_read AS lmr ON (t.id_board = lmr.id_board AND lmr.id_member = {int:current_member})') . (!empty($custom_tables) ? ' - ' . implode("\n\t\t\t\t\t", $custom_tables) : '') . ' - WHERE t.approved = {int:is_approved} - AND t.id_poll = {int:id_poll} - AND t.id_redirect_topic = {int:id_redirect_topic} - AND t.id_board IN ({array_int:selected_boards}) - AND {query_wanna_see_board}' . (!empty($custom_wheres) ? ' - ' . implode("\n\t\t\t\t\t", $custom_wheres) : '') . ' - ORDER BY ' . (!empty($modSettings['lp_frontpage_order_by_num_replies']) ? 'IF (t.num_replies > 0, 0, 1), t.num_replies DESC, ' : '') . $custom_sorting[$modSettings['lp_frontpage_article_sorting'] ?? 0] . ' - LIMIT {int:start}, {int:limit}', - $custom_parameters - ); - - $topics = []; - while ($row = $smcFunc['db_fetch_assoc']($request)) { - if (!isset($topics[$row['id_topic']])) { - Helpers::cleanBbcode($row['subject']); - censorText($row['subject']); - censorText($row['body']); - - $image = null; - if (!empty($row['id_attach'])) - $image = $scripturl . '?action=dlattach;topic=' . $row['id_topic'] . '.0;attach=' . $row['id_attach'] . ';image'; - - if (!empty($modSettings['lp_show_images_in_articles']) && empty($image)) { - $body = parse_bbc($row['body'], false); - $first_post_image = preg_match('/' => ' '))); - - $colorClass = ''; - if ($row['is_sticky']) - $colorClass .= ' alternative2'; - - $topics[$row['id_topic']] = array( - 'id' => $row['id_topic'], - 'id_msg' => $row['id_first_msg'], - 'author_id' => $row['id_member'], - 'author_link' => $scripturl . '?action=profile;u=' . $row['id_member'], - 'author_name' => $row['poster_name'], - 'date' => empty($modSettings['lp_frontpage_article_sorting']) && !empty($row['last_msg_time']) ? $row['last_msg_time'] : $row['poster_time'], - 'subject' => $row['subject'], - 'teaser' => Helpers::getTeaser($row['body']), - 'link' => $scripturl . '?topic=' . $row['id_topic'] . ($row['new_from'] > $row['id_msg_modified'] ? '.0' : '.new;topicseen#new'), - 'board_link' => $scripturl . '?board=' . $row['id_board'] . '.0', - 'board_name' => $row['name'], - 'is_sticky' => !empty($row['is_sticky']), - 'is_new' => $row['new_from'] <= $row['id_msg_modified'], - 'num_views' => $row['num_views'], - 'num_replies' => $row['num_replies'], - 'css_class' => $colorClass, - 'image' => $image, - 'can_edit' => $user_info['is_admin'] || ($row['id_member'] == $user_info['id'] && !empty($user_info['id'])) - ); - - $topics[$row['id_topic']]['msg_link'] = $topics[$row['id_topic']]['link']; - - if (!empty($topics[$row['id_topic']]['num_replies'])) - $topics[$row['id_topic']]['msg_link'] = $scripturl . '?msg=' . $row['id_msg']; - } - - Subs::runAddons('frontTopicsOutput', array(&$topics, $row)); - } - - $smcFunc['db_free_result']($request); - $context['lp_num_queries']++; - - cache_put_data('light_portal_articles_u' . $user_info['id'] . '_' . $start . '_' . $limit, $topics, LP_CACHE_TIME); - } - - return $topics; - } - - /** - * Get count of active topics from selected boards - * - * Получаем количество активных тем из выбранных разделов - * - * @return int - */ - public static function getTotalTopicsFromSelectedBoards() - { - global $modSettings, $user_info, $smcFunc, $context; - - $selected_boards = !empty($modSettings['lp_frontpage_boards']) ? explode(',', $modSettings['lp_frontpage_boards']) : []; - - if (empty($selected_boards)) - return 0; - - if (($num_topics = cache_get_data('light_portal_articles_u' . $user_info['id'] . '_total', LP_CACHE_TIME)) === null) { - $request = $smcFunc['db_query']('', ' - SELECT COUNT(t.id_topic) - FROM {db_prefix}topics AS t - INNER JOIN {db_prefix}boards AS b ON (t.id_board = b.id_board) - WHERE t.approved = {int:is_approved} - AND t.id_poll = {int:id_poll} - AND t.id_redirect_topic = {int:id_redirect_topic} - AND t.id_board IN ({array_int:selected_boards}) - AND {query_wanna_see_board}', - array( - 'is_approved' => 1, - 'id_poll' => 0, - 'id_redirect_topic' => 0, - 'selected_boards' => $selected_boards - ) - ); - - [$num_topics] = $smcFunc['db_fetch_row']($request); - $smcFunc['db_free_result']($request); - $context['lp_num_queries']++; - - cache_put_data('light_portal_articles_u' . $user_info['id'] . '_total', (int) $num_topics, LP_CACHE_TIME); - } - - return (int) $num_topics; - } - - /** - * Get active pages - * - * Получаем активные страницы - * - * @param int $start - * @param int $limit - * @return array - */ - public static function getActivePages(int $start, int $limit) - { - global $user_info, $smcFunc, $modSettings, $scripturl, $context; - - if (($pages = cache_get_data('light_portal_articles_u' . $user_info['id'] . '_' . $start . '_' . $limit, LP_CACHE_TIME)) === null) { - $titles = Helpers::getFromCache('all_titles', 'getAllTitles', '\Bugo\LightPortal\Subs', LP_CACHE_TIME, 'page'); - - $custom_columns = []; - $custom_tables = []; - $custom_wheres = []; - - $custom_parameters = [ - 'type' => 'page', - 'status' => Page::STATUS_ACTIVE, - 'current_time' => time(), - 'permissions' => Helpers::getPermissions(), - 'start' => $start, - 'limit' => $limit - ]; - - $custom_sorting = [ - 'comment_date DESC', - 'p.created_at DESC', - 'p.created_at', - ]; - - Subs::runAddons('frontPages', array(&$custom_columns, &$custom_tables, &$custom_wheres, &$custom_parameters, &$custom_sorting)); - - $request = $smcFunc['db_query']('', ' - SELECT - p.page_id, p.author_id, p.alias, p.content, p.description, p.type, p.status, p.num_views, p.num_comments, p.created_at, GREATEST(p.created_at, p.updated_at) AS date, - mem.real_name AS author_name, (SELECT lp.created_at FROM {db_prefix}lp_comments AS lp WHERE lp.page_id = p.page_id ORDER BY lp.created_at DESC LIMIT 1) AS comment_date' . (!empty($custom_columns) ? ', - ' . implode(', ', $custom_columns) : '') . ' - FROM {db_prefix}lp_pages AS p - LEFT JOIN {db_prefix}members AS mem ON (p.author_id = mem.id_member)' . (!empty($custom_tables) ? ' - ' . implode("\n\t\t\t\t\t", $custom_tables) : '') . ' - WHERE p.status = {int:status} - AND p.created_at <= {int:current_time} - AND p.permissions IN ({array_int:permissions})' . (!empty($custom_wheres) ? ' - ' . implode("\n\t\t\t\t\t", $custom_wheres) : '') . ' - ORDER BY ' . (!empty($modSettings['lp_frontpage_order_by_num_replies']) ? 'IF (num_comments > 0, 0, 1), num_comments DESC, ' : '') . $custom_sorting[$modSettings['lp_frontpage_article_sorting'] ?? 0] . ' - LIMIT {int:start}, {int:limit}', - $custom_parameters - ); - - $pages = []; - while ($row = $smcFunc['db_fetch_assoc']($request)) { - Subs::parseContent($row['content'], $row['type']); - - $image = null; - if (!empty($modSettings['lp_show_images_in_articles'])) { - $first_post_image = preg_match('/ $row['page_id'], - 'author_id' => $row['author_id'], - 'author_link' => $scripturl . '?action=profile;u=' . $row['author_id'], - 'author_name' => $row['author_name'], - 'teaser' => Helpers::getTeaser($row['description'] ?: strip_tags($row['content'])), - 'type' => $row['type'], - 'num_views' => $row['num_views'], - 'num_comments' => $row['num_comments'], - 'date' => empty($modSettings['lp_frontpage_article_sorting']) && !empty($row['comment_date']) ? $row['comment_date'] : $row['created_at'], - 'is_new' => $user_info['last_login'] < $row['date'] && $row['author_id'] != $user_info['id'], - 'link' => $scripturl . '?page=' . $row['alias'], - 'image' => $image, - 'can_edit' => $user_info['is_admin'] || (allowedTo('light_portal_manage_own_pages') && $row['author_id'] == $user_info['id']) - ); - } - - $pages[$row['page_id']]['title'] = $titles[$row['page_id']]; - - Subs::runAddons('frontPagesOutput', array(&$pages, $row)); - } - - $smcFunc['db_free_result']($request); - $context['lp_num_queries']++; - - cache_put_data('light_portal_articles_u' . $user_info['id'] . '_' . $start . '_' . $limit, $pages, LP_CACHE_TIME); - } - - return $pages; - } - - /** - * Get count of active pages - * - * Получаем количество активных страниц - * - * @return int - */ - public static function getTotalActivePages() - { - global $user_info, $smcFunc, $context; - - if (($num_pages = cache_get_data('light_portal_articles_u' . $user_info['id'] . '_total', LP_CACHE_TIME)) === null) { - $request = $smcFunc['db_query']('', ' - SELECT COUNT(page_id) - FROM {db_prefix}lp_pages - WHERE status = {int:status} - AND created_at <= {int:current_time} - AND permissions IN ({array_int:permissions})', - array( - 'status' => Page::STATUS_ACTIVE, - 'current_time' => time(), - 'permissions' => Helpers::getPermissions() - ) - ); - - [$num_pages] = $smcFunc['db_fetch_row']($request); - $smcFunc['db_free_result']($request); - $context['lp_num_queries']++; - - cache_put_data('light_portal_articles_u' . $user_info['id'] . '_total', (int) $num_pages, LP_CACHE_TIME); - } - - return (int) $num_pages; - } - - /** - * Get selected boards - * - * Получаем выбранные разделы - * - * @param int $start - * @param int $limit - * @return array - */ - public static function getSelectedBoards(int $start, int $limit) - { - global $modSettings, $user_info, $smcFunc, $context, $scripturl; - - $selected_boards = !empty($modSettings['lp_frontpage_boards']) ? explode(',', $modSettings['lp_frontpage_boards']) : []; - - if (empty($selected_boards)) - return []; - - if (($boards = cache_get_data('light_portal_articles_u' . $user_info['id'] . '_' . $start . '_' . $limit, LP_CACHE_TIME)) === null) { - $custom_columns = []; - $custom_tables = []; - $custom_wheres = []; - - $custom_parameters = [ - 'blank_string' => '', - 'current_member' => $user_info['id'], - 'selected_boards' => $selected_boards, - 'start' => $start, - 'limit' => $limit - ]; - - $custom_sorting = [ - 'b.id_last_msg DESC', - 'm.poster_time DESC', - 'm.poster_time', - ]; - - Subs::runAddons('frontBoards', array(&$custom_columns, &$custom_tables, &$custom_wheres, &$custom_parameters, &$custom_sorting)); - - $request = $smcFunc['db_query']('', ' - SELECT - b.id_board, b.name, b.description, b.redirect, CASE WHEN b.redirect != {string:blank_string} THEN 1 ELSE 0 END AS is_redirect, b.num_posts, - GREATEST(m.poster_time, m.modified_time) AS last_updated, m.id_msg, m.id_topic, c.name AS cat_name,' . ($user_info['is_guest'] ? ' 1 AS is_read, 0 AS new_from' : ' - (CASE WHEN COALESCE(lb.id_msg, 0) >= b.id_last_msg THEN 1 ELSE 0 END) AS is_read, COALESCE(lb.id_msg, -1) + 1 AS new_from') . (!empty($modSettings['lp_show_images_in_articles']) ? ', COALESCE(a.id_attach, 0) AS attach_id' : '') . (!empty($custom_columns) ? ', - ' . implode(', ', $custom_columns) : '') . ' - FROM {db_prefix}boards AS b - INNER JOIN {db_prefix}categories AS c ON (b.id_cat = c.id_cat) - LEFT JOIN {db_prefix}messages AS m ON (b.id_last_msg = m.id_msg)' . ($user_info['is_guest'] ? '' : ' - LEFT JOIN {db_prefix}log_boards AS lb ON (b.id_board = lb.id_board AND lb.id_member = {int:current_member})') . (!empty($modSettings['lp_show_images_in_articles']) ? ' - LEFT JOIN {db_prefix}attachments AS a ON (b.id_last_msg = a.id_msg AND a.id_thumb <> 0 AND a.width > 0 AND a.height > 0)' : '') . (!empty($custom_tables) ? ' - ' . implode("\n\t\t\t\t\t", $custom_tables) : '') . ' - WHERE b.id_board IN ({array_int:selected_boards}) - AND {query_see_board}' . (!empty($custom_wheres) ? ' - ' . implode("\n\t\t\t\t\t", $custom_wheres) : '') . ' - ORDER BY ' . (!empty($modSettings['lp_frontpage_order_by_num_replies']) ? 'IF (b.num_posts > 0, 0, 1), b.num_posts DESC, ' : '') . $custom_sorting[$modSettings['lp_frontpage_article_sorting'] ?? 0] . ' - LIMIT {int:start}, {int:limit}', - $custom_parameters - ); - - $boards = []; - while ($row = $smcFunc['db_fetch_assoc']($request)) { - $board_name = parse_bbc($row['name'], false, '', $context['description_allowed_tags']); - $description = parse_bbc($row['description'], false, '', $context['description_allowed_tags']); - $cat_name = parse_bbc($row['cat_name'], false, '', $context['description_allowed_tags']); - - $image = null; - if (!empty($modSettings['lp_show_images_in_articles'])) { - $board_image = preg_match('/ $row['id_board'], - 'name' => $board_name, - 'teaser' => Helpers::getTeaser($description), - 'category' => $cat_name, - 'link' => $row['is_redirect'] ? $row['redirect'] : $scripturl . '?board=' . $row['id_board'] . '.0', - 'is_redirect' => $row['is_redirect'], - 'is_updated' => empty($row['is_read']), - 'num_posts' => $row['num_posts'], - 'image' => $image, - 'can_edit' => $user_info['is_admin'] || allowedTo('manage_boards') - ); - - if (!empty($row['last_updated'])) { - $boards[$row['id_board']]['last_post'] = $scripturl . '?topic=' . $row['id_topic'] . '.msg' . ($user_info['is_guest'] ? $row['id_msg'] : $row['new_from']) . (empty($row['is_read']) ? ';boardseen' : '') . '#new'; - - $boards[$row['id_board']]['date'] = $row['last_updated']; - } - - $boards[$row['id_board']]['msg_link'] = $boards[$row['id_board']]['link']; - - if (empty($boards[$row['id_board']]['is_redirect'])) - $boards[$row['id_board']]['msg_link'] = $scripturl . '?msg=' . $row['id_msg']; - - Subs::runAddons('frontBoardsOutput', array(&$boards, $row)); - } - - $smcFunc['db_free_result']($request); - $context['lp_num_queries']++; - - cache_put_data('light_portal_articles_u' . $user_info['id'] . '_' . $start . '_' . $limit, $boards, LP_CACHE_TIME); - } - - return $boards; - } - - /** - * Get count of selected boards - * - * Получаем количество выбранных разделов - * - * @return int - */ - public static function getTotalSelectedBoards() - { - global $modSettings, $context, $smcFunc; - - $selected_boards = !empty($modSettings['lp_frontpage_boards']) ? explode(',', $modSettings['lp_frontpage_boards']) : []; - - if (empty($selected_boards)) - return 0; - - if (($num_boards = cache_get_data('light_portal_articles_u' . $context['user']['id'] . '_total', LP_CACHE_TIME)) === null) { - $request = $smcFunc['db_query']('', ' - SELECT COUNT(b.id_board) - FROM {db_prefix}boards AS b - INNER JOIN {db_prefix}categories AS c ON (b.id_cat = c.id_cat) - WHERE b.id_board IN ({array_int:selected_boards}) - AND {query_see_board}', - array( - 'selected_boards' => $selected_boards - ) - ); - - [$num_boards] = $smcFunc['db_fetch_row']($request); - $smcFunc['db_free_result']($request); - $context['lp_num_queries']++; - - cache_put_data('light_portal_articles_u' . $context['user']['id'] . '_total', (int) $num_boards, LP_CACHE_TIME); - } - - return (int) $num_boards; - } -} diff --git a/Sources/LightPortal/Helpers.php b/Sources/LightPortal/Helpers.php index 3f742ded7..92e56ea32 100644 --- a/Sources/LightPortal/Helpers.php +++ b/Sources/LightPortal/Helpers.php @@ -2,7 +2,10 @@ namespace Bugo\LightPortal; +use Bugo\LightPortal\Utils\Cache; +use Bugo\LightPortal\Utils\Post; use Bugo\LightPortal\Utils\Request; +use Bugo\LightPortal\Utils\Server; use Bugo\LightPortal\Utils\Session; /** @@ -14,7 +17,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -23,43 +26,76 @@ class Helpers { /** - * Get the request object + * Get the cache data or Cache class object * - * Получаем объект $_REQUEST + * Получаем данные из кэша или объект класса Cache * * @param string|null $key + * @param string|null $funcName + * @param string $class + * @param int $time (in seconds) + * @param mixed $vars * @return mixed */ - public static function request($key = null) + public static function cache(string $key = null, string $funcName = null, string $class = 'self', int $time = 3600, ...$vars) { - return $key ? (new Request)($key) : new Request; + return $key ? (new Cache)($key, $funcName, $class, $time, ...$vars) : new Cache; } /** - * Get the session object + * Get $_POST object * - * Получаем объект $_SESSION + * Получаем объект $_POST * * @param string|null $key + * @param mixed|null $default * @return mixed */ - public static function session($key = null) + public static function post($key = null, $default = null) { - return $key ? (new Session)($key) : new Session; + return $key ? (new Post)($key, $default) : new Post; } /** - * Get the maximum possible length of the message, in accordance with the settings of the forum + * Get $_REQUEST object * - * Получаем максимально возможную длину сообщения, в соответствии с настройками форума + * Получаем объект $_REQUEST * - * @return int + * @param string|null $key + * @param mixed $default + * @return mixed */ - public static function getMaxMessageLength() + public static function request($key = null, $default = null) { - global $modSettings; + return $key ? (new Request)($key, $default) : new Request; + } + + /** + * Get $_SERVER object + * + * Получаем объект $_SERVER + * + * @param string|null $key + * @param mixed $default + * @return mixed + */ + public static function server($key = null, $default = null) + { + return $key ? (new Server)($key, $default) : new Server; + } - return !empty($modSettings['max_messageLength']) && $modSettings['max_messageLength'] > 65534 ? (int) $modSettings['max_messageLength'] : 65534; + /** + * Get $_SESSION object + * + * Получаем объект $_SESSION + * + * @param string|null $key + * @param mixed $default + * @return mixed + */ + public static function session($key = null, $default = null) + { + return $key ? (new Session)($key, $default) : new Session; } /** @@ -80,8 +116,8 @@ public static function cleanBbcode(&$data) * * Получаем иконку блока * - * @param null|string $icon - * @param null|string $type + * @param string|null $icon + * @param string|null $type * @return string */ public static function getIcon($icon = null, $type = null) @@ -125,10 +161,10 @@ public static function doesThisThemeUseFontAwesome() * * Получаем заголовок блока превью * - * @param string $prefix + * @param string|null $prefix * @return string */ - public static function getPreviewTitle($prefix = null) + public static function getPreviewTitle(string $prefix = null) { global $context, $txt; @@ -191,8 +227,8 @@ public static function getCorrectDeclension(int $num, $str) return $num . ' ' . $str[($num % 10 === 1 && substr((string) $num, -2, 2) != '11') ? 0 : (($num % 10 === 0 || in_array(substr((string) $num, -2, 2), $cases)) ? 1 : 2)]; } - // Plural rule #7 (Croatian, Serbian, Russian, Ukrainian) - $rule_seven = array('hr', 'sr', 'ru', 'uk'); + // Plural rule #7 (Bosnian, Croatian, Serbian, Russian, Ukrainian) + $rule_seven = array('bs', 'hr', 'sr', 'ru', 'uk'); if (in_array($txt['lang_dictionary'], $rule_seven)) { $cases = array(2, 0, 1, 1, 1, 2); return $num . ' ' . $str[($num % 100 > 4 && $num % 100 < 20) ? 2 : $cases[min($num % 10, 5)]]; @@ -221,7 +257,7 @@ public static function getCorrectDeclension(int $num, $str) if ($txt['lang_dictionary'] == 'ar') return $str[in_array($num, array(0, 1, 2)) ? $num : ($num % 100 >= 3 && $num % 100 <= 10 ? 3 : ($num % 100 >= 11 ? 4 : 5))] . ' ' . $num; - // Plural rule #1 (Danish, Dutch, English, German, Norwegian, Swedish, Finnish, Hungarian, Greek, Hebrew, Italian, Portuguese_pt, Spanish, Catalan, Vietnamese, Esperanto, Galician, Albanian, Bulgarian) + // Plural rule #1 (Danish, Dutch, English, German, Norwegian, Swedish, Estonian, Finnish, Hungarian, Greek, Hebrew, Italian, Portuguese_pt, Spanish, Catalan, Vietnamese, Esperanto, Galician, Albanian, Bulgarian) return $num . ' ' . $str[$num == 1 ? 0 : 1]; } @@ -350,41 +386,6 @@ public static function getDateFormat(int $day, string $month, string $postfix) return $day . ' ' . $month . (strpos($postfix, ":") === false ? ' ' : ', ') . $postfix; } - /** - * Get needed data using cache - * - * Получаем нужные данные, используя кэш - * - * @param string $key - * @param string|null $funcName - * @param string $class - * @param int $time (in seconds) - * @param mixed $vars - * @return mixed - */ - public static function getFromCache(string $key, ?string $funcName, string $class = 'self', int $time = 3600, ...$vars) - { - if (empty($key)) - return false; - - if ($funcName === null || $time === 0) - cache_put_data('light_portal_' . $key, null); - - if (($$key = cache_get_data('light_portal_' . $key, $time)) === null) { - $$key = null; - - if (method_exists($class, $funcName)) { - $$key = $class == 'self' ? self::$funcName(...$vars) : $class::$funcName(...$vars); - } elseif (function_exists($funcName)) { - $$key = $funcName(...$vars); - } - - cache_put_data('light_portal_' . $key, $$key, $time); - } - - return $$key; - } - /** * Form a list of addons that not installed * @@ -416,10 +417,13 @@ public static function canViewItem(int $permissions) switch ($permissions) { case 0: return $user_info['is_admin'] == 1; + case 1: return $user_info['is_guest'] == 1; + case 2: return !empty($user_info['id']); + default: return true; } @@ -468,25 +472,24 @@ public static function isFrontpage(string $alias) } /** - * Get a public object title, according to the user's language, or the forum's language, or in English + * Get an object title, according to the user's language, or the forum's language, or in English * - * Получаем публичный заголовок объекта, в соответствии с языком пользователя или форума, или на английском + * Получаем заголовок объекта, в соответствии с языком пользователя или форума, или на английском * * @param array $object * @return string */ - public static function getPublicTitle(array $object) + public static function getTitle(array $object) { global $user_info, $language; if (empty($object) || !isset($object['title'])) return ''; - $lang1 = $object['title'][$user_info['language']] ?? null; - $lang2 = $object['title'][$language] ?? null; - $lang3 = $object['title']['english'] ?? null; - - return $lang1 ?: $lang2 ?: $lang3 ?: ''; + return $object['title'][$user_info['language']] + ?? $object['title'][$language] + ?? $object['title']['english'] + ?? ''; } /** @@ -537,22 +540,36 @@ public static function getTeaser($text) { global $modSettings; - return !empty($modSettings['lp_teaser_size']) ? shorten_subject(trim($text), $modSettings['lp_teaser_size']) : trim($text); + return !empty($modSettings['lp_teaser_size']) ? self::getShortenText(trim($text), $modSettings['lp_teaser_size']) : trim($text); } /** - * Collecting the names of existing themes + * Get the shorten text cut to the given length * - * Собираем названия существующих тем оформления + * Получаем обрезанный до заданной длины текст + * + * @param string $text + * @param int $length + * @return string + */ + public static function getShortenText($text, $length = MAX_MSG_LENGTH) + { + return shorten_subject($text, $length); + } + + /** + * Get an array with names of installed themes + * + * Получаем массив с названиями установленных тем оформления * * @return array */ public static function getForumThemes() { - global $smcFunc, $context; + global $smcFunc; $result = $smcFunc['db_query']('', ' - SELECT id_theme, variable, value + SELECT id_theme, value FROM {db_prefix}themes WHERE variable = {string:name}', array( @@ -565,8 +582,133 @@ public static function getForumThemes() $current_themes[$row['id_theme']] = $row['value']; $smcFunc['db_free_result']($result); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; return $current_themes; } + + /** + * Prepare content to display + * + * Готовим контент к отображению в браузере + * + * @param string $content + * @param string $type + * @param int $block_id + * @param int $cache_time + * @return void + */ + public static function prepareContent(string &$content, string $type = 'bbc', int $block_id = 0, int $cache_time = 0) + { + global $context; + + !empty($block_id) && !empty($context['lp_active_blocks'][$block_id]) + ? $parameters = $context['lp_active_blocks'][$block_id]['parameters'] ?? [] + : $parameters = $context['lp_block']['options']['parameters'] ?? []; + + Subs::runAddons('prepareContent', array(&$content, $type, $block_id, $cache_time, $parameters)); + } + + /** + * Parse content depending on the type + * + * Парсим контент в зависимости от типа + * + * @param string $content + * @param string $type + * @return void + */ + public static function parseContent(string &$content, string $type = 'bbc') + { + global $context; + + switch ($type) { + case 'bbc': + $content = parse_bbc($content); + + // Integrate with the Paragrapher mod + call_integration_hook('integrate_paragrapher_string', array(&$content)); + + break; + + case 'html': + $content = un_htmlspecialchars($content); + + break; + + case 'php': + $content = trim(un_htmlspecialchars($content)); + $content = trim($content, ''); + + ob_start(); + + try { + $content = html_entity_decode($content, ENT_COMPAT, $context['character_set'] ?? 'UTF-8'); + eval($content); + } catch (\ParseError $p) { + echo $p->getMessage(); + } + + $content = ob_get_clean(); + + break; + + default: + Subs::runAddons('parseContent', array(&$content, $type)); + } + } + + /** + * Get the filtered $obj[$key] + * + * Получаем отфильтрованное значение $obj[$key] + * + * @param string $key + * @param string|array $type + * @return mixed + */ + public static function validate(string $key, $type = 'string') + { + if (is_array($type)) { + return filter_var($key, FILTER_VALIDATE_REGEXP, $type); + } + + switch ($type) { + case 'string': + $filter = FILTER_SANITIZE_STRING; + break; + + case 'int': + $filter = FILTER_VALIDATE_INT; + break; + + case 'bool': + $filter = FILTER_VALIDATE_BOOLEAN; + break; + + case 'url': + $filter = FILTER_VALIDATE_URL; + break; + + default: + $filter = FILTER_DEFAULT; + } + + return filter_var($key, $filter); + } + + /** + * Check whether need to display dates in lowercase for the current language + * + * Проверяем, нужно ли для текущего языка отображать даты в нижнем регистре + * + * @return bool + */ + public static function isLowerCaseForDates() + { + global $txt; + + return in_array($txt['lang_dictionary'], ['pl', 'es', 'ru', 'uk']); + } } diff --git a/Sources/LightPortal/Integration.php b/Sources/LightPortal/Integration.php index ef56edd98..fc126bd0b 100644 --- a/Sources/LightPortal/Integration.php +++ b/Sources/LightPortal/Integration.php @@ -11,7 +11,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -32,6 +32,7 @@ public static function hooks() add_integration_function('integrate_user_info', __CLASS__ . '::userInfo', false, __FILE__); add_integration_function('integrate_pre_css_output', __CLASS__ . '::preCssOutput', false, __FILE__); add_integration_function('integrate_load_theme', __CLASS__ . '::loadTheme', false, __FILE__); + add_integration_function('integrate_redirect', __CLASS__ . '::redirect', false, __FILE__); add_integration_function('integrate_actions', __CLASS__ . '::actions', false, __FILE__); add_integration_function('integrate_default_action', __CLASS__ . '::defaultAction', false, __FILE__); add_integration_function('integrate_current_action', __CLASS__ . '::currentAction', false, __FILE__); @@ -40,7 +41,7 @@ public static function hooks() add_integration_function('integrate_load_permissions', __CLASS__ . '::loadPermissions', false, __FILE__); add_integration_function('integrate_alert_types', __CLASS__ . '::alertTypes', false, __FILE__); add_integration_function('integrate_fetch_alerts', __CLASS__ . '::fetchAlerts', false, __FILE__); - add_integration_function('integrate_whos_online', __CLASS__ . '::whosOnline', false, __FILE__); + add_integration_function('integrate_whos_online', __CLASS__ . '::whoisOnline', false, __FILE__); add_integration_function('integrate_credits', __NAMESPACE__ . '\Credits::show', false, '$sourcedir/LightPortal/Credits.php'); add_integration_function('integrate_admin_areas', __NAMESPACE__ . '\Settings::adminAreas', false, '$sourcedir/LightPortal/Settings.php'); add_integration_function('integrate_admin_search', __NAMESPACE__ . '\Settings::adminSearch', false, '$sourcedir/LightPortal/Settings.php'); @@ -58,6 +59,8 @@ public static function autoload(array &$classMap) { $classMap['Bugo\\LightPortal\\'] = 'LightPortal/'; $classMap['Bugo\\LightPortal\\Addons\\'] = 'LightPortal/addons/'; + $classMap['Bugo\\LightPortal\\Front\\'] = 'LightPortal/front/'; + $classMap['Bugo\\LightPortal\\Impex\\'] = 'LightPortal/impex/'; $classMap['Bugo\\LightPortal\\Utils\\'] = 'LightPortal/utils/'; } @@ -70,19 +73,20 @@ public static function autoload(array &$classMap) */ public static function userInfo() { - global $context, $modSettings, $user_info, $sourcedir; + global $context, $smcFunc, $modSettings, $user_info, $sourcedir; $context['lp_load_time'] = $context['lp_load_time'] ?? microtime(true); - $context['lp_num_queries'] = $context['lp_num_queries'] ?? 0; + $smcFunc['lp_num_queries'] = $smcFunc['lp_num_queries'] ?? 0; $lp_constants = [ 'LP_NAME' => 'Light Portal', - 'LP_VERSION' => '1.2', - 'LP_RELEASE_DATE' => '2020-10-10', - 'LP_DEBUG' => !empty($modSettings['lp_show_debug_info']) && $user_info['is_admin'], + 'LP_VERSION' => '1.3', + 'LP_RELEASE_DATE' => '2020-11-11', + 'LP_DEBUG' => !empty($modSettings['lp_show_debug_info']) && !empty($user_info['is_admin']), 'LP_ADDONS' => $sourcedir . '/LightPortal/addons', 'LP_CACHE_TIME' => $modSettings['lp_cache_update_interval'] ?? 3600, - 'RC2_CLEAN' => !defined('JQUERY_VERSION') + 'RC2_CLEAN' => !defined('JQUERY_VERSION'), + 'MAX_MSG_LENGTH' => 65535 ]; foreach ($lp_constants as $key => $value) @@ -125,6 +129,25 @@ public static function loadTheme() Subs::runAddons(); } + /** + * Set up a redirect to the main page of the forum, when requesting an action markasread + * + * Настраиваем редирект на главную страницу форума, при запросе действия action=markasread + * + * @param string $setLocation + * @return void + */ + public static function redirect(string &$setLocation) + { + global $modSettings, $scripturl; + + if (empty($modSettings['lp_frontpage_mode']) || (!empty($modSettings['lp_standalone_mode']) && !empty($modSettings['lp_standalone_url']))) + return; + + if (Helpers::request()->is('markasread')) + $setLocation = $scripturl . '?action=forum'; + } + /** * Add "action=portal" * @@ -137,7 +160,7 @@ public static function actions(array &$actions) { global $context, $modSettings; - $actions['portal'] = array('LightPortal/FrontPage.php', array(__NAMESPACE__ . '\FrontPage', 'show')); + $actions['portal'] = array('LightPortal/front/Article.php', array(__NAMESPACE__ . '\Front\Article', 'show')); $actions['forum'] = array('BoardIndex.php', 'BoardIndex'); if (Helpers::request()->is('portal') && $context['current_subaction'] == 'tags') @@ -155,22 +178,23 @@ public static function actions(array &$actions) * * Обращаемся к странице портала или вызываем метод по умолчанию * - * @return void + * @return mixed */ public static function defaultAction() { global $modSettings, $sourcedir; - if (!empty($_GET['page'])) - return Page::show(); + if (Helpers::request()->filled('page')) + return call_user_func(array(__NAMESPACE__ . '\Page', 'show')); if (empty($modSettings['lp_frontpage_mode']) || (!empty($modSettings['lp_standalone_mode']) && !empty($modSettings['lp_standalone_url']))) { require_once($sourcedir . '/BoardIndex.php'); - return BoardIndex(); + + return call_user_func('BoardIndex'); } if (!empty($modSettings['lp_frontpage_mode'])) - return FrontPage::show(); + return call_user_func(array(__NAMESPACE__ . '\Front\Article', 'show')); } /** @@ -191,7 +215,7 @@ public static function currentAction(string &$current_action) if (Helpers::request()->isEmpty('action')) { $current_action = 'portal'; - if (!empty($modSettings['lp_standalone_mode']) && !empty($modSettings['lp_standalone_url']) && $modSettings['lp_standalone_url'] != $_SERVER['REQUEST_URL']) + if (!empty($modSettings['lp_standalone_mode']) && !empty($modSettings['lp_standalone_url']) && $modSettings['lp_standalone_url'] != Helpers::server('REQUEST_URL')) $current_action = 'forum'; if (Helpers::request()->filled('page')) @@ -203,7 +227,7 @@ public static function currentAction(string &$current_action) $disabled_actions = !empty($modSettings['lp_standalone_mode_disabled_actions']) ? explode(',', $modSettings['lp_standalone_mode_disabled_actions']) : []; $disabled_actions[] = 'home'; - if (!empty($context['current_board']) || !empty($context['current_topic']) || Helpers::request()->is(['keywords'])) + if (!empty($context['current_board']) || Helpers::request()->is(['keywords'])) $current_action = !empty($modSettings['lp_standalone_mode']) ? (!in_array('forum', $disabled_actions) ? 'forum' : 'portal') : 'home'; } @@ -222,6 +246,7 @@ public static function menuButtons(array &$buttons) if (Subs::isPortalMustNotBeLoaded()) return; + $context['allow_light_portal_view'] = allowedTo('light_portal_view'); $context['allow_light_portal_manage_blocks'] = allowedTo('light_portal_manage_blocks'); $context['allow_light_portal_manage_own_pages'] = allowedTo('light_portal_manage_own_pages'); @@ -452,7 +477,7 @@ public static function fetchAlerts(array &$alerts, array &$formats) * @param array $actions * @return string */ - public static function whosOnline(array $actions) + public static function whoisOnline(array $actions) { global $txt, $scripturl, $modSettings, $context; diff --git a/Sources/LightPortal/ManageBlocks.php b/Sources/LightPortal/ManageBlocks.php index 5c470a852..a95daad2d 100644 --- a/Sources/LightPortal/ManageBlocks.php +++ b/Sources/LightPortal/ManageBlocks.php @@ -11,7 +11,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -19,8 +19,6 @@ class ManageBlocks { - use ShareTools; - /** * Areas for block output must begin with a Latin letter and may consist of lowercase Latin letters, numbers, and some characters * @@ -67,7 +65,7 @@ public static function main() */ public static function getAll() { - global $smcFunc, $context; + global $smcFunc; $request = $smcFunc['db_query']('', ' SELECT b.block_id, b.icon, b.icon_type, b.type, b.placement, b.priority, b.permissions, b.status, b.areas, bt.lang, bt.title @@ -96,7 +94,7 @@ public static function getAll() } $smcFunc['db_free_result']($request); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; return $current_blocks; } @@ -131,7 +129,8 @@ public static function doActions() self::updatePriority(); - clean_cache(); + Helpers::cache()->flush(); + exit; } @@ -145,7 +144,7 @@ public static function doActions() */ private static function remove(array $items) { - global $smcFunc, $context; + global $smcFunc; if (empty($items)) return; @@ -178,7 +177,7 @@ private static function remove(array $items) ) ); - $context['lp_num_queries'] += 3; + $smcFunc['lp_num_queries'] += 3; } /** @@ -196,7 +195,7 @@ private static function makeCopy(int $item) if (empty($item)) return; - $_POST['clone'] = true; + Helpers::post()->put('clone', true); $result['success'] = false; $context['lp_block'] = self::getData($item); @@ -216,7 +215,7 @@ private static function makeCopy(int $item) ]; } - Helpers::getFromCache('active_blocks', null); + Helpers::cache()->forget('active_blocks'); exit(json_encode($result)); } @@ -232,7 +231,7 @@ private static function makeCopy(int $item) */ public static function toggleStatus(array $items, int $status = 0) { - global $smcFunc, $context; + global $smcFunc; if (empty($items)) return; @@ -247,7 +246,7 @@ public static function toggleStatus(array $items, int $status = 0) ) ); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; } /** @@ -259,7 +258,7 @@ public static function toggleStatus(array $items, int $status = 0) */ private static function updatePriority() { - global $smcFunc, $context; + global $smcFunc; $json = file_get_contents('php://input'); $data = json_decode($json, true); @@ -279,16 +278,14 @@ private static function updatePriority() if (!empty($blocks) && is_array($blocks)) { $smcFunc['db_query']('', ' UPDATE {db_prefix}lp_blocks - SET priority = CASE ' . $conditions . ' - ELSE priority - END + SET priority = CASE ' . $conditions . ' ELSE priority END WHERE block_id IN ({array_int:blocks})', array( 'blocks' => $blocks ) ); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; if (!empty($data['update_placement'])) { $smcFunc['db_query']('', ' @@ -301,7 +298,7 @@ private static function updatePriority() ) ); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; } } } @@ -331,10 +328,10 @@ public static function add() $context['sub_template'] = 'block_add'; - if (!isset($_POST['add_block'])) + if (Helpers::post()->has('add_block') === false) return; - $type = (string) $_POST['add_block']; + $type = Helpers::post('add_block', ''); $context['current_block']['type'] = $type; Subs::getForumLanguages(); @@ -378,6 +375,11 @@ public static function edit() $context['sub_template'] = 'block_post'; $context['current_block'] = self::getData($item); + if (Helpers::post()->has('remove')) { + self::remove([$item]); + redirectexit('action=admin;area=lp_blocks;sa=main'); + } + self::validateData(); $context['canonical_url'] = $scripturl . '?action=admin;area=lp_blocks;sa=edit;id=' . $context['lp_block']['id']; @@ -425,7 +427,7 @@ private static function validateData() { global $context, $user_info; - if (isset($_POST['save']) || isset($_POST['preview'])) { + if (Helpers::post()->has('save') || Helpers::post()->has('preview')) { $args = array( 'block_id' => FILTER_VALIDATE_INT, 'icon' => FILTER_SANITIZE_STRING, @@ -472,6 +474,7 @@ private static function validateData() 'placement' => $post_data['placement'] ?? $context['current_block']['placement'] ?? '', 'priority' => $post_data['priority'] ?? $context['current_block']['priority'] ?? 0, 'permissions' => $post_data['permissions'] ?? $context['current_block']['permissions'] ?? ($user_info['is_admin'] ? 0 : 2), + 'status' => $context['current_block']['status'] ?? Block::STATUS_ACTIVE, 'areas' => $post_data['areas'] ?? $context['current_block']['areas'] ?? 'all', 'title_class' => $post_data['title_class'] ?? $context['current_block']['title_class'] ?? '', 'title_style' => $post_data['title_style'] ?? $context['current_block']['title_style'] ?? '', @@ -480,6 +483,10 @@ private static function validateData() 'options' => $options[$context['current_block']['type']] ); + $context['lp_block']['priority'] = empty($context['lp_block']['id']) ? self::getPriority() : $context['lp_block']['priority']; + + $context['lp_block']['content'] = Helpers::getShortenText($context['lp_block']['content']); + if (!empty($context['lp_block']['options']['parameters'])) { foreach ($context['lp_block']['options']['parameters'] as $option => $value) { if (!empty($post_data['parameters'])) { @@ -520,11 +527,11 @@ private static function findErrors(array $data) $areas_format = array( 'options' => array("regexp" => '/' . static::$areas_pattern . '/') ); - if (!empty($data['areas']) && empty(filter_var($data['areas'], FILTER_VALIDATE_REGEXP, $areas_format))) + if (!empty($data['areas']) && empty(Helpers::validate($data['areas'], $areas_format))) $post_errors[] = 'no_valid_areas'; if (!empty($post_errors)) { - $_POST['preview'] = true; + Helpers::post()->put('preview', true); $context['post_errors'] = []; foreach ($post_errors as $error) @@ -738,7 +745,7 @@ private static function prepareFormFields() 'type' => 'textarea', 'attributes' => array( 'id' => 'content', - 'maxlength' => Helpers::getMaxMessageLength(), + 'maxlength' => MAX_MSG_LENGTH, 'value' => $context['lp_block']['content'] ), 'tab' => 'content' @@ -771,7 +778,7 @@ private static function getAreasInfo() { global $context, $txt; - $exampe_areas = array( + $example_areas = array( 'all', 'custom_action', 'pages', @@ -786,7 +793,7 @@ private static function getAreasInfo() 'topic=id3|id7' ); - $context['lp_possible_areas'] = array_combine($exampe_areas, $txt['lp_block_areas_values']); + $context['lp_possible_areas'] = array_combine($example_areas, $txt['lp_block_areas_values']); ob_start(); @@ -847,7 +854,7 @@ private static function preparePreview() { global $context, $smcFunc, $txt; - if (!isset($_POST['preview'])) + if (Helpers::post()->has('preview') === false) return; checkSubmitOnce('free'); @@ -860,8 +867,8 @@ private static function preparePreview() censorText($context['preview_content']); !empty($context['preview_content']) - ? Subs::parseContent($context['preview_content'], $context['lp_block']['type']) - : Subs::prepareContent($context['preview_content'], $context['lp_block']['type'], $context['lp_block']['id']); + ? Helpers::parseContent($context['preview_content'], $context['lp_block']['type']) + : Helpers::prepareContent($context['preview_content'], $context['lp_block']['type'], $context['lp_block']['id']); $context['page_title'] = $txt['preview'] . ($context['preview_title'] ? ' - ' . $context['preview_title'] : ''); $context['preview_title'] = Helpers::getPreviewTitle(Helpers::getIcon()); @@ -891,8 +898,9 @@ private static function getPriority() ); [$priority] = $smcFunc['db_fetch_row']($request); + $smcFunc['db_free_result']($request); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; return (int) $priority; } @@ -909,22 +917,19 @@ private static function setData(int $item = 0) { global $context, $smcFunc; - if (!empty($context['post_errors']) || (!isset($_POST['save']) && !isset($_POST['clone']))) + if (!empty($context['post_errors']) || (Helpers::post()->has('save') === false && Helpers::post()->has('clone') === false)) return; checkSubmitOnce('check'); if (empty($item)) { - $max_length = Helpers::getMaxMessageLength(); - $priority = self::getPriority(); - $item = $smcFunc['db_insert']('', '{db_prefix}lp_blocks', array( 'icon' => 'string-60', 'icon_type' => 'string-10', 'type' => 'string', - 'content' => 'string-' . $max_length, + 'content' => 'string-' . MAX_MSG_LENGTH, 'placement' => 'string-10', 'priority' => 'int', 'permissions' => 'int', @@ -941,9 +946,9 @@ private static function setData(int $item = 0) $context['lp_block']['type'], $context['lp_block']['content'], $context['lp_block']['placement'], - $context['lp_block']['priority'] ?? $priority ?? 0, + $context['lp_block']['priority'], $context['lp_block']['permissions'], - $context['lp_block']['status'] ?? Block::STATUS_ACTIVE, + $context['lp_block']['status'], $context['lp_block']['areas'], $context['lp_block']['title_class'], $context['lp_block']['title_style'], @@ -954,7 +959,7 @@ private static function setData(int $item = 0) 1 ); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; if (!empty($context['lp_block']['title'])) { $titles = []; @@ -979,15 +984,15 @@ private static function setData(int $item = 0) array('item_id', 'type', 'lang') ); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; } if (!empty($context['lp_block']['options']['parameters'])) { - $parameters = []; + $params = []; foreach ($context['lp_block']['options']['parameters'] as $param_name => $value) { $value = is_array($value) ? implode(',', $value) : $value; - $parameters[] = array( + $params[] = array( 'item_id' => $item, 'type' => 'block', 'name' => $param_name, @@ -1003,11 +1008,11 @@ private static function setData(int $item = 0) 'name' => 'string', 'value' => 'string' ), - $parameters, + $params, array('item_id', 'type', 'name') ); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; } } else { $smcFunc['db_query']('', ' @@ -1030,7 +1035,7 @@ private static function setData(int $item = 0) ) ); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; if (!empty($context['lp_block']['title'])) { $titles = []; @@ -1055,15 +1060,15 @@ private static function setData(int $item = 0) array('item_id', 'type', 'lang') ); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; } if (!empty($context['lp_block']['options']['parameters'])) { - $parameters = []; + $params = []; foreach ($context['lp_block']['options']['parameters'] as $param_name => $value) { $value = is_array($value) ? implode(',', $value) : $value; - $parameters[] = array( + $params[] = array( 'item_id' => $item, 'type' => 'block', 'name' => $param_name, @@ -1079,22 +1084,22 @@ private static function setData(int $item = 0) 'name' => 'string', 'value' => 'string' ), - $parameters, + $params, array('item_id', 'type', 'name') ); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; } - Helpers::getFromCache($context['lp_block']['type'] . '_addon_b' . $item, null); - Helpers::getFromCache($context['lp_block']['type'] . '_addon_u' . $context['user']['id'], null); - Helpers::getFromCache($context['lp_block']['type'] . '_addon_b' . $item . '_u' . $context['user']['id'], null); + Helpers::cache()->forget($context['lp_block']['type'] . '_addon_b' . $item); + Helpers::cache()->forget($context['lp_block']['type'] . '_addon_u' . $context['user']['id']); + Helpers::cache()->forget($context['lp_block']['type'] . '_addon_b' . $item . '_u' . $context['user']['id']); } - if (!empty($_POST['clone'])) + if (Helpers::post()->filled('clone')) return $item; - Helpers::getFromCache('active_blocks', null); + Helpers::cache()->forget('active_blocks'); redirectexit('action=admin;area=lp_blocks;sa=main'); } @@ -1109,7 +1114,7 @@ private static function setData(int $item = 0) */ public static function getData(int $item) { - global $smcFunc, $context; + global $smcFunc; if (empty($item)) return []; @@ -1127,8 +1132,10 @@ public static function getData(int $item) ) ); - if ($smcFunc['db_num_rows']($request) == 0) + if ($smcFunc['db_num_rows']($request) == 0) { + self::changeBackButton(); fatal_lang_error('lp_block_not_found', false, null, 404); + } while ($row = $smcFunc['db_fetch_assoc']($request)) { censorText($row['content']); @@ -1158,282 +1165,23 @@ public static function getData(int $item) } $smcFunc['db_free_result']($request); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; return $data ?? []; } /** - * Block export - * - * Экспорт блоков - * - * @return void - */ - public static function export() - { - global $context, $txt, $scripturl; - - loadTemplate('LightPortal/ManageExport'); - - $context['page_title'] = $txt['lp_portal'] . ' - ' . $txt['lp_blocks_export']; - $context['page_area_title'] = $txt['lp_blocks_export']; - $context['canonical_url'] = $scripturl . '?action=admin;area=lp_blocks;sa=export'; - - $context[$context['admin_menu_name']]['tab_data'] = array( - 'title' => LP_NAME, - 'description' => $txt['lp_blocks_export_tab_description'] - ); - - self::runExport(self::getXmlFile()); - - $context['lp_current_blocks'] = self::getAll(); - $context['lp_current_blocks'] = array_merge(array_flip(array_keys($txt['lp_block_placement_set'])), $context['lp_current_blocks']); - - $context['sub_template'] = 'manage_export_blocks'; - } - - /** - * Creating data in XML format - * - * Формируем данные в XML-формате - * - * @return array - */ - private static function getDataForXml() - { - global $smcFunc, $context; - - if (empty($_POST['items'])) - return []; - - $request = $smcFunc['db_query']('', ' - SELECT - b.block_id, b.icon, b.icon_type, b.type, b.content, b.placement, b.priority, b.permissions, b.status, b.areas, b.title_class, b.title_style, b.content_class, b.content_style, - pt.lang, pt.title, pp.name, pp.value - FROM {db_prefix}lp_blocks AS b - LEFT JOIN {db_prefix}lp_titles AS pt ON (b.block_id = pt.item_id AND pt.type = {string:type}) - LEFT JOIN {db_prefix}lp_params AS pp ON (b.block_id = pp.item_id AND pp.type = {string:type}) - WHERE b.block_id IN ({array_int:blocks})', - array( - 'type' => 'block', - 'blocks' => $_POST['items'] - ) - ); - - $items = []; - while ($row = $smcFunc['db_fetch_assoc']($request)) { - if (!isset($items[$row['block_id']])) - $items[$row['block_id']] = array( - 'block_id' => $row['block_id'], - 'icon' => $row['icon'], - 'icon_type' => $row['icon_type'], - 'type' => $row['type'], - 'content' => $row['content'], - 'placement' => $row['placement'], - 'priority' => $row['priority'], - 'permissions' => $row['permissions'], - 'status' => $row['status'], - 'areas' => $row['areas'], - 'title_class' => $row['title_class'], - 'title_style' => $row['title_style'], - 'content_class' => $row['content_class'], - 'content_style' => $row['content_style'] - ); - - if (!empty($row['lang'])) - $items[$row['block_id']]['titles'][$row['lang']] = $row['title']; - - if (!empty($row['name'])) - $items[$row['block_id']]['params'][$row['name']] = $row['value']; - } - - $smcFunc['db_free_result']($request); - $context['lp_num_queries']++; - - return $items; - } - - /** - * Get filename with XML data + * Change back button position and back button href * - * Получаем имя файла с XML-данными - * - * @return string - */ - private static function getXmlFile() - { - $items = self::getDataForXml(); - - if (empty($items)) - return ''; - - $xml = new \DomDocument('1.0', 'utf-8'); - $root = $xml->appendChild($xml->createElement('light_portal')); - - $xml->formatOutput = true; - - $xmlElements = $root->appendChild($xml->createElement('blocks')); - foreach ($items as $item) { - $xmlElement = $xmlElements->appendChild($xml->createElement('item')); - foreach ($item as $key => $val) { - $xmlName = $xmlElement->appendChild(in_array($key, ['block_id', 'priority', 'permissions', 'status']) ? $xml->createAttribute($key) : $xml->createElement($key)); - - if (in_array($key, ['titles', 'params'])) { - foreach ($item[$key] as $k => $v) { - $xmlTitle = $xmlName->appendChild($xml->createElement($k)); - $xmlTitle->appendChild($xml->createTextNode($v)); - } - } elseif ($key == 'content') { - $xmlName->appendChild($xml->createCDATASection($val)); - } else { - $xmlName->appendChild($xml->createTextNode($val)); - } - } - } - - $file = sys_get_temp_dir() . '/lp_blocks_backup.xml'; - $xml->save($file); - - return $file; - } - - /** - * Block import - * - * Импорт блоков + * Меняем положение и href кнопки «Назад» * * @return void */ - public static function import() + private static function changeBackButton() { - global $context, $txt, $scripturl; - - loadTemplate('LightPortal/ManageImport'); - - $context['page_title'] = $txt['lp_portal'] . ' - ' . $txt['lp_blocks_import']; - $context['page_area_title'] = $txt['lp_blocks_import']; - $context['canonical_url'] = $scripturl . '?action=admin;area=lp_blocks;sa=import'; - - $context[$context['admin_menu_name']]['tab_data'] = array( - 'title' => LP_NAME, - 'description' => $txt['lp_blocks_import_tab_description'] - ); - - $context['sub_template'] = 'manage_import'; - - self::runImport(); - } - - /** - * Import from an XML file - * - * Импорт из XML-файла - * - * @return void - */ - private static function runImport() - { - global $smcFunc, $context; - - if (empty($_FILES['import_file'])) - return; - - $file = $_FILES['import_file']; - - if ($file['type'] !== 'text/xml') - return; - - $xml = simplexml_load_file($file['tmp_name']); - - if ($xml === false) - return; - - if (!isset($xml->blocks->item[0]['block_id'])) - fatal_lang_error('lp_wrong_import_file', false); - - $items = $titles = $params = []; - - foreach ($xml as $element) { - foreach ($element->item as $item) { - $items[] = [ - 'block_id' => $block_id = intval($item['block_id']), - 'icon' => $item->icon, - 'icon_type' => $item->icon_type, - 'type' => $item->type, - 'content' => $item->content, - 'placement' => $item->placement, - 'priority' => intval($item['priority']), - 'permissions' => intval($item['permissions']), - 'status' => intval($item['status']), - 'areas' => $item->areas, - 'title_class' => $item->title_class, - 'title_style' => $item->title_style, - 'content_class' => $item->content_class, - 'content_style' => $item->content_style - ]; - - if (!empty($item->titles)) { - foreach ($item->titles as $title) { - foreach ($title as $k => $v) { - $titles[] = [ - 'item_id' => $block_id, - 'type' => 'block', - 'lang' => $k, - 'title' => $v - ]; - } - } - } - - if (!empty($item->params)) { - foreach ($item->params as $param) { - foreach ($param as $k => $v) { - $params[] = [ - 'item_id' => $block_id, - 'type' => 'block', - 'name' => $k, - 'value' => $v - ]; - } - } - } - } - } - - if (!empty($items)) { - $sql = "REPLACE INTO {db_prefix}lp_blocks (`block_id`, `icon`, `icon_type`, `type`, `content`, `placement`, `priority`, `permissions`, `status`, `areas`, `title_class`, `title_style`, `content_class`, `content_style`) - VALUES "; - - $sql .= self::getValues($items); - - $result = $smcFunc['db_query']('', $sql); - $context['lp_num_queries']++; - } - - if (!empty($titles) && !empty($result)) { - $sql = "REPLACE INTO {db_prefix}lp_titles (`item_id`, `type`, `lang`, `title`) - VALUES "; - - $sql .= self::getValues($titles); - - $result = $smcFunc['db_query']('', $sql); - $context['lp_num_queries']++; - } - - if (!empty($params) && !empty($result)) { - $sql = "REPLACE INTO {db_prefix}lp_params (`item_id`, `type`, `name`, `value`) - VALUES "; - - $sql .= self::getValues($params); - - $result = $smcFunc['db_query']('', $sql); - $context['lp_num_queries']++; - } - - if (empty($result)) - fatal_lang_error('lp_import_failed', false); - - clean_cache(); + addInlineJavaScript(' + const backButton = document.querySelector("#fatal_error + .centertext > a.button"); + backButton.setAttribute("href", smf_scripturl + "?action=admin;area=lp_blocks"); + backButton.className = "button floatnone";', true); } } diff --git a/Sources/LightPortal/ManagePages.php b/Sources/LightPortal/ManagePages.php index 44c1a7525..3e904cc3d 100644 --- a/Sources/LightPortal/ManagePages.php +++ b/Sources/LightPortal/ManagePages.php @@ -11,7 +11,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -19,25 +19,23 @@ class ManagePages { - use ShareTools; - /** - * The page name must begin with a Latin letter and may consist of lowercase Latin letters, numbers, and underscore + * Number pages within tables * - * Имя страницы должно начинаться с латинской буквы и может состоять из строчных латинских букв, цифр и знака подчеркивания + * Количество страниц в таблицах * - * @var string + * @var int */ - private static $alias_pattern = '^[a-z][a-z0-9_]+$'; + public static $num_pages = 20; /** - * Number pages within tables + * The page name must begin with a Latin letter and may consist of lowercase Latin letters, numbers, and underscore * - * Количество страниц в таблицах + * Имя страницы должно начинаться с латинской буквы и может состоять из строчных латинских букв, цифр и знака подчеркивания * - * @var int + * @var string */ - private static $num_pages = 20; + private static $alias_pattern = '^[a-z][a-z0-9_]+$'; /** * Manage pages @@ -70,7 +68,7 @@ public static function main() $search_params = $smcFunc['json_decode']($search_params, true); } - $search_params_string = Helpers::request('search', ''); + $search_params_string = trim(Helpers::request('search', '')); $search_params = array( 'string' => $smcFunc['htmlspecialchars']($search_params_string) ); @@ -90,15 +88,15 @@ public static function main() 'get_items' => array( 'function' => __CLASS__ . '::getAll', 'params' => array( - (!empty($search_params['string']) ? ' INSTR(p.alias, {string:quick_search_string}) > 0 OR INSTR(t.title, {string:quick_search_string}) > 0' : ''), - array('quick_search_string' => $search_params['string']) + (!empty($search_params['string']) ? ' INSTR(LOWER(p.alias), {string:quick_search_string}) > 0 OR INSTR(LOWER(t.title), {string:quick_search_string}) > 0' : ''), + array('quick_search_string' => $smcFunc['strtolower']($search_params['string'])) ) ), 'get_count' => array( 'function' => __CLASS__ . '::getTotalQuantity', 'params' => array( - (!empty($search_params['string']) ? ' INSTR(p.alias, {string:quick_search_string}) > 0 OR INSTR(t.title, {string:quick_search_string}) > 0' : ''), - array('quick_search_string' => $search_params['string']) + (!empty($search_params['string']) ? ' INSTR(LOWER(p.alias), {string:quick_search_string}) > 0 OR INSTR(LOWER(t.title), {string:quick_search_string}) > 0' : ''), + array('quick_search_string' => $smcFunc['strtolower']($search_params['string'])) ) ), 'columns' => array( @@ -178,8 +176,13 @@ public static function main() 'data' => array( 'function' => function ($entry) use ($scripturl) { - $title = Helpers::getPublicTitle($entry); - return '' . $title . ''; + $title = Helpers::getTitle($entry); + + return '' . $title . ''; }, 'class' => 'word_break' ), @@ -292,9 +295,9 @@ public static function main() */ public static function getAll(int $start, int $items_per_page, string $sort, string $query_string = '', array $query_params = []) { - global $smcFunc, $user_info, $context; + global $smcFunc, $user_info; - $titles = Helpers::getFromCache('all_titles', 'getAllTitles', '\Bugo\LightPortal\Subs', LP_CACHE_TIME, 'page'); + $titles = Helpers::cache('all_titles', 'getAllTitles', '\Bugo\LightPortal\Subs', LP_CACHE_TIME, 'page'); $request = $smcFunc['db_query']('', ' SELECT p.page_id, p.author_id, p.alias, p.type, p.permissions, p.status, p.num_views, GREATEST(p.created_at, p.updated_at) AS date, mem.real_name AS author_name @@ -333,7 +336,7 @@ public static function getAll(int $start, int $items_per_page, string $sort, str } $smcFunc['db_free_result']($request); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; return $items; } @@ -349,7 +352,7 @@ public static function getAll(int $start, int $items_per_page, string $sort, str */ public static function getTotalQuantity(string $query_string = '', array $query_params = []) { - global $smcFunc, $user_info, $context; + global $smcFunc, $user_info; $request = $smcFunc['db_query']('', ' SELECT COUNT(p.page_id) @@ -366,8 +369,9 @@ public static function getTotalQuantity(string $query_string = '', array $query_ ); [$num_entries] = $smcFunc['db_fetch_row']($request); + $smcFunc['db_free_result']($request); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; return (int) $num_entries; } @@ -397,7 +401,8 @@ private static function doActions() self::toggleStatus([$item], $status == 'off' ? Page::STATUS_ACTIVE : Page::STATUS_INACTIVE); } - clean_cache(); + Helpers::cache()->flush(); + exit; } @@ -411,7 +416,7 @@ private static function doActions() */ private static function remove(array $items) { - global $smcFunc, $context; + global $smcFunc; if (empty($items)) return; @@ -435,20 +440,20 @@ private static function remove(array $items) ); $smcFunc['db_query']('', ' - DELETE FROM {db_prefix}lp_params - WHERE item_id IN ({array_int:items}) - AND type = {string:type}', + DELETE FROM {db_prefix}lp_comments + WHERE page_id IN ({array_int:items})', array( - 'items' => $items, - 'type' => 'page' + 'items' => $items ) ); $smcFunc['db_query']('', ' - DELETE FROM {db_prefix}lp_comments - WHERE page_id IN ({array_int:items})', + DELETE FROM {db_prefix}lp_params + WHERE item_id IN ({array_int:items}) + AND type = {string:type}', array( - 'items' => $items + 'items' => $items, + 'type' => 'page' ) ); @@ -460,9 +465,9 @@ private static function remove(array $items) ) ); - Subs::runAddons('onRemovePages', array(&$items)); + Subs::runAddons('onPageRemoving', array(&$items)); - $context['lp_num_queries'] += 5; + $smcFunc['lp_num_queries'] += 5; } /** @@ -501,19 +506,21 @@ public static function toggleStatus(array $items, int $status = 0) */ public static function massActions() { - if (!isset($_POST['mass_actions']) || empty($_POST['items'])) + if (Helpers::post()->has('mass_actions') === false || Helpers::post()->isEmpty('items')) return; $redirect = filter_input(INPUT_SERVER, 'HTTP_REFERER', FILTER_DEFAULT, array('options' => array('default' => 'action=admin;area=lp_pages'))); - $items = $_POST['items']; + $items = Helpers::post('items'); switch (filter_input(INPUT_POST, 'page_actions')) { case 'delete': self::remove($items); break; + case 'action_on': self::toggleStatus($items, Page::STATUS_ACTIVE); break; + case 'action_off': self::toggleStatus($items); break; @@ -590,6 +597,11 @@ public static function edit() Subs::getForumLanguages(); + if (Helpers::post()->has('remove')) { + self::remove([$item]); + redirectexit('action=admin;area=lp_pages;sa=main'); + } + self::validateData(); $page_title = $context['lp_page']['title'][$context['user']['language']] ?? ''; @@ -635,7 +647,7 @@ private static function validateData() { global $context, $modSettings, $user_info; - if (isset($_POST['save']) || isset($_POST['preview'])) { + if (Helpers::post()->has('save') || Helpers::post()->has('preview')) { $args = array( 'alias' => FILTER_SANITIZE_STRING, 'description' => FILTER_SANITIZE_STRING, @@ -664,7 +676,7 @@ private static function validateData() ); $post_data = filter_input_array(INPUT_POST, array_merge($args, $parameters)); - $post_data['id'] = !empty($_GET['id']) ? (int) $_GET['id'] : 0; + $post_data['id'] = Helpers::request('id', 0); self::findErrors($post_data); } @@ -672,8 +684,11 @@ private static function validateData() $options = self::getOptions(); $page_options = $context['lp_current_page']['options'] ?? $options; - if (!empty($context['lp_current_page']['keywords'])) + if (!empty($context['lp_current_page']['keywords'])) { $context['lp_current_page']['keywords'] = implode(', ', $context['lp_current_page']['keywords']); + } else { + $context['lp_current_page']['keywords'] = ''; + } $context['lp_page'] = array( 'id' => $post_data['id'] ?? $context['lp_current_page']['id'] ?? 0, @@ -691,6 +706,8 @@ private static function validateData() 'options' => $options ); + $context['lp_page']['content'] = Helpers::getShortenText($context['lp_page']['content']); + foreach ($context['lp_page']['options'] as $option => $value) { if (!empty($parameters[$option]) && $parameters[$option] == FILTER_VALIDATE_BOOLEAN && !empty($post_data) && $post_data[$option] === null) { $post_data[$option] = 0; @@ -728,7 +745,7 @@ private static function findErrors(array $data) $alias_format = array( 'options' => array("regexp" => '/' . static::$alias_pattern . '/') ); - if (!empty($data['alias']) && empty(filter_var($data['alias'], FILTER_VALIDATE_REGEXP, $alias_format))) + if (!empty($data['alias']) && empty(Helpers::validate($data['alias'], $alias_format))) $post_errors[] = 'no_valid_alias'; if (!empty($data['alias']) && self::isUnique($data)) @@ -738,7 +755,7 @@ private static function findErrors(array $data) $post_errors[] = 'no_content'; if (!empty($post_errors)) { - $_POST['preview'] = true; + Helpers::post()->put('preview', true); $context['post_errors'] = []; foreach ($post_errors as $error) @@ -746,6 +763,24 @@ private static function findErrors(array $data) } } + /** + * https://github.com/jshjohnson/Choices + * + * @return void + */ + private static function improveKeywordsField() + { + loadCssFile('https://cdn.jsdelivr.net/npm/choices.js/public/assets/styles/choices.min.css', array('external' => true)); + + addInlineCss(' + .choices__list { + position: relative; + } + .choices__input { + box-shadow: none; + }'); + } + /** * Adding special fields to the form * @@ -827,14 +862,16 @@ private static function prepareFormFields() 'tab' => 'seo' ); + self::improveKeywordsField(); + $context['posting_fields']['keywords']['label']['text'] = $txt['lp_page_keywords']; - $context['posting_fields']['keywords']['label']['after'] = '
' . $txt['lp_page_keywords_after'] . ''; $context['posting_fields']['keywords']['input'] = array( - 'type' => 'textarea', + 'type' => 'text', 'attributes' => array( - 'id' => 'keywords', - 'maxlength' => 255, - 'value' => $context['lp_page']['keywords'] + 'id' => 'keywords', + 'value' => $context['lp_page']['keywords'], + 'style' => 'width: 100%', + 'dir' => $context['right_to_left'] ? 'rtl' : 'ltr' ), 'tab' => 'seo' ); @@ -875,7 +912,7 @@ private static function prepareFormFields() 'type' => 'textarea', 'attributes' => array( 'id' => 'content', - 'maxlength' => Helpers::getMaxMessageLength(), + 'maxlength' => MAX_MSG_LENGTH, 'value' => $context['lp_page']['content'], 'required' => true ), @@ -952,7 +989,7 @@ private static function preparePreview() { global $context, $smcFunc, $txt; - if (!isset($_POST['preview'])) + if (Helpers::post()->has('preview') === false) return; checkSubmitOnce('free'); @@ -965,7 +1002,7 @@ private static function preparePreview() censorText($context['preview_content']); if (!empty($context['preview_content'])) - Subs::parseContent($context['preview_content'], $context['lp_page']['type']); + Helpers::parseContent($context['preview_content'], $context['lp_page']['type']); $context['page_title'] = $txt['preview'] . ($context['preview_title'] ? ' - ' . $context['preview_title'] : ''); $context['preview_title'] = Helpers::getPreviewTitle(); @@ -1025,7 +1062,7 @@ private static function setData(int $item = 0) { global $context, $smcFunc, $db_type; - if (!empty($context['post_errors']) || !isset($_POST['save'])) + if (!empty($context['post_errors']) || Helpers::post()->has('save') === false) return; checkSubmitOnce('check'); @@ -1039,7 +1076,7 @@ private static function setData(int $item = 0) 'author_id' => 'int', 'alias' => 'string-255', 'description' => 'string-255', - 'content' => 'string-' . Helpers::getMaxMessageLength(), + 'content' => 'string-' . MAX_MSG_LENGTH, 'type' => 'string-4', 'permissions' => 'int', 'status' => 'int', @@ -1059,9 +1096,9 @@ private static function setData(int $item = 0) 1 ); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; - Subs::runAddons('onDataSaving', array($item)); + Subs::runAddons('onPageSaving', array($item)); if (!empty($context['lp_page']['title'])) { $titles = []; @@ -1086,15 +1123,15 @@ private static function setData(int $item = 0) array('item_id', 'type', 'lang') ); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; } if (!empty($context['lp_page']['options'])) { - $parameters = []; + $params = []; foreach ($context['lp_page']['options'] as $param_name => $value) { $value = is_array($value) ? implode(',', $value) : $value; - $parameters[] = array( + $params[] = array( 'item_id' => $item, 'type' => 'page', 'name' => $param_name, @@ -1110,17 +1147,17 @@ private static function setData(int $item = 0) 'name' => 'string', 'value' => 'string' ), - $parameters, + $params, array('item_id', 'type', 'name') ); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; } if (!empty($context['lp_page']['keywords'])) { - $keywords = []; + $tags = []; foreach ($context['lp_page']['keywords'] as $value) { - $keywords[] = array( + $tags[] = array( 'page_id' => $item, 'value' => $value ); @@ -1132,11 +1169,11 @@ private static function setData(int $item = 0) 'page_id' => 'int', 'value' => 'string' ), - $keywords, + $tags, array('page_id', 'value') ); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; } } else { $smcFunc['db_query']('', ' @@ -1156,9 +1193,9 @@ private static function setData(int $item = 0) ) ); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; - Subs::runAddons('onDataSaving', array($item)); + Subs::runAddons('onPageSaving', array($item)); if (!empty($context['lp_page']['title'])) { $titles = []; @@ -1183,15 +1220,15 @@ private static function setData(int $item = 0) array('item_id', 'type', 'lang') ); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; } if (!empty($context['lp_page']['options'])) { - $parameters = []; + $params = []; foreach ($context['lp_page']['options'] as $param_name => $value) { $value = is_array($value) ? implode(',', $value) : $value; - $parameters[] = array( + $params[] = array( 'item_id' => $item, 'type' => 'page', 'name' => $param_name, @@ -1207,11 +1244,11 @@ private static function setData(int $item = 0) 'name' => 'string', 'value' => 'string' ), - $parameters, + $params, array('item_id', 'type', 'name') ); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; } $smcFunc['db_query']('', ' @@ -1222,12 +1259,12 @@ private static function setData(int $item = 0) ) ); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; if (!empty($context['lp_page']['keywords'])) { - $keywords = []; + $tags = []; foreach ($context['lp_page']['keywords'] as $value) { - $keywords[] = array( + $tags[] = array( 'page_id' => $item, 'value' => $value ); @@ -1239,15 +1276,16 @@ private static function setData(int $item = 0) 'page_id' => 'int', 'value' => 'string' ), - $keywords, + $tags, array('page_id', 'value') ); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; } } - clean_cache(); + Helpers::cache()->flush(); + redirectexit('action=admin;area=lp_pages;sa=main'); } @@ -1260,12 +1298,13 @@ private static function setData(int $item = 0) */ private static function getAutoIncrementValue() { - global $smcFunc, $context; + global $smcFunc; $request = $smcFunc['db_query']('', 'SELECT setval(\'{db_prefix}lp_pages_seq\', (SELECT MAX(page_id) FROM {db_prefix}lp_pages))'); [$value] = $smcFunc['db_fetch_row']($request); + $smcFunc['db_free_result']($request); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; return (int) $value + 1; } @@ -1280,7 +1319,7 @@ private static function getAutoIncrementValue() */ private static function isUnique(array $data) { - global $smcFunc, $context; + global $smcFunc; $request = $smcFunc['db_query']('', ' SELECT COUNT(page_id) @@ -1294,470 +1333,10 @@ private static function isUnique(array $data) ); [$count] = $smcFunc['db_fetch_row']($request); - $smcFunc['db_free_result']($request); - $context['lp_num_queries']++; - - return (bool) $count; - } - - /** - * Page export - * - * Экспорт страниц - * - * @return void - */ - public static function export() - { - global $context, $txt, $scripturl, $sourcedir; - - $context['page_title'] = $txt['lp_portal'] . ' - ' . $txt['lp_pages_export']; - $context['page_area_title'] = $txt['lp_pages_export']; - $context['canonical_url'] = $scripturl . '?action=admin;area=lp_pages;sa=export'; - - $context[$context['admin_menu_name']]['tab_data'] = array( - 'title' => LP_NAME, - 'description' => $txt['lp_pages_export_tab_description'] - ); - - self::runExport(self::getXmlFile()); - - $listOptions = array( - 'id' => 'pages', - 'items_per_page' => self::$num_pages, - 'title' => $txt['lp_pages_export'], - 'no_items_label' => $txt['lp_no_items'], - 'base_href' => $scripturl . '?action=admin;area=lp_pages;sa=export', - 'default_sort_col' => 'id', - 'get_items' => array( - 'function' => __CLASS__ . '::getAll' - ), - 'get_count' => array( - 'function' => __CLASS__ . '::getTotalQuantity' - ), - 'columns' => array( - 'id' => array( - 'header' => array( - 'value' => '#', - 'style' => 'width: 5%' - ), - 'data' => array( - 'db' => 'id', - 'class' => 'centertext' - ), - 'sort' => array( - 'default' => 'p.page_id', - 'reverse' => 'p.page_id DESC' - ) - ), - 'alias' => array( - 'header' => array( - 'value' => $txt['lp_page_alias'] - ), - 'data' => array( - 'db' => 'alias', - 'class' => 'centertext word_break' - ), - 'sort' => array( - 'default' => 'p.alias DESC', - 'reverse' => 'p.alias' - ) - ), - 'title' => array( - 'header' => array( - 'value' => $txt['lp_title'] - ), - 'data' => array( - 'function' => function ($entry) use ($scripturl) - { - $title = Helpers::getPublicTitle($entry); - - return '' . $title . ''; - }, - 'class' => 'word_break' - ), - 'sort' => array( - 'default' => 't.title DESC', - 'reverse' => 't.title' - ) - ), - 'actions' => array( - 'header' => array( - 'value' => '' - ), - 'data' => array( - 'function' => function ($entry) - { - return ''; - }, - 'class' => 'centertext' - ) - ) - ), - 'form' => array( - 'href' => $scripturl . '?action=admin;area=lp_pages;sa=export' - ), - 'additional_rows' => array( - array( - 'position' => 'below_table_data', - 'value' => ' - - ', - 'class' => 'floatright' - ) - ) - ); - - require_once($sourcedir . '/Subs-List.php'); - createList($listOptions); - - $context['sub_template'] = 'show_list'; - $context['default_list'] = 'pages'; - } - - /** - * Creating data in XML format - * - * Формируем данные в XML-формате - * - * @return mixed - */ - private static function getDataForXml() - { - global $smcFunc, $context; - - if (empty($_POST['pages']) && !isset($_POST['export_all'])) - return false; - - $pages = !empty($_POST['pages']) && !isset($_POST['export_all']) ? $_POST['pages'] : null; - - $request = $smcFunc['db_query']('', ' - SELECT - p.page_id, p.author_id, p.alias, p.description, p.content, p.type, p.permissions, p.status, p.num_views, p.num_comments, p.created_at, p.updated_at, - pt.lang, pt.title, pp.name, pp.value, t.value AS keyword, com.id, com.parent_id, com.author_id AS com_author_id, com.message, com.created_at AS com_created_at - FROM {db_prefix}lp_pages AS p - LEFT JOIN {db_prefix}lp_titles AS pt ON (p.page_id = pt.item_id AND pt.type = {string:type}) - LEFT JOIN {db_prefix}lp_params AS pp ON (p.page_id = pp.item_id AND pp.type = {string:type}) - LEFT JOIN {db_prefix}lp_tags AS t ON (p.page_id = t.page_id) - LEFT JOIN {db_prefix}lp_comments AS com ON (p.page_id = com.page_id)' . (!empty($pages) ? ' - WHERE p.page_id IN ({array_int:pages})' : ''), - array( - 'type' => 'page', - 'pages' => $pages - ) - ); - - $items = []; - while ($row = $smcFunc['db_fetch_assoc']($request)) { - if (!isset($items[$row['page_id']])) - $items[$row['page_id']] = array( - 'page_id' => $row['page_id'], - 'author_id' => $row['author_id'], - 'alias' => $row['alias'], - 'description' => trim($row['description']), - 'content' => $row['content'], - 'type' => $row['type'], - 'permissions' => $row['permissions'], - 'status' => $row['status'], - 'num_views' => $row['num_views'], - 'num_comments' => $row['num_comments'], - 'created_at' => $row['created_at'], - 'updated_at' => $row['updated_at'] - ); - - if (!empty($row['lang'])) - $items[$row['page_id']]['titles'][$row['lang']] = $row['title']; - - if (!empty($row['name'])) - $items[$row['page_id']]['params'][$row['name']] = $row['value']; - - if (!empty($row['keyword'])) - $items[$row['page_id']]['keywords'][] = $row['keyword']; - - if (!empty($row['message'])) { - $items[$row['page_id']]['comments'][$row['id']] = array( - 'id' => $row['id'], - 'parent_id' => $row['parent_id'], - 'author_id' => $row['com_author_id'], - 'message' => trim($row['message']), - 'created_at' => $row['com_created_at'] - ); - } - } $smcFunc['db_free_result']($request); - $context['lp_num_queries']++; - - return $items; - } - - /** - * Get filename with XML data - * - * Получаем имя файла с XML-данными - * - * @return string - */ - private static function getXmlFile() - { - $items = self::getDataForXml(); - - if (empty($items)) - return ''; - - $xml = new \DomDocument('1.0', 'utf-8'); - $root = $xml->appendChild($xml->createElement('light_portal')); - - $xml->formatOutput = true; - - $xmlElements = $root->appendChild($xml->createElement('pages')); - foreach ($items as $item) { - $xmlElement = $xmlElements->appendChild($xml->createElement('item')); - foreach ($item as $key => $val) { - $xmlName = $xmlElement->appendChild(in_array($key, ['page_id', 'author_id', 'permissions', 'status', 'num_views', 'num_comments', 'created_at', 'updated_at']) ? $xml->createAttribute($key) : $xml->createElement($key)); - - if (in_array($key, ['titles', 'params'])) { - foreach ($item[$key] as $k => $v) { - $xmlTitle = $xmlName->appendChild($xml->createElement($k)); - $xmlTitle->appendChild($xml->createTextNode($v)); - } - } elseif (in_array($key, ['description', 'content'])) { - $xmlName->appendChild($xml->createCDATASection($val)); - } elseif ($key == 'keywords' && !empty($val)) { - $xmlName->appendChild($xml->createTextNode(implode(', ', array_unique($val)))); - } elseif ($key == 'comments') { - foreach ($item[$key] as $k => $comment) { - $xmlComment = $xmlName->appendChild($xml->createElement('comment')); - foreach ($comment as $label => $text) { - $xmlCommentElem = $xmlComment->appendChild($label == 'message' ? $xml->createElement($label) : $xml->createAttribute($label)); - $xmlCommentElem->appendChild($label == 'message' ? $xml->createCDATASection($text) : $xml->createTextNode($text)); - } - } - } else { - $xmlName->appendChild($xml->createTextNode($val)); - } - } - } - - $file = sys_get_temp_dir() . '/lp_pages_backup.xml'; - $xml->save($file); - - return $file; - } - - /** - * Page import - * - * Импорт страниц - * - * @return void - */ - public static function import() - { - global $context, $txt, $scripturl; - - loadTemplate('LightPortal/ManageImport'); + $smcFunc['lp_num_queries']++; - $context['page_title'] = $txt['lp_portal'] . ' - ' . $txt['lp_pages_import']; - $context['page_area_title'] = $txt['lp_pages_import']; - $context['canonical_url'] = $scripturl . '?action=admin;area=lp_pages;sa=import'; - - $context[$context['admin_menu_name']]['tab_data'] = array( - 'title' => LP_NAME, - 'description' => $txt['lp_pages_import_tab_description'] - ); - - $context['sub_template'] = 'manage_import'; - - self::runImport(); - } - - /** - * Import from an XML file - * - * Импорт из XML-файла - * - * @return void - */ - private static function runImport() - { - global $db_temp_cache, $db_cache, $smcFunc, $context; - - if (empty($_FILES['import_file'])) - return; - - // Might take some time. - @set_time_limit(600); - - // Don't allow the cache to get too full - $db_temp_cache = $db_cache; - $db_cache = []; - - $file = $_FILES['import_file']; - - if ($file['type'] !== 'text/xml') - return; - - $xml = simplexml_load_file($file['tmp_name']); - - if ($xml === false) - return; - - if (!isset($xml->pages->item[0]['page_id'])) - fatal_lang_error('lp_wrong_import_file', false); - - $items = $titles = $params = $keywords = $comments = []; - - foreach ($xml as $element) { - foreach ($element->item as $item) { - $items[] = [ - 'page_id' => $page_id = intval($item['page_id']), - 'author_id' => intval($item['author_id']), - 'alias' => (string) $item->alias, - 'description' => $item->description, - 'content' => $item->content, - 'type' => (string) $item->type, - 'permissions' => intval($item['permissions']), - 'status' => intval($item['status']), - 'num_views' => intval($item['num_views']), - 'num_comments' => intval($item['num_comments']), - 'created_at' => intval($item['created_at']), - 'updated_at' => intval($item['updated_at']) - ]; - - if (!empty($item->titles)) { - foreach ($item->titles as $title) { - foreach ($title as $k => $v) { - $titles[] = [ - 'item_id' => $page_id, - 'type' => 'page', - 'lang' => $k, - 'title' => $v - ]; - } - } - } - - if (!empty($item->params)) { - foreach ($item->params as $param) { - foreach ($param as $k => $v) { - $params[] = [ - 'item_id' => $page_id, - 'type' => 'page', - 'name' => $k, - 'value' => intval($v) - ]; - } - } - } - - if (!empty($item->keywords)) { - foreach (explode(', ', $item->keywords) as $value) { - $keywords[] = [ - 'page_id' => $page_id, - 'value' => $value - ]; - } - } - - if (!empty($item->comments)) { - foreach ($item->comments as $comment) { - foreach ($comment as $k => $v) { - $comments[] = [ - 'id' => $v['id'], - 'parent_id' => $v['parent_id'], - 'page_id' => $page_id, - 'author_id' => $v['author_id'], - 'message' => $v->message, - 'created_at' => $v['created_at'] - ]; - } - } - } - } - } - - if (!empty($items)) { - $items = array_chunk($items, 100); - $count = sizeof($items); - - for ($i = 0; $i < $count; $i++) { - $sql = "REPLACE INTO {db_prefix}lp_pages (`page_id`, `author_id`, `alias`, `description`, `content`, `type`, `permissions`, `status`, `num_views`, `num_comments`, `created_at`, `updated_at`) - VALUES "; - - $sql .= self::getValues($items[$i]); - - $result = $smcFunc['db_query']('', $sql); - $context['lp_num_queries']++; - } - } - - if (!empty($titles) && !empty($result)) { - $titles = array_chunk($titles, 100); - $count = sizeof($titles); - - for ($i = 0; $i < $count; $i++) { - $sql = "REPLACE INTO {db_prefix}lp_titles (`item_id`, `type`, `lang`, `title`) - VALUES "; - - $sql .= self::getValues($titles[$i]); - - $result = $smcFunc['db_query']('', $sql); - $context['lp_num_queries']++; - } - } - - if (!empty($params) && !empty($result)) { - $params = array_chunk($params, 100); - $count = sizeof($params); - - for ($i = 0; $i < $count; $i++) { - $sql = "REPLACE INTO {db_prefix}lp_params (`item_id`, `type`, `name`, `value`) - VALUES "; - - $sql .= self::getValues($params[$i]); - - $result = $smcFunc['db_query']('', $sql); - $context['lp_num_queries']++; - } - } - - if (!empty($keywords) && !empty($result)) { - $keywords = array_chunk($keywords, 100); - $count = sizeof($keywords); - - for ($i = 0; $i < $count; $i++) { - $sql = "REPLACE INTO {db_prefix}lp_tags (`page_id`, `value`) - VALUES "; - - $sql .= self::getValues($keywords[$i]); - - $result = $smcFunc['db_query']('', $sql); - $context['lp_num_queries']++; - } - } - - if (!empty($comments) && !empty($result)) { - $comments = array_chunk($comments, 100); - $count = sizeof($comments); - - for ($i = 0; $i < $count; $i++) { - $sql = "REPLACE INTO {db_prefix}lp_comments (`id`, `parent_id`, `page_id`, `author_id`, `message`, `created_at`) - VALUES "; - - $sql .= self::getValues($comments[$i]); - - $result = $smcFunc['db_query']('', $sql); - $context['lp_num_queries']++; - } - } - - if (empty($result)) - fatal_lang_error('lp_import_failed', false); - - // Restore the cache - $db_cache = $db_temp_cache; - - clean_cache(); + return (bool) $count; } } diff --git a/Sources/LightPortal/Notify.php b/Sources/LightPortal/Notify.php index f30b4c07d..8894a303d 100644 --- a/Sources/LightPortal/Notify.php +++ b/Sources/LightPortal/Notify.php @@ -11,7 +11,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ class Notify extends \SMF_BackgroundTask @@ -25,7 +25,7 @@ class Notify extends \SMF_BackgroundTask */ public function execute() { - global $sourcedir, $user_profile, $smcFunc, $context; + global $sourcedir, $user_profile, $smcFunc; require_once($sourcedir . '/Subs-Members.php'); $members = membersAllowedTo('light_portal_view'); @@ -57,10 +57,12 @@ public function execute() foreach ($prefs as $member => $pref_option) { foreach ($alert_bits as $type => $bitvalue) { if ($this->_details['content_type'] == 'new_comment') { - if ($pref_option['page_comment'] & $bitvalue) + if ($pref_option['page_comment'] & $bitvalue) { $notifies[$type][] = $member; - } elseif ($pref_option['page_comment_reply'] & $bitvalue) + } + } elseif ($pref_option['page_comment_reply'] & $bitvalue) { $notifies[$type][] = $member; + } } } @@ -98,7 +100,7 @@ public function execute() array('id_alert') ); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; updateMemberData($notifies['alert'], array('alerts' => '+')); } diff --git a/Sources/LightPortal/Page.php b/Sources/LightPortal/Page.php index 45dd7496e..c69f5a312 100644 --- a/Sources/LightPortal/Page.php +++ b/Sources/LightPortal/Page.php @@ -11,7 +11,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -35,7 +35,7 @@ public static function show() isAllowedTo('light_portal_view'); - $alias = filter_input(INPUT_GET, 'page'); + $alias = Helpers::request('page'); if (empty($alias) && !empty($modSettings['lp_frontpage_mode']) && $modSettings['lp_frontpage_mode'] == 1 && !empty($modSettings['lp_frontpage_alias'])) { $context['lp_page'] = self::getDataByAlias($modSettings['lp_frontpage_alias']); @@ -62,17 +62,17 @@ public static function show() if ($context['lp_page']['created_at'] > time()) send_http_status(404); - Subs::parseContent($context['lp_page']['content'], $context['lp_page']['type']); + Helpers::parseContent($context['lp_page']['content'], $context['lp_page']['type']); if (empty($alias)) { - $context['page_title'] = Helpers::getPublicTitle($context['lp_page']) ?: $txt['lp_portal']; + $context['page_title'] = Helpers::getTitle($context['lp_page']) ?: $txt['lp_portal']; $context['canonical_url'] = $scripturl; $context['lp_current_page_url'] = $context['canonical_url'] . '?'; $context['linktree'][] = array( 'name' => $txt['lp_portal'] ); } else { - $context['page_title'] = Helpers::getPublicTitle($context['lp_page']) ?: $txt['lp_post_error_no_title']; + $context['page_title'] = Helpers::getTitle($context['lp_page']) ?: $txt['lp_post_error_no_title']; $context['canonical_url'] = $scripturl . '?page=' . $alias; $context['lp_current_page_url'] = $context['canonical_url'] . ';'; $context['linktree'][] = array( @@ -170,19 +170,30 @@ public static function getRelatedPages() if (empty($item = $context['lp_page'])) return []; + $title_words = explode(' ', $title = Helpers::getTitle($item)); + $alias_words = explode('_', $item['alias']); + + $search_formula = ''; + foreach ($title_words as $key => $word) { + $search_formula .= ($search_formula ? ' + ' : '') . 'CASE WHEN lower(t.title) LIKE lower(\'%' . $word . '%\') THEN ' . (count($title_words) - $key) * 2 . ' ELSE 0 END'; + } + + foreach ($alias_words as $key => $word) { + $search_formula .= ' + CASE WHEN lower(p.alias) LIKE lower(\'%' . $word . '%\') THEN ' . (count($alias_words) - $key) . ' ELSE 0 END'; + } + $request = $smcFunc['db_query']('', ' - SELECT p.page_id, p.alias, p.content, p.type, (IF (t.title LIKE {string:title}, 80, 0) + IF (p.alias LIKE {string:alias}, 20, 0)) AS related, t.title + SELECT p.page_id, p.alias, p.content, p.type, (' . $search_formula . ') AS related, t.title FROM {db_prefix}lp_pages AS p LEFT JOIN {db_prefix}lp_titles AS t ON (p.page_id = t.item_id AND t.lang = {string:current_lang}) - WHERE p.status = {int:status} + WHERE (' . $search_formula . ') > 0 + AND p.status = {int:status} AND p.created_at <= {int:current_time} AND p.permissions IN ({array_int:permissions}) AND p.page_id != {int:current_page} - HAVING related > 0 - ORDER BY related DESC', + ORDER BY related DESC + LIMIT 4', array( - 'title' => Helpers::getPublicTitle($context['lp_page']), - 'alias' => $item['alias'], 'current_lang' => $context['user']['language'], 'status' => 1, 'current_time' => time(), @@ -196,7 +207,7 @@ public static function getRelatedPages() if (Helpers::isFrontpage($row['alias'])) continue; - Subs::parseContent($row['content'], $row['type']); + Helpers::parseContent($row['content'], $row['type']); $first_post_image = preg_match('/ $alias)); + $data = Helpers::cache('page_' . $alias, 'getData', __CLASS__, LP_CACHE_TIME, array('alias' => $alias)); self::prepareData($data); return $data; @@ -416,7 +427,7 @@ private static function updateNumViews() ); Helpers::session()->put('light_portal_last_page_viewed', $context['lp_page']['id']); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; } } } diff --git a/Sources/LightPortal/Settings.php b/Sources/LightPortal/Settings.php index eab6ac116..707d1ee75 100644 --- a/Sources/LightPortal/Settings.php +++ b/Sources/LightPortal/Settings.php @@ -11,7 +11,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -157,7 +157,11 @@ public static function settingArea() 'description' => sprintf($txt['lp_panels_info'], LP_NAME, 'https://evgenyrodionov.github.io/flexboxgrid2/') ), 'plugins' => array( - 'description' => sprintf($txt['lp_plugins_info'], 'https://github.com/dragomano/Light-Portal/wiki/How-to-create-an-addon') + 'description' => sprintf( + $txt['lp_plugins_info'], + 'https://github.com/dragomano/Light-Portal/wiki/How-to-create-an-addon', + 'https://github.com/dragomano/Light-Portal/wiki/Addon-list-for-sponsors' + ) ) ) ); @@ -179,9 +183,6 @@ public static function basic(bool $return_config = false) require_once($sourcedir . '/ManageServer.php'); - addInlineJavaScript(' - $("p.information").removeClass("information").toggleClass("infobox");', true); - self::checkNewVersion(); $context['page_title'] = $context['settings_title'] = $txt['lp_base']; @@ -199,6 +200,8 @@ public static function basic(bool $return_config = false) $add_settings['lp_frontpage_title'] = $context['forum_name']; if (!isset($modSettings['lp_frontpage_alias'])) $add_settings['lp_frontpage_alias'] = 'home'; + if (!isset($modSettings['lp_frontpage_article_sorting'])) + $add_settings['lp_frontpage_article_sorting'] = 1; if (!isset($modSettings['lp_teaser_size'])) $add_settings['lp_teaser_size'] = 255; if (!isset($modSettings['lp_num_items_per_page'])) @@ -217,11 +220,11 @@ public static function basic(bool $return_config = false) array('boards', 'lp_frontpage_boards'), array('check', 'lp_show_images_in_articles'), array('text', 'lp_image_placeholder', '80" placeholder="' . $txt['lp_example'] . $settings['default_images_url'] . '/smflogo.svg'), - array('check', 'lp_frontpage_card_alt_layout'), + array('check', 'lp_frontpage_card_alt_layout', 'help' => 'lp_frontpage_card_alt_layout_help'), array('check', 'lp_frontpage_order_by_num_replies'), - array('select', 'lp_frontpage_article_sorting', $txt['lp_frontpage_article_sorting_set']), + array('select', 'lp_frontpage_article_sorting', $txt['lp_frontpage_article_sorting_set'], 'help' => 'lp_frontpage_article_sorting_help'), array('select', 'lp_frontpage_layout', $txt['lp_frontpage_layout_set']), - //array('int', 'lp_teaser_size', 'min' => 0), + array('int', 'lp_teaser_size', 'min' => 0, 'help' => 'lp_teaser_size_help'), array('int', 'lp_num_items_per_page'), array('title', 'lp_standalone_mode_title'), array('check', 'lp_standalone_mode'), @@ -245,7 +248,7 @@ public static function basic(bool $return_config = false) array('permissions', 'light_portal_manage_own_pages', 'help' => 'permissionhelp_light_portal_manage_own_pages'), array('permissions', 'light_portal_approve_pages', 'help' => 'permissionhelp_light_portal_approve_pages'), array('title', 'lp_debug_and_caching'), - array('check', 'lp_show_debug_info'), + array('check', 'lp_show_debug_info', 'help' => 'lp_show_debug_info_help'), array('int', 'lp_cache_update_interval', 'postinput' => $txt['seconds']) ); @@ -253,13 +256,13 @@ public static function basic(bool $return_config = false) return $config_vars; // Frontpage mode toggle - $frontpage_mode_toggle = array('lp_frontpage_title', 'lp_frontpage_alias', 'lp_frontpage_boards', 'lp_show_images_in_articles', 'lp_image_placeholder', 'lp_frontpage_card_alt_layout', 'lp_frontpage_order_by_num_replies', 'lp_frontpage_layout', 'lp_num_items_per_page'); + $frontpage_mode_toggle = array('lp_frontpage_title', 'lp_frontpage_alias', 'lp_frontpage_boards', 'lp_show_images_in_articles', 'lp_image_placeholder', 'lp_frontpage_card_alt_layout', 'lp_frontpage_order_by_num_replies', 'lp_frontpage_article_sorting', 'lp_frontpage_layout', 'lp_teaser_size', 'lp_num_items_per_page'); $frontpage_mode_toggle_dt = []; foreach ($frontpage_mode_toggle as $item) $frontpage_mode_toggle_dt[] = 'setting_' . $item; - $frontpage_alias_toggle = array('lp_frontpage_title', 'lp_frontpage_boards', 'lp_show_images_in_articles', 'lp_image_placeholder', 'lp_frontpage_card_alt_layout', 'lp_frontpage_order_by_num_replies', 'lp_frontpage_layout', 'lp_num_items_per_page'); + $frontpage_alias_toggle = array('lp_frontpage_title', 'lp_frontpage_boards', 'lp_show_images_in_articles', 'lp_image_placeholder', 'lp_frontpage_card_alt_layout', 'lp_frontpage_order_by_num_replies', 'lp_frontpage_article_sorting', 'lp_frontpage_layout', 'lp_teaser_size', 'lp_num_items_per_page'); $frontpage_alias_toggle_dt = []; foreach ($frontpage_alias_toggle as $item) @@ -268,18 +271,35 @@ public static function basic(bool $return_config = false) addInlineJavaScript(' function toggleFrontpageMode() { let change_mode = $("#lp_frontpage_mode").val() > 0; + let board_selector = $(".board_selector").parent("dd"); + $("#' . implode(', #', $frontpage_mode_toggle) . '").closest("dd").toggle(change_mode); $("#' . implode(', #', $frontpage_mode_toggle_dt) . '").closest("dt").toggle(change_mode); - $(".board_selector").toggle(change_mode); + board_selector.toggle(change_mode); + let allow_change_title = $("#lp_frontpage_mode").val() > 1; + $("#' . implode(', #', $frontpage_alias_toggle) . '").closest("dd").toggle(allow_change_title); $("#' . implode(', #', $frontpage_alias_toggle_dt) . '").closest("dt").toggle(allow_change_title); - $(".board_selector").toggle(allow_change_title); + board_selector.toggle(allow_change_title); + let allow_change_alias = $("#lp_frontpage_mode").val() == 1; + $("#lp_frontpage_alias").closest("dd").toggle(allow_change_alias); $("#setting_lp_frontpage_alias").closest("dt").toggle(allow_change_alias); + + if ($("#lp_frontpage_mode").val() == 3) { + let boards = $("#setting_lp_frontpage_boards").closest("dt"); + + boards.hide(); + boards.next("dd").hide(); + } else { + board_selector.toggle(allow_change_title); + } }; + toggleFrontpageMode(); + $("#lp_frontpage_mode").on("click", function () { toggleFrontpageMode() });', true); @@ -294,31 +314,35 @@ function toggleFrontpageMode() { addInlineJavaScript(' function toggleStandaloneMode() { let change_mode = $("#lp_standalone_mode").prop("checked"); + $("#' . implode(', #', $standalone_mode_toggle) . '").closest("dd").toggle(change_mode); $("#' . implode(', #', $standalone_mode_toggle_dt) . '").closest("dt").toggle(change_mode); }; + toggleStandaloneMode(); + $("#lp_standalone_mode").on("click", function () { toggleStandaloneMode() });', true); // Save - if (isset($_GET['save'])) { + if (Helpers::request()->has('save')) { checkSession(); - if (empty($_POST['lp_frontpage_mode'])) - $_POST['lp_standalone_url'] = 0; + if (Helpers::post()->isEmpty('lp_frontpage_mode')) + Helpers::post()->put('lp_standalone_url', 0); - if (!empty($_POST['lp_image_placeholder'])) - $_POST['lp_image_placeholder'] = filter_var($_POST['lp_image_placeholder'], FILTER_VALIDATE_URL); + if (Helpers::post()->filled('lp_image_placeholder')) + Helpers::post()->put('lp_image_placeholder', Helpers::validate(Helpers::post('lp_image_placeholder'), 'url')); - if (!empty($_POST['lp_standalone_url'])) - $_POST['lp_standalone_url'] = filter_var($_POST['lp_standalone_url'], FILTER_VALIDATE_URL); + if (Helpers::post()->filled('lp_standalone_url')) + Helpers::post()->put('lp_standalone_url', Helpers::validate(Helpers::post('lp_standalone_url'), 'url')); $save_vars = $config_vars; saveDBSettings($save_vars); - clean_cache(); + Helpers::cache()->flush(); + redirectexit('action=admin;area=lp_settings;sa=basic'); } @@ -371,20 +395,24 @@ public static function extra(bool $return_config = false) addInlineJavaScript(' function toggleShowCommentBlock() { let change_mode = $("#lp_show_comment_block").val() != "none"; + $("#' . implode(', #', $show_comment_block_toggle) . '").closest("dd").toggle(change_mode); $("#' . implode(', #', $show_comment_block_toggle_dt) . '").closest("dt").toggle(change_mode); + if (change_mode && $("#lp_show_comment_block").val() != "default") { $("#lp_disabled_bbc_in_comments").closest("dd").hide(); $("#setting_lp_disabled_bbc_in_comments").closest("dt").hide(); } }; + toggleShowCommentBlock(); + $("#lp_show_comment_block").on("click", function () { toggleShowCommentBlock() });', true); // Save - if (isset($_GET['save'])) { + if (Helpers::request()->has('save')) { checkSession(); // Clean up the tags @@ -392,19 +420,20 @@ function toggleShowCommentBlock() { foreach (parse_bbc(false) as $tag) $bbcTags[] = $tag['tag']; - if (!isset($_POST['lp_disabled_bbc_in_comments_enabledTags'])) - $_POST['lp_disabled_bbc_in_comments_enabledTags'] = []; - elseif (!is_array($_POST['lp_disabled_bbc_in_comments_enabledTags'])) - $_POST['lp_disabled_bbc_in_comments_enabledTags'] = array($_POST['lp_disabled_bbc_in_comments_enabledTags']); + if (Helpers::post()->has('lp_disabled_bbc_in_comments_enabledTags') === false) + Helpers::post()->put('lp_disabled_bbc_in_comments_enabledTags', []); + elseif (!is_array(Helpers::post('lp_disabled_bbc_in_comments_enabledTags'))) + Helpers::post()->put('lp_disabled_bbc_in_comments_enabledTags', array(Helpers::post('lp_disabled_bbc_in_comments_enabledTags'))); - $_POST['lp_enabled_bbc_in_comments'] = implode(',', $_POST['lp_disabled_bbc_in_comments_enabledTags']); - $_POST['lp_disabled_bbc_in_comments'] = implode(',', array_diff($bbcTags, $_POST['lp_disabled_bbc_in_comments_enabledTags'])); + Helpers::post()->put('lp_enabled_bbc_in_comments', implode(',', Helpers::post('lp_disabled_bbc_in_comments_enabledTags'))); + Helpers::post()->put('lp_disabled_bbc_in_comments', implode(',', array_diff($bbcTags, Helpers::post('lp_disabled_bbc_in_comments_enabledTags')))); $save_vars = $config_vars; $save_vars[] = ['text', 'lp_enabled_bbc_in_comments']; saveDBSettings($save_vars); - clean_cache(); + Helpers::cache()->flush(); + redirectexit('action=admin;area=lp_settings;sa=extra'); } @@ -447,6 +476,10 @@ public static function panels(bool $return_config = false) $add_settings['lp_right_panel_width'] = json_encode($context['lp_right_panel_width']); if (!isset($modSettings['lp_footer_panel_width'])) $add_settings['lp_footer_panel_width'] = 12; + if (!isset($modSettings['lp_left_panel_sticky'])) + $add_settings['lp_left_panel_sticky'] = 1; + if (!isset($modSettings['lp_right_panel_sticky'])) + $add_settings['lp_right_panel_sticky'] = 1; if (!empty($add_settings)) updateSettings($add_settings); @@ -470,18 +503,20 @@ public static function panels(bool $return_config = false) $context['sub_template'] = 'show_settings'; - if (isset($_GET['save'])) { + if (Helpers::request()->has('save')) { checkSession(); - $_POST['lp_left_panel_width'] = json_encode($_POST['lp_left_panel_width']); - $_POST['lp_right_panel_width'] = json_encode($_POST['lp_right_panel_width']); - $_POST['lp_panel_direction'] = json_encode($_POST['lp_panel_direction']); + Helpers::post()->put('lp_left_panel_width', json_encode(Helpers::post('lp_left_panel_width'))); + Helpers::post()->put('lp_right_panel_width', json_encode(Helpers::post('lp_right_panel_width'))); + Helpers::post()->put('lp_panel_direction', json_encode(Helpers::post('lp_panel_direction'))); $save_vars = $config_vars; $save_vars[] = ['int', 'lp_header_panel_width']; $save_vars[] = ['text', 'lp_left_panel_width']; $save_vars[] = ['text', 'lp_right_panel_width']; $save_vars[] = ['int', 'lp_footer_panel_width']; + $save_vars[] = ['check', 'lp_left_panel_sticky']; + $save_vars[] = ['check', 'lp_right_panel_sticky']; $save_vars[] = ['text', 'lp_panel_direction']; saveDBSettings($save_vars); @@ -530,28 +565,28 @@ public static function plugins() $context['sub_template'] = 'plugin_settings'; - if (isset($_GET['save'])) { + if (Helpers::request()->has('save')) { checkSession(); $plugin_options = []; foreach ($config_vars as $id => $var) { - if (isset($_POST[$var[1]])) { + if (Helpers::post()->has($var[1])) { if ($var[0] == 'check') { - $plugin_options[$var[1]] = (int) filter_var($_POST[$var[1]], FILTER_VALIDATE_BOOLEAN); + $plugin_options[$var[1]] = (int) Helpers::validate(Helpers::post($var[1]), 'bool'); } elseif ($var[0] == 'int') { - $plugin_options[$var[1]] = filter_var($_POST[$var[1]], FILTER_VALIDATE_INT); + $plugin_options[$var[1]] = Helpers::validate(Helpers::post($var[1]), 'int'); } elseif ($var[0] == 'multicheck') { $plugin_options[$var[1]] = []; - foreach ($_POST[$var[1]] as $key => $value) { - $plugin_options[$var[1]][(int) $key] = (int) filter_var($value, FILTER_VALIDATE_BOOLEAN); + foreach (Helpers::post($var[1]) as $key => $value) { + $plugin_options[$var[1]][$key] = (int) Helpers::validate($value, 'bool'); } $plugin_options[$var[1]] = json_encode($plugin_options[$var[1]]); } elseif ($var[0] == 'url') { - $plugin_options[$var[1]] = filter_var($_POST[$var[1]], FILTER_SANITIZE_URL); + $plugin_options[$var[1]] = Helpers::validate(Helpers::post($var[1]), 'url'); } else { - $plugin_options[$var[1]] = $_POST[$var[1]]; + $plugin_options[$var[1]] = Helpers::post($var[1]); } } } @@ -621,7 +656,7 @@ private static function getPluginTypes($snake_name) * @param string $name * @return array */ - private static function getPluginSettings($config_vars, $name = '') + private static function getPluginSettings(array $config_vars, $name = '') { if (empty($config_vars)) return []; @@ -657,8 +692,8 @@ public static function blockArea() ); if ($user_info['is_admin']) { - $subActions['export'] = 'ManageBlocks::export'; - $subActions['import'] = 'ManageBlocks::import'; + $subActions['export'] = 'Impex\BlockExport::main'; + $subActions['import'] = 'Impex\BlockImport::main'; } self::loadGeneralSettingParameters($subActions, 'main'); @@ -678,14 +713,14 @@ public static function pageArea() isAllowedTo('light_portal_manage_own_pages'); $subActions = array( - 'main' => 'ManagePages::main', - 'add' => 'ManagePages::add', - 'edit' => 'ManagePages::edit' + 'main' => 'ManagePages::main', + 'add' => 'ManagePages::add', + 'edit' => 'ManagePages::edit' ); if ($user_info['is_admin']) { - $subActions['export'] = 'ManagePages::export'; - $subActions['import'] = 'ManagePages::import'; + $subActions['export'] = 'Impex\PageExport::main'; + $subActions['import'] = 'Impex\PageImport::main'; } self::loadGeneralSettingParameters($subActions, 'main'); @@ -697,7 +732,7 @@ public static function pageArea() * Вызывает метод, если он существует; в противном случае вызывается метод по умолчанию * * @param array $subActions - * @param string $defaultAction + * @param string|null $defaultAction * @return void */ private static function loadGeneralSettingParameters(array $subActions = [], string $defaultAction = null) @@ -729,7 +764,7 @@ private static function checkNewVersion() global $context, $txt; // Check once a week | Проверяем раз в неделю - if (LP_VERSION < $new_version = Helpers::getFromCache('last_version', 'getLastVersion', __CLASS__, 604800)) { + if (LP_VERSION < $new_version = Helpers::cache('last_version', 'getLastVersion', __CLASS__, 604800)) { $context['settings_insert_above'] = '
' . $txt['lp_new_version_is_available'] . ' (' . $new_version . ') diff --git a/Sources/LightPortal/Subs.php b/Sources/LightPortal/Subs.php index a1da7be96..9be21b19b 100644 --- a/Sources/LightPortal/Subs.php +++ b/Sources/LightPortal/Subs.php @@ -11,7 +11,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -49,8 +49,8 @@ public static function loadBlocks() $context['lp_all_content_classes'] = self::getContentClasses(); $context['lp_fontawesome_enabled'] = Helpers::doesThisThemeUseFontAwesome(); - $context['lp_active_blocks'] = Helpers::getFromCache('active_blocks', 'getActiveBlocks', __CLASS__); - $context['lp_num_active_pages'] = Helpers::getFromCache('num_active_pages_u' . $context['user']['id'], 'getNumActivePages', __CLASS__); + $context['lp_active_blocks'] = Helpers::cache('active_blocks', 'getActiveBlocks', __CLASS__); + $context['lp_num_active_pages'] = Helpers::cache('num_active_pages_u' . $context['user']['id'], 'getNumActivePages', __CLASS__); // Width of some panels | Ширина некоторых панелей $context['lp_header_panel_width'] = !empty($modSettings['lp_header_panel_width']) ? (int) $modSettings['lp_header_panel_width'] : 12; @@ -106,8 +106,7 @@ public static function getActiveBLocks() 'title_class' => $row['title_class'], 'title_style' => $row['title_style'], 'content_class' => $row['content_class'], - 'content_style' => $row['content_style'], - 'permissions' => $row['permissions'] + 'content_style' => $row['content_style'] ); $active_blocks[$row['block_id']]['title'][$row['lang']] = $row['title']; @@ -117,15 +116,15 @@ public static function getActiveBLocks() } $smcFunc['db_free_result']($request); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; return $active_blocks; } /** - * Get the total number of active pages of the current user + * Get the total number of active pages * - * Подсчитываем общее количество активных страниц текущего пользователя + * Подсчитываем общее количество активных страниц * * @return int */ @@ -145,8 +144,9 @@ public static function getNumActivePages() ); [$num_pages] = $smcFunc['db_fetch_row']($request); + $smcFunc['db_free_result']($request); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; return (int) $num_pages; } @@ -187,75 +187,6 @@ public static function unsetDisabledActions(array &$data) return $disabled_actions; } - /** - * Prepare content to display - * - * Готовим контент к отображению в браузере - * - * @param string $content - * @param string $type - * @param int $block_id - * @param int $cache_time - * @return void - */ - public static function prepareContent(string &$content, string $type = 'bbc', int $block_id = 0, int $cache_time = 0) - { - global $context; - - !empty($block_id) && !empty($context['lp_active_blocks'][$block_id]) - ? $parameters = $context['lp_active_blocks'][$block_id]['parameters'] ?? [] - : $parameters = $context['lp_block']['options']['parameters'] ?? []; - - self::runAddons('prepareContent', array(&$content, $type, $block_id, $cache_time, $parameters)); - } - - /** - * Parse content depending on the type - * - * Парсим контент в зависимости от типа - * - * @param string $content - * @param string $type - * @return void - */ - public static function parseContent(string &$content, string $type = 'bbc') - { - global $context; - - switch ($type) { - case 'bbc': - $content = parse_bbc($content); - - // Integrate with the Paragrapher mod - call_integration_hook('integrate_paragrapher_string', array(&$content)); - - break; - case 'html': - $content = un_htmlspecialchars($content); - - break; - case 'php': - $content = trim(un_htmlspecialchars($content)); - $content = trim($content, ''); - - ob_start(); - - try { - $content = html_entity_decode($content, ENT_COMPAT, $context['character_set'] ?? 'UTF-8'); - eval($content); - } catch (\ParseError $p) { - echo $p->getMessage(); - } - - $content = ob_get_clean(); - - break; - default: - self::runAddons('parseContent', array(&$content, $type)); - } - } - /** * Get names of the current addons * @@ -448,7 +379,7 @@ public static function getContentClasses() */ public static function getAllTitles(string $type = 'page') { - global $smcFunc, $context; + global $smcFunc; $request = $smcFunc['db_query']('', ' SELECT item_id, lang, title @@ -467,7 +398,7 @@ public static function getAllTitles(string $type = 'page') } $smcFunc['db_free_result']($request); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; return $titles; } @@ -481,9 +412,9 @@ public static function getAllTitles(string $type = 'page') */ public static function showDebugInfo() { - global $context, $txt; + global $context, $txt, $smcFunc; - $context['lp_load_page_stats'] = LP_DEBUG ? sprintf($txt['lp_load_page_stats'], round(microtime(true) - $context['lp_load_time'], 3), $context['lp_num_queries']) : false; + $context['lp_load_page_stats'] = LP_DEBUG ? sprintf($txt['lp_load_page_stats'], round(microtime(true) - $context['lp_load_time'], 3), $smcFunc['lp_num_queries']) : false; if (!empty($context['lp_load_page_stats']) && !empty($context['template_layers'])) { loadTemplate('LightPortal/ViewDebug'); @@ -539,6 +470,8 @@ public static function fixLinktree() /** * Check if the portal must not be loaded * + * Проверяем, должен портал загружаться или нет + * * @return bool */ public static function isPortalMustNotBeLoaded() diff --git a/Sources/LightPortal/Tag.php b/Sources/LightPortal/Tag.php index 0b3cc1a59..6a7f7b99b 100644 --- a/Sources/LightPortal/Tag.php +++ b/Sources/LightPortal/Tag.php @@ -11,7 +11,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -30,10 +30,10 @@ public static function show() { global $context, $smcFunc, $txt, $scripturl, $modSettings, $sourcedir; - if (empty($_GET['key'])) + if (Helpers::request()->isEmpty('key')) self::showAll(); - $context['lp_keyword'] = $smcFunc['htmlspecialchars'](trim($_GET['key']), ENT_QUOTES); + $context['lp_keyword'] = $smcFunc['htmlspecialchars'](trim(Helpers::request('key')), ENT_QUOTES); $context['page_title'] = sprintf($txt['lp_all_tags_by_key'], $context['lp_keyword']); $context['canonical_url'] = $scripturl . '?action=portal;sa=tags;key=' . urlencode($context['lp_keyword']); $context['robot_no_index'] = true; @@ -84,7 +84,7 @@ public static function show() 'data' => array( 'function' => function ($entry) use ($scripturl) { - return '' . Helpers::getPublicTitle($entry) . ''; + return '' . Helpers::getTitle($entry) . ''; }, 'class' => 'centertext' ) @@ -147,7 +147,7 @@ public static function getAllPagesWithSelectedTag(int $start, int $items_per_pag { global $smcFunc, $txt, $context, $modSettings, $scripturl, $user_info; - $titles = Helpers::getFromCache('all_titles', 'getAllTitles', '\Bugo\LightPortal\Subs', LP_CACHE_TIME, 'page'); + $titles = Helpers::cache('all_titles', 'getAllTitles', '\Bugo\LightPortal\Subs', LP_CACHE_TIME, 'page'); $request = $smcFunc['db_query']('', ' SELECT @@ -176,7 +176,7 @@ public static function getAllPagesWithSelectedTag(int $start, int $items_per_pag $items = []; while ($row = $smcFunc['db_fetch_assoc']($request)) { - Subs::parseContent($row['content'], $row['type']); + Helpers::parseContent($row['content'], $row['type']); $image = null; if (!empty($modSettings['lp_show_images_in_articles'])) { @@ -203,7 +203,7 @@ public static function getAllPagesWithSelectedTag(int $start, int $items_per_pag } $smcFunc['db_free_result']($request); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; return $items; } @@ -240,7 +240,7 @@ public static function getTotalQuantityPagesWithSelectedTag() $items[$row['page_id']] = $row['value']; $smcFunc['db_free_result']($request); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; return sizeof($items); } @@ -330,19 +330,20 @@ public static function showAll() */ public static function getAll(int $start, int $items_per_page, string $sort) { - global $smcFunc, $scripturl, $context; + global $smcFunc, $scripturl; $request = $smcFunc['db_query']('', ' SELECT t.value FROM {db_prefix}lp_tags AS t INNER JOIN {db_prefix}lp_pages AS p ON (t.page_id = p.page_id) - WHERE t.value IS NOT NULL + WHERE t.value <> {string:blank_string} AND p.status = {int:status} AND p.created_at <= {int:current_time} AND p.permissions IN ({array_int:permissions}) ORDER BY {raw:sort}' . ($items_per_page ? ' LIMIT {int:start}, {int:limit}' : ''), array( + 'blank_string' => '', 'status' => Page::STATUS_ACTIVE, 'current_time' => time(), 'permissions' => Helpers::getPermissions(), @@ -366,7 +367,7 @@ public static function getAll(int $start, int $items_per_page, string $sort) } $smcFunc['db_free_result']($request); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; uasort($items, function ($a, $b) { return $a['frequency'] < $b['frequency']; @@ -384,7 +385,7 @@ public static function getAll(int $start, int $items_per_page, string $sort) */ public static function getTotalQuantity() { - global $smcFunc, $context; + global $smcFunc; $request = $smcFunc['db_query']('', ' SELECT t.page_id, t.value @@ -406,7 +407,7 @@ public static function getTotalQuantity() $items[$row['value']] = $row['page_id']; $smcFunc['db_free_result']($request); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; return sizeof($items); } @@ -443,14 +444,14 @@ private static function showAsArticles() 'num_views' => 'p.num_views' ); - $context['current_sorting'] = $_POST['sort'] ?? 'created;desc'; + $context['current_sorting'] = Helpers::post('sort', 'created;desc'); $sort = $sorting_types[$context['current_sorting']]; $articles = self::getAllPagesWithSelectedTag($start, $limit, $sort); $articles = array_map(function ($article) use ($modSettings) { if (isset($article['title'])) - $article['title'] = Helpers::getPublicTitle($article); + $article['title'] = Helpers::getTitle($article); if (empty($article['image']) && !empty($modSettings['lp_image_placeholder'])) $article['image'] = $modSettings['lp_image_placeholder']; @@ -463,7 +464,7 @@ private static function showAsArticles() $context['lp_frontpage_articles'] = $articles; - $context['lp_frontpage_layout'] = FrontPage::getNumColumns(); + $context['lp_frontpage_layout'] = Front\Article::getNumColumns(); loadTemplate('LightPortal/ViewFrontPage'); loadTemplate('LightPortal/ViewTags'); diff --git a/Sources/LightPortal/addons/AdsBlock/AdsBlock.php b/Sources/LightPortal/addons/AdsBlock/AdsBlock.php index 83809d13b..553ca04fc 100644 --- a/Sources/LightPortal/addons/AdsBlock/AdsBlock.php +++ b/Sources/LightPortal/addons/AdsBlock/AdsBlock.php @@ -13,7 +13,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -91,7 +91,7 @@ public static function menuButtons() if (empty($context['current_board'])) return; - $context['lp_ads_blocks'] = Helpers::getFromCache('ads_block_addon', 'getData', __CLASS__); + $context['lp_ads_blocks'] = Helpers::cache('ads_block_addon', 'getData', __CLASS__); if (!empty($context['lp_ads_blocks'])) $context['lp_blocks'] = array_merge($context['lp_blocks'], $context['lp_ads_blocks']); @@ -114,6 +114,7 @@ public static function getData() if (empty($context['lp_blocks']['ads'])) return []; + $ads_blocks = []; foreach ($txt['lp_ads_block_addon_placement_set'] as $position => $dump) $ads_blocks[$position] = self::getByPosition($position); @@ -189,7 +190,9 @@ public static function prepareDisplayContext(&$output, &$message, $counter) * * Вывод рекламы перед каждым последним сообщением */ - $before_every_last_post = empty($options['view_newest_first']) ? $counter == $context['total_visible_posts'] || $counter % $context['messages_per_page'] == 0 : ($output['id'] == $context['topic_first_message'] || ($context['total_visible_posts'] - $counter) % $context['messages_per_page'] == 0); + $before_every_last_post = empty($options['view_newest_first']) + ? $counter == $context['total_visible_posts'] || $counter % $context['messages_per_page'] == 0 + : ($output['id'] == $context['topic_first_message'] || ($context['total_visible_posts'] - $counter) % $context['messages_per_page'] == 0); if (!empty($context['lp_ads_blocks']['before_every_last_post']) && $before_every_last_post) { lp_show_blocks('before_every_last_post'); } @@ -221,56 +224,6 @@ public static function prepareDisplayContext(&$output, &$message, $counter) if (!empty($context['lp_ads_blocks']['after_every_first_post']) && ($output['counter'] == (empty($options['view_newest_first']) ? $context['start'] + 1 : $current_counter - 1))) { lp_show_blocks('after_every_first_post'); } - - /** - * Displaying ads after every fifth message on the page - * - * Вывод рекламы после каждого пятого сообщения - */ - if (!empty($context['lp_ads_blocks']['after_every_five_post']) && abs($current_counter - $counter) == 5) { - ob_start(); - - lp_show_blocks('after_every_five_post'); - - $after_every_five_post = ob_get_clean(); - - addInlineJavaScript(' - const all_windowbg = document.getElementById("quickModForm").querySelectorAll("div.windowbg"); - all_windowbg[all_windowbg.length - 1].insertAdjacentHTML("afterend", ' . JavaScriptEscape($after_every_five_post) . ');', true); - } - - /** - * Displaying ads after each last message on the page - * - * Вывод рекламы после каждого последнего сообщения - */ - if (!empty($context['lp_ads_blocks']['after_every_last_post']) && ($counter == $context['total_visible_posts'] || $counter % $context['messages_per_page'] == 0)) { - ob_start(); - - lp_show_blocks('after_every_last_post'); - - $after_every_last_post = ob_get_clean(); - - addInlineJavaScript(' - const all_windowbg2 = document.getElementById("quickModForm").querySelectorAll("div.windowbg"); - all_windowbg2[all_windowbg2.length - 1].insertAdjacentHTML("afterend", ' . JavaScriptEscape($after_every_last_post) . ');', true); - } - - /** - * Displaying ads after the last message - * - * Вывод рекламы после последнего сообщения - */ - if (!empty($context['lp_ads_blocks']['after_last_post']) && $output['id'] == (empty($options['view_newest_first']) ? $context['topic_last_message'] : $context['topic_first_message'])) { - ob_start(); - - lp_show_blocks('after_last_post'); - - $after_last_post = ob_get_clean(); - - addInlineJavaScript(' - document.getElementById("quickModForm").insertAdjacentHTML("beforeend", ' . JavaScriptEscape($after_last_post) . ');', true); - } } /** @@ -281,14 +234,14 @@ public static function prepareDisplayContext(&$output, &$message, $counter) * @param string $position * @return array */ - private static function getByPosition($position) + private static function getByPosition(string $position) { global $context; if (empty($position)) return []; - $blocks = array_filter($context['lp_blocks']['ads'], function ($block) use ($position, $context) { + return array_filter($context['lp_blocks']['ads'], function ($block) use ($position, $context) { if (!empty($block['parameters']['ads_boards'])) { $boards = array_flip(explode(',', $block['parameters']['ads_boards'])); if (!array_key_exists($context['current_board'], $boards)) @@ -308,8 +261,6 @@ private static function getByPosition($position) return false; }); - - return $blocks; } /** @@ -403,7 +354,9 @@ public static function prepareBlockFields() ) ); - $context['lp_block']['options']['parameters']['ads_placement'] = is_array($context['lp_block']['options']['parameters']['ads_placement']) ? $context['lp_block']['options']['parameters']['ads_placement'] : explode(',', $context['lp_block']['options']['parameters']['ads_placement']); + if (!is_array($context['lp_block']['options']['parameters']['ads_placement'])) { + $context['lp_block']['options']['parameters']['ads_placement'] = explode(',', $context['lp_block']['options']['parameters']['ads_placement']); + } $context['posting_fields']['ads_placement']['label']['text'] = $txt['lp_block_placement']; $context['posting_fields']['ads_placement']['input'] = array( diff --git a/Sources/LightPortal/addons/AdsBlock/langs/english.php b/Sources/LightPortal/addons/AdsBlock/langs/english.php index ee9b9ab74..334563565 100644 --- a/Sources/LightPortal/addons/AdsBlock/langs/english.php +++ b/Sources/LightPortal/addons/AdsBlock/langs/english.php @@ -19,8 +19,5 @@ 'before_every_last_post' => 'Before each last message on the page', 'before_last_post' => 'Before the last message', 'after_first_post' => 'After the first message', - 'after_every_first_post' => 'After each first message on the page', - 'after_every_five_post' => 'After every fifth message on the page', - 'after_every_last_post' => 'After each last message on the page', - 'after_last_post' => 'After the last message' + 'after_every_first_post' => 'After each first message on the page' ); \ No newline at end of file diff --git a/Sources/LightPortal/addons/AdsBlock/langs/polish.php b/Sources/LightPortal/addons/AdsBlock/langs/polish.php index f67d434b1..b188b6d31 100644 --- a/Sources/LightPortal/addons/AdsBlock/langs/polish.php +++ b/Sources/LightPortal/addons/AdsBlock/langs/polish.php @@ -19,8 +19,5 @@ 'before_every_last_post' => 'Przed ostatnią wiadomością na każdej stronie wątku', 'before_last_post' => 'Przed ostatnią wiadomością', 'after_first_post' => 'Po pierwszej wiadomości', - 'after_every_first_post' => 'Po pierwszej wiadomości na każdej stronie wątku', - 'after_every_five_post' => 'Po piątej wiadomości na każdej stronie wątku', - 'after_every_last_post' => 'Po ostatniej wiadomości na każdej stronie wątku', - 'after_last_post' => 'Po ostatniej wiadomości' + 'after_every_first_post' => 'Po pierwszej wiadomości na każdej stronie wątku' ); diff --git a/Sources/LightPortal/addons/AdsBlock/langs/russian.php b/Sources/LightPortal/addons/AdsBlock/langs/russian.php index c046d75c2..61e1668f0 100644 --- a/Sources/LightPortal/addons/AdsBlock/langs/russian.php +++ b/Sources/LightPortal/addons/AdsBlock/langs/russian.php @@ -19,8 +19,5 @@ 'before_every_last_post' => 'Перед каждым последним сообщением на странице', 'before_last_post' => 'Перед последним сообщением', 'after_first_post' => 'После первого сообщения', - 'after_every_first_post' => 'После каждого первого сообщения на странице', - 'after_every_five_post' => 'После каждого пятого сообщения на странице', - 'after_every_last_post' => 'После каждого последнего сообщения на странице', - 'after_last_post' => 'После последнего сообщения' + 'after_every_first_post' => 'После каждого первого сообщения на странице' ); \ No newline at end of file diff --git a/Sources/LightPortal/addons/AdsBlock/langs/spanish_es.php b/Sources/LightPortal/addons/AdsBlock/langs/spanish_es.php index b2644c8e4..8173ce6d6 100644 --- a/Sources/LightPortal/addons/AdsBlock/langs/spanish_es.php +++ b/Sources/LightPortal/addons/AdsBlock/langs/spanish_es.php @@ -21,8 +21,5 @@ 'before_every_last_post' => 'Antes de cada último mensaje en la página', 'before_last_post' => 'Antes del último mensaje', 'after_first_post' => 'Después del primer mensaje', - 'after_every_first_post' => 'Después de cada primer mensaje en la página', - 'after_every_five_post' => 'Después de cada quinto mensaje en la página', - 'after_every_last_post' => 'Después de cada último mensaje en la página.', - 'after_last_post' => 'Después del último mensaje' + 'after_every_first_post' => 'Después de cada primer mensaje en la página' ); diff --git a/Sources/LightPortal/addons/AdsBlock/langs/spanish_latin.php b/Sources/LightPortal/addons/AdsBlock/langs/spanish_latin.php index 8889271ed..07b261cee 100644 --- a/Sources/LightPortal/addons/AdsBlock/langs/spanish_latin.php +++ b/Sources/LightPortal/addons/AdsBlock/langs/spanish_latin.php @@ -21,8 +21,5 @@ 'before_every_last_post' => 'Antes de cada último mensaje en la página', 'before_last_post' => 'Antes del último mensaje', 'after_first_post' => 'Después del primer mensaje', - 'after_every_first_post' => 'Después de cada primer mensaje en la página', - 'after_every_five_post' => 'Después de cada quinto mensaje en la página', - 'after_every_last_post' => 'Después de cada último mensaje en la página.', - 'after_last_post' => 'Después del último mensaje' + 'after_every_first_post' => 'Después de cada primer mensaje en la página' ); diff --git a/Sources/LightPortal/addons/AdsBlock/langs/ukrainian.php b/Sources/LightPortal/addons/AdsBlock/langs/ukrainian.php index 2c0466526..0959d2df8 100644 --- a/Sources/LightPortal/addons/AdsBlock/langs/ukrainian.php +++ b/Sources/LightPortal/addons/AdsBlock/langs/ukrainian.php @@ -20,7 +20,4 @@ 'before_last_post' => 'Перед останнім повідомленням', 'after_first_post' => 'Після першого повідомлення', 'after_every_first_post' => 'Після кожного першого повідомлення на сторінці', - 'after_every_five_post' => 'Після кожного п\'ятого повідомлення на сторінці', - 'after_every_last_post' => 'Після кожного останнього повідомлення на сторінці', - 'after_last_post' => 'Після останнього повідомлення' ); \ No newline at end of file diff --git a/Sources/LightPortal/addons/ArticleList/ArticleList.php b/Sources/LightPortal/addons/ArticleList/ArticleList.php index b4b7eac0a..62376ae70 100644 --- a/Sources/LightPortal/addons/ArticleList/ArticleList.php +++ b/Sources/LightPortal/addons/ArticleList/ArticleList.php @@ -3,7 +3,6 @@ namespace Bugo\LightPortal\Addons\ArticleList; use Bugo\LightPortal\Helpers; -use Bugo\LightPortal\Subs; /** * ArticleList @@ -14,7 +13,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -134,7 +133,8 @@ public static function prepareBlockFields() 'attributes' => array( 'id' => 'article_body_class' ), - 'options' => array() + 'options' => array(), + 'tab' => 'appearance' ); foreach ($context['lp_all_content_classes'] as $key => $data) { @@ -210,7 +210,7 @@ public static function prepareBlockFields() */ public static function getTopics(array $parameters) { - global $smcFunc, $modSettings, $context; + global $smcFunc, $modSettings; if (empty($parameters['ids'])) return []; @@ -250,7 +250,7 @@ public static function getTopics(array $parameters) } $smcFunc['db_free_result']($request); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; return $topics; } @@ -265,12 +265,12 @@ public static function getTopics(array $parameters) */ public static function getPages(array $parameters) { - global $smcFunc, $modSettings, $context; + global $smcFunc, $modSettings; if (empty($parameters['ids'])) return []; - $titles = Helpers::getFromCache('all_titles', 'getAllTitles', '\Bugo\LightPortal\Subs', LP_CACHE_TIME, 'page'); + $titles = Helpers::cache('all_titles', 'getAllTitles', '\Bugo\LightPortal\Subs', LP_CACHE_TIME, 'page'); $request = $smcFunc['db_query']('', ' SELECT page_id, alias, content, description, type @@ -294,7 +294,7 @@ public static function getPages(array $parameters) continue; if (!empty($parameters['seek_images'])) { - Subs::parseContent($row['content'], $row['type']); + Helpers::parseContent($row['content'], $row['type']); $first_post_image = preg_match('/ + ' . $topic['title'] . '
'; } @@ -366,14 +366,14 @@ public static function prepareContent(&$content, $type, $block_id, $cache_time, } } else { foreach ($article_list as $page) { - if (empty($title = Helpers::getPublicTitle($page))) + if (empty($title = Helpers::getTitle($page))) continue; $content = ''; if (!empty($page['image'])) { $content .= '
- + '. $title . '
'; } @@ -385,8 +385,9 @@ public static function prepareContent(&$content, $type, $block_id, $cache_time, echo ' '; - } else - echo $txt['lp_article_list_addon_no_items']; + } else { + echo '
', $txt['lp_article_list_addon_no_items'], '
'; + } $content = ob_get_clean(); } diff --git a/Sources/LightPortal/addons/BoardIndex/BoardIndex.php b/Sources/LightPortal/addons/BoardIndex/BoardIndex.php index d83429c1d..b2f793a9b 100644 --- a/Sources/LightPortal/addons/BoardIndex/BoardIndex.php +++ b/Sources/LightPortal/addons/BoardIndex/BoardIndex.php @@ -11,7 +11,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -56,6 +56,10 @@ public static function addSettings(&$config_vars) */ public static function init() { + global $txt, $scripturl; + + $txt['lp_board_index_description'] = sprintf($txt['lp_board_index_description'], $scripturl . '?action=forum'); + add_integration_function('integrate_mark_read_button', __CLASS__ . '::toggleRobotNoIndex', false, __FILE__); } diff --git a/Sources/LightPortal/addons/BoardIndex/langs/english.php b/Sources/LightPortal/addons/BoardIndex/langs/english.php index 35f38a524..74e7ae0df 100644 --- a/Sources/LightPortal/addons/BoardIndex/langs/english.php +++ b/Sources/LightPortal/addons/BoardIndex/langs/english.php @@ -1,5 +1,5 @@ ?action=forum) if the portal is enabled.'; +$txt['lp_board_index_description'] = 'Additional settings of the forum home page if the portal is enabled.'; $txt['lp_board_index_addon_allow_for_spiders'] = 'Allow indexing of the forum home page'; diff --git a/Sources/LightPortal/addons/BoardIndex/langs/russian.php b/Sources/LightPortal/addons/BoardIndex/langs/russian.php index 0441fc11e..a01f10ae7 100644 --- a/Sources/LightPortal/addons/BoardIndex/langs/russian.php +++ b/Sources/LightPortal/addons/BoardIndex/langs/russian.php @@ -1,5 +1,5 @@ ?action=forum), если включен портал.'; +$txt['lp_board_index_description'] = 'Дополнительные настройки главной страницы форума, если включен портал.'; $txt['lp_board_index_addon_allow_for_spiders'] = 'Разрешить индексацию главной страницы форума'; diff --git a/Sources/LightPortal/addons/BoardIndex/langs/ukrainian.php b/Sources/LightPortal/addons/BoardIndex/langs/ukrainian.php index dd9ae304f..d0de5b9e5 100644 --- a/Sources/LightPortal/addons/BoardIndex/langs/ukrainian.php +++ b/Sources/LightPortal/addons/BoardIndex/langs/ukrainian.php @@ -1,5 +1,5 @@ ?action=forum), якщо включений портал.'; +$txt['lp_board_index_description'] = 'Додаткові налаштування головної сторінки форуму, якщо включений портал.'; $txt['lp_board_index_addon_allow_for_spiders'] = 'Дозволити індексацію головної сторінки форуму'; diff --git a/Sources/LightPortal/addons/BoardList/BoardList.php b/Sources/LightPortal/addons/BoardList/BoardList.php index 985a0a95d..605be2093 100644 --- a/Sources/LightPortal/addons/BoardList/BoardList.php +++ b/Sources/LightPortal/addons/BoardList/BoardList.php @@ -13,7 +13,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -196,7 +196,7 @@ public static function prepareContent(&$content, $type, $block_id, $cache_time, if ($type !== 'board_list') return; - $board_list = Helpers::getFromCache('board_list_addon_b' . $block_id . '_u' . $context['user']['id'], 'getData', __CLASS__, $cache_time); + $board_list = Helpers::cache('board_list_addon_b' . $block_id . '_u' . $context['user']['id'], 'getData', __CLASS__, $cache_time); if (!empty($board_list)) { $context['current_board'] = $context['current_board'] ?? 0; diff --git a/Sources/LightPortal/addons/BoardNews/BoardNews.php b/Sources/LightPortal/addons/BoardNews/BoardNews.php index a94bb430b..4b2eb4e83 100644 --- a/Sources/LightPortal/addons/BoardNews/BoardNews.php +++ b/Sources/LightPortal/addons/BoardNews/BoardNews.php @@ -13,7 +13,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -194,7 +194,7 @@ public static function prepareContent(&$content, $type, $block_id, $cache_time, if ($type !== 'board_news') return; - $board_news = Helpers::getFromCache('board_news_addon_b' . $block_id . '_u' . $user_info['id'], 'getData', __CLASS__, $cache_time, $parameters); + $board_news = Helpers::cache('board_news_addon_b' . $block_id . '_u' . $user_info['id'], 'getData', __CLASS__, $cache_time, $parameters); if (!empty($board_news)) { ob_start(); diff --git a/Sources/LightPortal/addons/CodeMirror/CodeMirror.php b/Sources/LightPortal/addons/CodeMirror/CodeMirror.php index cf8c13c45..1492b5735 100644 --- a/Sources/LightPortal/addons/CodeMirror/CodeMirror.php +++ b/Sources/LightPortal/addons/CodeMirror/CodeMirror.php @@ -11,7 +11,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) diff --git a/Sources/LightPortal/addons/CurrentMonth/CurrentMonth.php b/Sources/LightPortal/addons/CurrentMonth/CurrentMonth.php index 565b1d360..81b8f951d 100644 --- a/Sources/LightPortal/addons/CurrentMonth/CurrentMonth.php +++ b/Sources/LightPortal/addons/CurrentMonth/CurrentMonth.php @@ -13,7 +13,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -188,7 +188,7 @@ public static function prepareContent(&$content, $type, $block_id, $cache_time) if ($type !== 'current_month') return; - $calendar_data = Helpers::getFromCache('current_month_addon_u' . $user_info['id'], 'getData', __CLASS__, $cache_time); + $calendar_data = Helpers::cache('current_month_addon_u' . $user_info['id'], 'getData', __CLASS__, $cache_time); if (!empty($calendar_data)) { ob_start(); diff --git a/Sources/LightPortal/addons/EasyMarkdownEditor/EasyMarkdownEditor.php b/Sources/LightPortal/addons/EasyMarkdownEditor/EasyMarkdownEditor.php index 74b839e97..68561db55 100644 --- a/Sources/LightPortal/addons/EasyMarkdownEditor/EasyMarkdownEditor.php +++ b/Sources/LightPortal/addons/EasyMarkdownEditor/EasyMarkdownEditor.php @@ -11,7 +11,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) diff --git a/Sources/LightPortal/addons/FaBoardIcons/FaBoardIcons.php b/Sources/LightPortal/addons/FaBoardIcons/FaBoardIcons.php index bfcce25e7..056eb28e6 100644 --- a/Sources/LightPortal/addons/FaBoardIcons/FaBoardIcons.php +++ b/Sources/LightPortal/addons/FaBoardIcons/FaBoardIcons.php @@ -11,7 +11,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) diff --git a/Sources/LightPortal/addons/FacebookComments/FacebookComments.php b/Sources/LightPortal/addons/FacebookComments/FacebookComments.php index a73099432..ccdbcde78 100644 --- a/Sources/LightPortal/addons/FacebookComments/FacebookComments.php +++ b/Sources/LightPortal/addons/FacebookComments/FacebookComments.php @@ -13,7 +13,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) diff --git a/Sources/LightPortal/addons/FlipsterCarousel/FlipsterCarousel.php b/Sources/LightPortal/addons/FlipsterCarousel/FlipsterCarousel.php index f548d2db5..28b9f9dd3 100644 --- a/Sources/LightPortal/addons/FlipsterCarousel/FlipsterCarousel.php +++ b/Sources/LightPortal/addons/FlipsterCarousel/FlipsterCarousel.php @@ -13,7 +13,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -245,7 +245,7 @@ public static function prepareContent(&$content, $type, $block_id, $cache_time, if ($type !== 'flipster_carousel') return; - $flipster_html = Helpers::getFromCache('flipster_carousel_addon_b' . $block_id, 'getHtml', __CLASS__, $cache_time, $block_id, $parameters); + $flipster_html = Helpers::cache('flipster_carousel_addon_b' . $block_id, 'getHtml', __CLASS__, $cache_time, $block_id, $parameters); if (!empty($flipster_html)) { loadCSSFile('https://cdn.jsdelivr.net/npm/jquery.flipster@1/dist/jquery.flipster.min.css', array('external' => true)); diff --git a/Sources/LightPortal/addons/FlipsterCarousel/langs/english.php b/Sources/LightPortal/addons/FlipsterCarousel/langs/english.php index b266e174f..6e74cc771 100644 --- a/Sources/LightPortal/addons/FlipsterCarousel/langs/english.php +++ b/Sources/LightPortal/addons/FlipsterCarousel/langs/english.php @@ -16,9 +16,9 @@ $txt['lp_flipster_carousel_addon_show_buttons'] = 'Display Previous/Next buttons'; $txt['lp_flipster_carousel_addon_images'] = 'Image list'; $txt['lp_flipster_carousel_addon_images_subtext'] = 'One image url per line. Example:

-https://example.com/image1.png|Image 1 title|Image 1 category
+https://picsum.photos/seed/picsum1/300/200|Image 1 title|Image 1 category
 
-https://example.com/image2.png|Image 2 title|Image 2 category +https://picsum.photos/seed/picsum2/300/200|Image 2 title|Image 2 category
'; $txt['lp_flipster_carousel_addon_prev'] = 'Previous'; diff --git a/Sources/LightPortal/addons/FlipsterCarousel/langs/polish.php b/Sources/LightPortal/addons/FlipsterCarousel/langs/polish.php index 8bd97a4b3..6e8767994 100644 --- a/Sources/LightPortal/addons/FlipsterCarousel/langs/polish.php +++ b/Sources/LightPortal/addons/FlipsterCarousel/langs/polish.php @@ -16,9 +16,9 @@ $txt['lp_flipster_carousel_addon_show_buttons'] = 'Pokaż przyciski Następny/poprzedni'; $txt['lp_flipster_carousel_addon_images'] = 'Lista obrazów'; $txt['lp_flipster_carousel_addon_images_subtext'] = 'Jeden adres URL obrazu na linię. Przykład:

-https://example.com/image1.png|Tytuł obrazu 1|Kategoria obrazu 1
+https://picsum.photos/seed/picsum1/300/200|Tytuł obrazu 1|Kategoria obrazu 1
 
-https://example.com/image2.png|Tytuł obrazu 2|Kategoria obrazu 2 +https://picsum.photos/seed/picsum2/300/200|Tytuł obrazu 2|Kategoria obrazu 2
'; $txt['lp_flipster_carousel_addon_prev'] = 'Poprzedni'; diff --git a/Sources/LightPortal/addons/FlipsterCarousel/langs/russian.php b/Sources/LightPortal/addons/FlipsterCarousel/langs/russian.php index 21dcd69f8..f0f5b5c48 100644 --- a/Sources/LightPortal/addons/FlipsterCarousel/langs/russian.php +++ b/Sources/LightPortal/addons/FlipsterCarousel/langs/russian.php @@ -16,9 +16,9 @@ $txt['lp_flipster_carousel_addon_show_buttons'] = 'Отображать кнопки «Предыдущая» и «Следующая»'; $txt['lp_flipster_carousel_addon_images'] = 'Список изображений'; $txt['lp_flipster_carousel_addon_images_subtext'] = 'Одна картинка в строке. Пример:

-https://example.com/image1.png|Заголовок 1|Категория 1
+https://picsum.photos/seed/picsum1/300/200|Заголовок 1|Категория 1
 
-https://example.com/image2.png|Заголовок 2|Категория 2 +https://picsum.photos/seed/picsum2/300/200|Заголовок 2|Категория 2
'; $txt['lp_flipster_carousel_addon_prev'] = 'Предыдущая'; diff --git a/Sources/LightPortal/addons/FlipsterCarousel/langs/ukrainian.php b/Sources/LightPortal/addons/FlipsterCarousel/langs/ukrainian.php index a93a9fb3e..9add65209 100644 --- a/Sources/LightPortal/addons/FlipsterCarousel/langs/ukrainian.php +++ b/Sources/LightPortal/addons/FlipsterCarousel/langs/ukrainian.php @@ -16,9 +16,9 @@ $txt['lp_flipster_carousel_addon_show_buttons'] = 'Відображати кнопки «Попередня» і «Наступна»'; $txt['lp_flipster_carousel_addon_images'] = 'Список зображень'; $txt['lp_flipster_carousel_addon_images_subtext'] = 'Одна картинка в рядку. Приклад:

-https://example.com/image1.png|Заголовок 1|Категорія 1
+https://picsum.photos/seed/picsum1/300/200|Заголовок 1|Категорія 1
 
-https://example.com/image2.png|Заголовок 2|Категорія 2 +https://picsum.photos/seed/picsum2/300/200|Заголовок 2|Категорія 2
'; $txt['lp_flipster_carousel_addon_prev'] = 'Попередня'; diff --git a/Sources/LightPortal/addons/FrontpageFlarumStyle/FrontpageFlarumStyle.php b/Sources/LightPortal/addons/FrontpageFlarumStyle/FrontpageFlarumStyle.php index 51892d361..251436bf2 100644 --- a/Sources/LightPortal/addons/FrontpageFlarumStyle/FrontpageFlarumStyle.php +++ b/Sources/LightPortal/addons/FrontpageFlarumStyle/FrontpageFlarumStyle.php @@ -11,7 +11,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -27,7 +27,7 @@ class FrontpageFlarumStyle * * @var string */ - public static $addon_type = 'other'; + public static $addon_type = 'frontpage'; /** * Load custom template for frontpage topics @@ -36,7 +36,7 @@ class FrontpageFlarumStyle * * @return void */ - public static function frontpageCustomTemplate() + public static function frontCustomTemplate() { global $modSettings, $context; @@ -47,9 +47,40 @@ public static function frontpageCustomTemplate() require_once(__DIR__ . '/Template.php'); + self::prepareFantomBLock(); + $context['sub_template'] = 'show_topics_as_flarum_style'; } + /** + * Make a fantom block + * + * Создаем фантомный блок + * + * @return void + */ + private static function prepareFantomBLock() + { + global $context; + + ob_start(); + + show_ffs_sidebar(); + + $content = ob_get_clean(); + + $context['lp_blocks']['left'][time()] = [ + 'id' => time(), + 'type' => 'flarum_style', + 'content' => $content, + 'title_class' => '', + 'title_style' => '', + 'content_class' => '', + 'content_style' => '', + 'title' => '' + ]; + } + /** * Get the list of categories with boards, considering the selected boards in the portal settings * diff --git a/Sources/LightPortal/addons/FrontpageFlarumStyle/Template.php b/Sources/LightPortal/addons/FrontpageFlarumStyle/Template.php index b2be1efd8..486246981 100644 --- a/Sources/LightPortal/addons/FrontpageFlarumStyle/Template.php +++ b/Sources/LightPortal/addons/FrontpageFlarumStyle/Template.php @@ -1,77 +1,89 @@ -
-
-
+ + '; +} + +/** + * Topics from selected boards as sources of articles (Flarum style) + * + * Темы из выбранных разделов в виде статей + * + * @return void + */ +function template_show_topics_as_flarum_style() +{ + global $context, $txt; + + echo ' +
+

', $context['page_title'], '

'; @@ -83,8 +95,8 @@ function template_show_topics_as_flarum_style() if (!empty($topic['image'])) { echo ' -
- ', $topic['subject'], ' +
+ ', $topic['subject'], '
'; } else { echo ' @@ -96,18 +108,25 @@ function template_show_topics_as_flarum_style() echo '

- ', $topic['subject'], '', $topic['is_new'] ? ' + ', $topic['subject'], '', $topic['is_new'] ? ' ' . $txt['new'] . ' ' : '', '

'; + if (!empty($topic['num_replies'])) { + echo ' + '; + } + if (!empty($topic['author_id'])) { echo ' ', $topic['author_name'], ', '; - } else + } else { echo $topic['author_name'], ', '; + } - echo $topic['date'], ' + echo ' + ', $topic['date'], '
'; if (!empty($topic['teaser'])) { diff --git a/Sources/LightPortal/addons/HidingBlocks/HidingBlocks.php b/Sources/LightPortal/addons/HidingBlocks/HidingBlocks.php index 23c06d190..584cdc40d 100644 --- a/Sources/LightPortal/addons/HidingBlocks/HidingBlocks.php +++ b/Sources/LightPortal/addons/HidingBlocks/HidingBlocks.php @@ -2,6 +2,8 @@ namespace Bugo\LightPortal\Addons\HidingBlocks; +use Bugo\LightPortal\Helpers; + /** * HidingBlocks * @@ -11,7 +13,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -122,7 +124,7 @@ public static function prepareBlockFields() if (isset($context['lp_block']['options']['parameters']['hidden_breakpoints'])) { $context['lp_block']['options']['parameters']['hidden_breakpoints'] = is_array($context['lp_block']['options']['parameters']['hidden_breakpoints']) ? $context['lp_block']['options']['parameters']['hidden_breakpoints'] : explode(',', $context['lp_block']['options']['parameters']['hidden_breakpoints']); } else - $context['lp_block']['options']['parameters']['hidden_breakpoints'] = $_POST['hidden_breakpoints'] ?? []; + $context['lp_block']['options']['parameters']['hidden_breakpoints'] = Helpers::post('hidden_breakpoints', []); $context['posting_fields']['hidden_breakpoints']['label']['text'] = $txt['lp_hiding_blocks_addon_hidden_breakpoints']; $context['posting_fields']['hidden_breakpoints']['input'] = array( diff --git a/Sources/LightPortal/addons/KarmaPostRating/KarmaPostRating.php b/Sources/LightPortal/addons/KarmaPostRating/KarmaPostRating.php index c41c10127..4eefbb124 100644 --- a/Sources/LightPortal/addons/KarmaPostRating/KarmaPostRating.php +++ b/Sources/LightPortal/addons/KarmaPostRating/KarmaPostRating.php @@ -11,7 +11,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -37,15 +37,19 @@ class KarmaPostRating * @param array $custom_tables * @return void */ - public static function frontTopics(&$custom_columns, &$custom_tables) + public static function frontTopics(&$custom_columns, &$custom_tables, &$custom_wheres, &$custom_parameters) { global $modSettings; if (!class_exists('\Bugo\KarmaPostRating\Subs')) return; - $custom_columns[] = 'IF (kpr.rating_plus || kpr.rating_minus, kpr.rating_plus + kpr.rating_minus' . (!empty($modSettings['kpr_num_topics_factor']) ? ' + t.num_replies' : '') . ', 0) AS rating'; - $custom_tables[] = 'LEFT JOIN {db_prefix}kpr_ratings AS kpr ON (t.id_first_msg = kpr.item_id AND kpr.item = "message")'; + $custom_columns[] = 'IF (kpr.rating_plus || kpr.rating_minus, kpr.rating_plus + kpr.rating_minus' . (!empty($modSettings['kpr_num_topics_factor']) + ? ' + t.num_replies' : '') . ', 0) AS rating'; + + $custom_tables[] = 'LEFT JOIN {db_prefix}kpr_ratings AS kpr ON (t.id_first_msg = kpr.item_id AND kpr.item = {string:kpr_item_type})'; + + $custom_parameters['kpr_item_type'] = 'message'; } /** @@ -67,7 +71,7 @@ public static function frontTopicsOutput(&$topics, $row) * * @return void */ - public static function frontpageAssets() + public static function frontAssets() { global $context; diff --git a/Sources/LightPortal/addons/LanguageAccess/LanguageAccess.php b/Sources/LightPortal/addons/LanguageAccess/LanguageAccess.php index db96494f9..c0a444bf4 100644 --- a/Sources/LightPortal/addons/LanguageAccess/LanguageAccess.php +++ b/Sources/LightPortal/addons/LanguageAccess/LanguageAccess.php @@ -2,6 +2,8 @@ namespace Bugo\LightPortal\Addons\LanguageAccess; +use Bugo\LightPortal\Helpers; + /** * LanguageAccess * @@ -11,7 +13,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -108,7 +110,7 @@ public static function prepareBlockFields() if (isset($context['lp_block']['options']['parameters']['allowed_languages'])) { $context['lp_block']['options']['parameters']['allowed_languages'] = is_array($context['lp_block']['options']['parameters']['allowed_languages']) ? $context['lp_block']['options']['parameters']['allowed_languages'] : explode(',', $context['lp_block']['options']['parameters']['allowed_languages']); } else - $context['lp_block']['options']['parameters']['allowed_languages'] = $_POST['allowed_languages'] ?? []; + $context['lp_block']['options']['parameters']['allowed_languages'] = Helpers::post('allowed_languages', []); $context['posting_fields']['allowed_languages']['label']['text'] = $txt['lp_language_access_addon_allowed_languages']; $context['posting_fields']['allowed_languages']['input'] = array( diff --git a/Sources/LightPortal/addons/Likely/Likely.php b/Sources/LightPortal/addons/Likely/Likely.php index 8cecfe30a..fdbc78615 100644 --- a/Sources/LightPortal/addons/Likely/Likely.php +++ b/Sources/LightPortal/addons/Likely/Likely.php @@ -11,7 +11,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) diff --git a/Sources/LightPortal/addons/Markdown/Markdown.php b/Sources/LightPortal/addons/Markdown/Markdown.php index cb7d68b9f..a3417cf9d 100644 --- a/Sources/LightPortal/addons/Markdown/Markdown.php +++ b/Sources/LightPortal/addons/Markdown/Markdown.php @@ -11,7 +11,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) diff --git a/Sources/LightPortal/addons/Markdown/Michelf/MarkdownSMF.php b/Sources/LightPortal/addons/Markdown/Michelf/MarkdownSMF.php index f285d5659..955bfc3bf 100644 --- a/Sources/LightPortal/addons/Markdown/Michelf/MarkdownSMF.php +++ b/Sources/LightPortal/addons/Markdown/Michelf/MarkdownSMF.php @@ -11,7 +11,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ class MarkdownSMF extends \Michelf\MarkdownExtra diff --git a/Sources/LightPortal/addons/News/News.php b/Sources/LightPortal/addons/News/News.php index dd1cbb830..1298ed822 100644 --- a/Sources/LightPortal/addons/News/News.php +++ b/Sources/LightPortal/addons/News/News.php @@ -13,7 +13,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -123,6 +123,7 @@ public static function prepareBlockFields() * * Получаем новость форума * + * @param int $item * @return string */ public static function getData($item = 0) diff --git a/Sources/LightPortal/addons/PageList/PageList.php b/Sources/LightPortal/addons/PageList/PageList.php index 99b4bde08..bf0d21087 100644 --- a/Sources/LightPortal/addons/PageList/PageList.php +++ b/Sources/LightPortal/addons/PageList/PageList.php @@ -13,7 +13,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -141,7 +141,7 @@ public static function getData(array $parameters) { global $smcFunc, $txt, $context; - $titles = Helpers::getFromCache('all_titles', 'getAllTitles', '\Bugo\LightPortal\Subs', LP_CACHE_TIME, 'page'); + $titles = Helpers::cache('all_titles', 'getAllTitles', '\Bugo\LightPortal\Subs', LP_CACHE_TIME, 'page'); $request = $smcFunc['db_query']('', ' SELECT @@ -186,7 +186,7 @@ public static function getData(array $parameters) } $smcFunc['db_free_result']($request); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; return $pages; } @@ -210,7 +210,7 @@ public static function prepareContent(&$content, $type, $block_id, $cache_time, if ($type !== 'page_list') return; - $page_list = Helpers::getFromCache('page_list_addon_b' . $block_id . '_u' . $user_info['id'], 'getData', __CLASS__, $cache_time, $parameters); + $page_list = Helpers::cache('page_list_addon_b' . $block_id . '_u' . $user_info['id'], 'getData', __CLASS__, $cache_time, $parameters); ob_start(); @@ -219,7 +219,7 @@ public static function prepareContent(&$content, $type, $block_id, $cache_time,
    '; foreach ($page_list as $page) { - if (empty($title = Helpers::getPublicTitle($page))) + if (empty($title = Helpers::getTitle($page))) continue; echo ' @@ -235,8 +235,9 @@ public static function prepareContent(&$content, $type, $block_id, $cache_time, echo '
'; - } else - echo $txt['lp_page_list_addon_no_items']; + } else { + echo '
', $txt['lp_page_list_addon_no_items'], '
'; + } $content = ob_get_clean(); } diff --git a/Sources/LightPortal/addons/PrettyUrls/PrettyUrls.php b/Sources/LightPortal/addons/PrettyUrls/PrettyUrls.php index de5d0a45c..395519ea4 100644 --- a/Sources/LightPortal/addons/PrettyUrls/PrettyUrls.php +++ b/Sources/LightPortal/addons/PrettyUrls/PrettyUrls.php @@ -11,7 +11,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) diff --git a/Sources/LightPortal/addons/RandomTopics/RandomTopics.php b/Sources/LightPortal/addons/RandomTopics/RandomTopics.php index 619424370..8bd8664e7 100644 --- a/Sources/LightPortal/addons/RandomTopics/RandomTopics.php +++ b/Sources/LightPortal/addons/RandomTopics/RandomTopics.php @@ -13,7 +13,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -115,31 +115,37 @@ public static function prepareBlockFields() */ public static function getData($num_topics) { - global $db_type, $smcFunc, $modSettings, $user_info, $context, $settings, $scripturl; + global $modSettings, $user_info, $db_type, $smcFunc, $context, $settings, $scripturl; if (empty($num_topics)) return []; + $ignore_boards = !empty($modSettings['recycle_board']) ? [(int) $modSettings['recycle_board']] : []; + + if (!empty($modSettings['allow_ignore_boards'])) { + $ignore_boards = array_unique(array_merge($ignore_boards, $user_info['ignoreboards'])); + } + if ($db_type == 'postgresql') { $request = $smcFunc['db_query']('', ' WITH RECURSIVE r AS ( WITH b AS ( SELECT min(t.id_topic), ( SELECT t.id_topic FROM {db_prefix}topics AS t - WHERE t.approved = {int:is_approved}' . (!empty($modSettings['recycle_board']) ? ' - AND t.id_board != {int:recycle_board}' : '') . ' + WHERE t.approved = {int:is_approved}' . (!empty($ignore_boards) ? ' + AND t.id_board NOT IN ({array_int:ignore_boards})' : '') . ' ORDER BY t.id_topic DESC LIMIT 1 OFFSET {int:limit} - 1 ) max FROM {db_prefix}topics AS t - WHERE t.approved = {int:is_approved}' . (!empty($modSettings['recycle_board']) ? ' - AND t.id_board != {int:recycle_board}' : '') . ' + WHERE t.approved = {int:is_approved}' . (!empty($ignore_boards) ? ' + AND t.id_board NOT IN ({array_int:ignore_boards})' : '') . ' ) ( SELECT t.id_topic, min, max, array[]::integer[] || t.id_topic AS a, 0 AS n FROM {db_prefix}topics AS t, b - WHERE t.id_topic >= min + ((max - min) * random())::int' . (!empty($modSettings['recycle_board']) ? ' - AND t.id_board != {int:recycle_board}' : '') . ' + WHERE t.id_topic >= min + ((max - min) * random())::int' . (!empty($ignore_boards) ? ' + AND t.id_board NOT IN ({array_int:ignore_boards})' : '') . ' AND t.approved = {int:is_approved} LIMIT 1 ) UNION ALL ( @@ -147,8 +153,8 @@ public static function getData($num_topics) FROM {db_prefix}topics AS t, r WHERE t.id_topic >= min + ((max - min) * random())::int AND t.id_topic <> all(a) - AND r.n + 1 < {int:limit}' . (!empty($modSettings['recycle_board']) ? ' - AND t.id_board != {int:recycle_board}' : '') . ' + AND r.n + 1 < {int:limit}' . (!empty($ignore_boards) ? ' + AND t.id_board NOT IN ({array_int:ignore_boards})' : '') . ' AND t.approved = {int:is_approved} LIMIT 1 ) @@ -158,7 +164,7 @@ public static function getData($num_topics) WHERE r.id_topic = t.id_topic', array( 'is_approved' => 1, - 'recycle_board' => !empty($modSettings['recycle_board']) ? (int) $modSettings['recycle_board'] : null, + 'ignore_boards' => $ignore_boards, 'limit' => $num_topics ) ); @@ -168,7 +174,7 @@ public static function getData($num_topics) $topic_ids[] = $row['id_topic']; $smcFunc['db_free_result']($request); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; if (empty($topic_ids)) return self::getData($num_topics - 1); @@ -181,11 +187,10 @@ public static function getData($num_topics) FROM {db_prefix}topics AS t INNER JOIN {db_prefix}messages AS ml ON (t.id_last_msg = ml.id_msg) INNER JOIN {db_prefix}messages AS mf ON (t.id_first_msg = mf.id_msg) - LEFT JOIN {db_prefix}members AS mem ON (mf.id_member = mem.id_member)' . (!$user_info['is_guest'] ? ' + LEFT JOIN {db_prefix}members AS mem ON (mf.id_member = mem.id_member)' . ($user_info['is_guest'] ? '' : ' LEFT JOIN {db_prefix}log_topics AS lt ON (t.id_topic = lt.id_topic AND lt.id_member = {int:current_member}) - LEFT JOIN {db_prefix}log_mark_read AS lmr ON (t.id_board = lmr.id_board AND lmr.id_member = {int:current_member})' : '') . ' - WHERE t.id_topic IN ({array_int:topic_ids})' . (!empty($modSettings['allow_ignore_boards']) ? ' - AND t.id_board NOT IN (SELECT ignore_boards FROM {db_prefix}members WHERE id_member = {int:current_member})' : ''), + LEFT JOIN {db_prefix}log_mark_read AS lmr ON (t.id_board = lmr.id_board AND lmr.id_member = {int:current_member})') . ' + WHERE t.id_topic IN ({array_int:topic_ids})', array( 'current_member' => $user_info['id'], 'topic_ids' => $topic_ids @@ -200,19 +205,17 @@ public static function getData($num_topics) FROM {db_prefix}topics AS t INNER JOIN {db_prefix}messages AS ml ON (t.id_last_msg = ml.id_msg) INNER JOIN {db_prefix}messages AS mf ON (t.id_first_msg = mf.id_msg) - LEFT JOIN {db_prefix}members AS mem ON (mf.id_member = mem.id_member)' . (!$user_info['is_guest'] ? ' + LEFT JOIN {db_prefix}members AS mem ON (mf.id_member = mem.id_member)' . ($user_info['is_guest'] ? '' : ' LEFT JOIN {db_prefix}log_topics AS lt ON (t.id_topic = lt.id_topic AND lt.id_member = {int:current_member}) - LEFT JOIN {db_prefix}log_mark_read AS lmr ON (t.id_board = lmr.id_board AND lmr.id_member = {int:current_member})' : '') . ' - WHERE t.approved = {int:is_approved}' . (!empty($modSettings['recycle_board']) ? ' - AND t.id_board != {int:recycle_board}' : '') . (!empty($modSettings['allow_ignore_boards']) ? ' - AND t.id_board NOT IN (SELECT ignore_boards FROM {db_prefix}members WHERE id_member = {int:current_member})' : '') . ' - AND t.id_topic IN (SELECT id_topic FROM {db_prefix}topics) + LEFT JOIN {db_prefix}log_mark_read AS lmr ON (t.id_board = lmr.id_board AND lmr.id_member = {int:current_member})') . ' + WHERE t.approved = {int:is_approved} + AND t.id_board NOT IN ({array_int:ignore_boards}) ORDER BY RAND() LIMIT {int:limit}', array( 'current_member' => $user_info['id'], 'is_approved' => 1, - 'recycle_board' => !empty($modSettings['recycle_board']) ? (int) $modSettings['recycle_board'] : null, + 'ignore_boards' => $ignore_boards, 'limit' => $num_topics ) ); @@ -224,10 +227,11 @@ public static function getData($num_topics) $topics = []; while ($row = $smcFunc['db_fetch_assoc']($request)) { - if (!empty($modSettings['messageIconChecks_enable']) && !isset($icon_sources[$row['icon']])) + if (!empty($modSettings['messageIconChecks_enable']) && !isset($icon_sources[$row['icon']])) { $icon_sources[$row['icon']] = file_exists($settings['theme_dir'] . '/images/post/' . $row['icon'] . '.png') ? 'images_url' : 'default_images_url'; - elseif (!isset($icon_sources[$row['icon']])) + } elseif (!isset($icon_sources[$row['icon']])) { $icon_sources[$row['icon']] = 'images_url'; + } $topics[] = array( 'poster' => empty($row['id_member']) ? $row['poster_name'] : '' . $row['poster_name'] . '', @@ -239,7 +243,7 @@ public static function getData($num_topics) } $smcFunc['db_free_result']($request); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; return $topics; } @@ -263,7 +267,13 @@ public static function prepareContent(&$content, $type, $block_id, $cache_time, if ($type !== 'random_topics') return; - $random_topics = Helpers::getFromCache('random_topics_addon_b' . $block_id . '_u' . $user_info['id'], 'getData', __CLASS__, $cache_time, $parameters['num_topics']); + $random_topics = Helpers::cache( + 'random_topics_addon_b' . $block_id . '_u' . $user_info['id'], + 'getData', + __CLASS__, + $cache_time, + $parameters['num_topics'] + ); if (!empty($random_topics)) { ob_start(); @@ -271,7 +281,7 @@ public static function prepareContent(&$content, $type, $block_id, $cache_time, echo '
    '; - foreach ($topics as $topic) { + foreach ($random_topics as $topic) { echo '
  • ', ($topic['is_new'] ? ' ' . $txt['new'] . '' : ''), $topic['icon'], ' ', $topic['link'], ' diff --git a/Sources/LightPortal/addons/RecentAttachments/RecentAttachments.php b/Sources/LightPortal/addons/RecentAttachments/RecentAttachments.php index 55e158abf..7e39925f2 100644 --- a/Sources/LightPortal/addons/RecentAttachments/RecentAttachments.php +++ b/Sources/LightPortal/addons/RecentAttachments/RecentAttachments.php @@ -13,7 +13,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -188,7 +188,13 @@ public static function prepareContent(&$content, $type, $block_id, $cache_time, if ($type !== 'recent_attachments') return; - $attachment_list = Helpers::getFromCache('recent_attachments_addon_b' . $block_id . '_u' . $user_info['id'], 'getData', __CLASS__, $cache_time, $parameters); + $attachment_list = Helpers::cache( + 'recent_attachments_addon_b' . $block_id . '_u' . $user_info['id'], + 'getData', + __CLASS__, + $cache_time, + $parameters + ); if (!empty($attachment_list)) { ob_start(); diff --git a/Sources/LightPortal/addons/RecentPosts/RecentPosts.php b/Sources/LightPortal/addons/RecentPosts/RecentPosts.php index d2c96dd73..3602d9b48 100644 --- a/Sources/LightPortal/addons/RecentPosts/RecentPosts.php +++ b/Sources/LightPortal/addons/RecentPosts/RecentPosts.php @@ -13,7 +13,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -324,7 +324,7 @@ public static function getData($parameters) $item['poster']['avatar'] = $memberContext[$item['poster']['id']]['avatar']['image']; } else { - $item['poster']['avatar'] = ''; + $item['poster']['avatar'] = ''. $item['poster']['name'] . ''; } return $item; @@ -353,7 +353,13 @@ public static function prepareContent(&$content, $type, $block_id, $cache_time, if ($type !== 'recent_posts') return; - $recent_posts = Helpers::getFromCache('recent_posts_addon_b' . $block_id . '_u' . $user_info['id'], 'getData', __CLASS__, $parameters['update_interval'] ?? $cache_time, $parameters); + $recent_posts = Helpers::cache( + 'recent_posts_addon_b' . $block_id . '_u' . $user_info['id'], + 'getData', + __CLASS__, + $parameters['update_interval'] ?? $cache_time, + $parameters + ); if (!empty($recent_posts)) { ob_start(); @@ -372,8 +378,10 @@ public static function prepareContent(&$content, $type, $block_id, $cache_time, ', $post['poster']['avatar'], ''; if ($post['is_new']) + /* echo ' + ', $txt['new'], ''; */ echo ' - ', $txt['new'], ''; + ', $txt['new'], '1'; echo ' ', $post[$parameters['link_type']]; diff --git a/Sources/LightPortal/addons/RecentTopics/RecentTopics.php b/Sources/LightPortal/addons/RecentTopics/RecentTopics.php index 8db1f7382..8085caf73 100644 --- a/Sources/LightPortal/addons/RecentTopics/RecentTopics.php +++ b/Sources/LightPortal/addons/RecentTopics/RecentTopics.php @@ -13,7 +13,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -230,7 +230,7 @@ public static function getData($parameters) $item['poster']['avatar'] = $memberContext[$item['poster']['id']]['avatar']['image']; } else { - $item['poster']['avatar'] = ''; + $item['poster']['avatar'] = ''. $item['poster']['name'] . ''; } return $item; @@ -259,7 +259,13 @@ public static function prepareContent(&$content, $type, $block_id, $cache_time, if ($type !== 'recent_topics') return; - $recent_topics = Helpers::getFromCache('recent_topics_addon_b' . $block_id . '_u' . $user_info['id'], 'getData', __CLASS__, $parameters['update_interval'] ?? $cache_time, $parameters); + $recent_topics = Helpers::cache( + 'recent_topics_addon_b' . $block_id . '_u' . $user_info['id'], + 'getData', + __CLASS__, + $parameters['update_interval'] ?? $cache_time, + $parameters + ); if (!empty($recent_topics)) { ob_start(); @@ -276,8 +282,10 @@ public static function prepareContent(&$content, $type, $block_id, $cache_time, ', $topic['poster']['avatar'], ''; if ($topic['is_new']) + /* echo ' + ', $txt['new'], ''; */ echo ' - ', $txt['new'], ''; + ', $txt['new'], ''; echo $topic['icon'], ' ', $topic['link']; diff --git a/Sources/LightPortal/addons/RssFeed/RssFeed.php b/Sources/LightPortal/addons/RssFeed/RssFeed.php index 2c61d7608..6ece3a8a4 100644 --- a/Sources/LightPortal/addons/RssFeed/RssFeed.php +++ b/Sources/LightPortal/addons/RssFeed/RssFeed.php @@ -13,7 +13,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -154,7 +154,7 @@ public static function prepareContent(&$content, $type, $block_id, $cache_time, if ($type !== 'rss_feed') return; - $rss_feed = Helpers::getFromCache('rss_feed_addon_b' . $block_id, 'getData', __CLASS__, $cache_time, $parameters['url']); + $rss_feed = Helpers::cache('rss_feed_addon_b' . $block_id, 'getData', __CLASS__, $cache_time, $parameters['url']); if (!empty($rss_feed)) { ob_start(); diff --git a/Sources/LightPortal/addons/SlickSlider/SlickSlider.php b/Sources/LightPortal/addons/SlickSlider/SlickSlider.php index e378d28cb..0eaa66100 100644 --- a/Sources/LightPortal/addons/SlickSlider/SlickSlider.php +++ b/Sources/LightPortal/addons/SlickSlider/SlickSlider.php @@ -13,7 +13,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -310,7 +310,7 @@ public static function prepareContent(&$content, $type, $block_id, $cache_time, if ($type !== 'slick_slider') return; - $slick_slider_html = Helpers::getFromCache('slick_slider_addon_b' . $block_id, 'getHtml', __CLASS__, $cache_time, $block_id, $parameters); + $slick_slider_html = Helpers::cache('slick_slider_addon_b' . $block_id, 'getHtml', __CLASS__, $cache_time, $block_id, $parameters); if (!empty($slick_slider_html)) { loadCSSFile('https://cdn.jsdelivr.net/npm/slick-carousel@1/slick/slick.css', array('external' => true)); diff --git a/Sources/LightPortal/addons/SlickSlider/langs/english.php b/Sources/LightPortal/addons/SlickSlider/langs/english.php index 99e52dc6e..9cdc1fe2b 100644 --- a/Sources/LightPortal/addons/SlickSlider/langs/english.php +++ b/Sources/LightPortal/addons/SlickSlider/langs/english.php @@ -13,7 +13,11 @@ $txt['lp_slick_slider_addon_speed'] = 'Transition speed, ms'; $txt['lp_slick_slider_addon_images'] = 'Image list'; $txt['lp_slick_slider_addon_images_subtext'] = 'One image url per line. Example:
    
    -https://example.com/image1.png
    +https://picsum.photos/seed/picsum1/300/200
     
    -https://example.com/image2.png +https://picsum.photos/seed/picsum2/300/200 +
    +https://picsum.photos/seed/picsum3/300/200 +
    +https://picsum.photos/seed/picsum4/300/200
    '; \ No newline at end of file diff --git a/Sources/LightPortal/addons/SlickSlider/langs/polish.php b/Sources/LightPortal/addons/SlickSlider/langs/polish.php index 59566e430..489b1295e 100644 --- a/Sources/LightPortal/addons/SlickSlider/langs/polish.php +++ b/Sources/LightPortal/addons/SlickSlider/langs/polish.php @@ -13,7 +13,11 @@ $txt['lp_slick_slider_addon_speed'] = 'Prędkość przejścia, ms'; $txt['lp_slick_slider_addon_images'] = 'Lista obrazów'; $txt['lp_slick_slider_addon_images_subtext'] = 'Jeden URL obrazu w linii. Przykład:
    
    -https://example.com/image1.png
    +https://picsum.photos/seed/picsum1/300/200
     
    -https://example.com/image2.png +https://picsum.photos/seed/picsum2/300/200 +
    +https://picsum.photos/seed/picsum3/300/200 +
    +https://picsum.photos/seed/picsum4/300/200
    '; diff --git a/Sources/LightPortal/addons/SlickSlider/langs/russian.php b/Sources/LightPortal/addons/SlickSlider/langs/russian.php index d55c03725..4fdc0493a 100644 --- a/Sources/LightPortal/addons/SlickSlider/langs/russian.php +++ b/Sources/LightPortal/addons/SlickSlider/langs/russian.php @@ -13,7 +13,11 @@ $txt['lp_slick_slider_addon_speed'] = 'Скорость перехода между слайдами (в миллисекундах)'; $txt['lp_slick_slider_addon_images'] = 'Список изображений'; $txt['lp_slick_slider_addon_images_subtext'] = 'Одна картинка в строке. Пример:
    
    -https://example.com/image1.png
    +https://picsum.photos/seed/picsum1/300/200
     
    -https://example.com/image2.png +https://picsum.photos/seed/picsum2/300/200 +
    +https://picsum.photos/seed/picsum3/300/200 +
    +https://picsum.photos/seed/picsum4/300/200
    '; \ No newline at end of file diff --git a/Sources/LightPortal/addons/SlickSlider/langs/ukrainian.php b/Sources/LightPortal/addons/SlickSlider/langs/ukrainian.php index 5e7d7d2d5..8ba72806b 100644 --- a/Sources/LightPortal/addons/SlickSlider/langs/ukrainian.php +++ b/Sources/LightPortal/addons/SlickSlider/langs/ukrainian.php @@ -13,7 +13,11 @@ $txt['lp_slick_slider_addon_speed'] = 'Швидкість переходу між слайдами (в мілісекундах)'; $txt['lp_slick_slider_addon_images'] = 'Список зображень'; $txt['lp_slick_slider_addon_images_subtext'] = 'Одна картинка в рядку. Приклад:
    
    -https://example.com/image1.png
    +https://picsum.photos/seed/picsum1/300/200
     
    -https://example.com/image2.png +https://picsum.photos/seed/picsum2/300/200 +
    +https://picsum.photos/seed/picsum3/300/200 +
    +https://picsum.photos/seed/picsum4/300/200
    '; \ No newline at end of file diff --git a/Sources/LightPortal/addons/TagList/TagList.php b/Sources/LightPortal/addons/TagList/TagList.php index 0a210dd02..419532fb3 100644 --- a/Sources/LightPortal/addons/TagList/TagList.php +++ b/Sources/LightPortal/addons/TagList/TagList.php @@ -13,7 +13,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -120,7 +120,7 @@ public static function prepareBlockFields() */ public static function getAllTopicKeywords() { - global $smcFunc, $scripturl, $context; + global $smcFunc, $scripturl; if (!class_exists('\Bugo\Optimus\Keywords')) return []; @@ -144,7 +144,7 @@ public static function getAllTopicKeywords() } $smcFunc['db_free_result']($request); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; return $keywords; } @@ -157,6 +157,8 @@ public static function getAllTopicKeywords() * @param string $content * @param string $type * @param int $block_id + * @param int $cache_time + * @param array $parameters * @return void */ public static function prepareContent(&$content, $type, $block_id, $cache_time, $parameters) @@ -167,9 +169,11 @@ public static function prepareContent(&$content, $type, $block_id, $cache_time, return; if ($parameters['source'] == 'lp_tags') { - $tag_list = Helpers::getFromCache('tag_list_addon_b' . $block_id . '_u' . $user_info['id'], 'getAll', '\Bugo\LightPortal\Tag', $cache_time, ...array(0, 0, 'value')); + $tag_list = Helpers::cache( + 'tag_list_addon_b' . $block_id . '_u' . $user_info['id'], 'getAll', '\Bugo\LightPortal\Tag', $cache_time, ...array(0, 0, 'value') + ); } else { - $tag_list = Helpers::getFromCache('tag_list_addon_b' . $block_id . '_u' . $user_info['id'], 'getAllTopicKeywords', __CLASS__, $cache_time); + $tag_list = Helpers::cache('tag_list_addon_b' . $block_id . '_u' . $user_info['id'], 'getAllTopicKeywords', __CLASS__, $cache_time); } ob_start(); @@ -179,8 +183,9 @@ public static function prepareContent(&$content, $type, $block_id, $cache_time, echo ' ', $tag['value'], ' ', $tag['frequency'], ''; } - } else + } else { echo $txt['lp_no_tags']; + } $content = ob_get_clean(); } diff --git a/Sources/LightPortal/addons/ThemeSwitcher/ThemeSwitcher.php b/Sources/LightPortal/addons/ThemeSwitcher/ThemeSwitcher.php index 2c48d528a..af7266436 100644 --- a/Sources/LightPortal/addons/ThemeSwitcher/ThemeSwitcher.php +++ b/Sources/LightPortal/addons/ThemeSwitcher/ThemeSwitcher.php @@ -13,7 +13,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -39,31 +39,12 @@ class ThemeSwitcher */ public static function getAvailableThemes() { - global $modSettings, $smcFunc, $context; + global $modSettings; if (empty($modSettings['knownThemes'])) return []; - $request = $smcFunc['db_query']('', ' - SELECT id_theme, value - FROM {db_prefix}themes - WHERE id_member = 0 - AND variable = {string:name} - AND id_theme IN ({array_int:themes})', - array( - 'name' => 'name', - 'themes' => explode(',', $modSettings['knownThemes']) - ) - ); - - $available_themes = []; - while ($row = $smcFunc['db_fetch_row']($request)) - $available_themes[$row[0]] = $row[1]; - - $smcFunc['db_free_result']($request); - $context['lp_num_queries']++; - - return $available_themes; + return array_intersect_key(Helpers::getForumThemes(), array_flip(explode(',', $modSettings['knownThemes']))); } /** @@ -84,7 +65,7 @@ public static function prepareContent(&$content, $type, $block_id, $cache_time) if ($type !== 'theme_switcher') return; - $available_themes = Helpers::getFromCache('theme_switcher_addon', 'getAvailableThemes', __CLASS__, $cache_time); + $available_themes = Helpers::cache('theme_switcher_addon', 'getAvailableThemes', __CLASS__, $cache_time); if (!empty($available_themes)) { ob_start(); @@ -111,9 +92,7 @@ function lp_block_', $block_id, '_themeswitcher_change() { search = search != "" ? search + ";" : "?"; window.location = window.location.origin + window.location.pathname + search + "theme=" + lp_block_', $block_id, '_themeswitcher_theme_id; } - '; - - echo ' +
'; $content = ob_get_clean(); diff --git a/Sources/LightPortal/addons/Todays/Todays.php b/Sources/LightPortal/addons/Todays/Todays.php index 6e888bce2..2ff718cbe 100644 --- a/Sources/LightPortal/addons/Todays/Todays.php +++ b/Sources/LightPortal/addons/Todays/Todays.php @@ -2,8 +2,6 @@ namespace Bugo\LightPortal\Addons\Todays; -use Bugo\LightPortal\Helpers; - /** * Todays * @@ -13,7 +11,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -63,8 +61,6 @@ public static function blockOptions(&$options) */ public static function validateBlockData(&$parameters, $type) { - global $context; - if ($type !== 'todays') return; diff --git a/Sources/LightPortal/addons/TopBoards/TopBoards.php b/Sources/LightPortal/addons/TopBoards/TopBoards.php index bb62ec7fa..0cac09a27 100644 --- a/Sources/LightPortal/addons/TopBoards/TopBoards.php +++ b/Sources/LightPortal/addons/TopBoards/TopBoards.php @@ -13,7 +13,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -127,6 +127,7 @@ public static function getData($num_boards) global $boarddir; require_once($boarddir . '/SSI.php'); + return ssi_topBoards($num_boards, 'array'); } @@ -149,7 +150,7 @@ public static function prepareContent(&$content, $type, $block_id, $cache_time, if ($type !== 'top_boards') return; - $top_boards = Helpers::getFromCache('top_boards_addon_b' . $block_id . '_u' . $user_info['id'], 'getData', __CLASS__, $cache_time, $parameters); + $top_boards = Helpers::cache('top_boards_addon_b' . $block_id . '_u' . $user_info['id'], 'getData', __CLASS__, $cache_time, $parameters['num_boards']); if (!empty($top_boards)) { ob_start(); diff --git a/Sources/LightPortal/addons/TopPages/TopPages.php b/Sources/LightPortal/addons/TopPages/TopPages.php index 096fea7ef..f030076ef 100644 --- a/Sources/LightPortal/addons/TopPages/TopPages.php +++ b/Sources/LightPortal/addons/TopPages/TopPages.php @@ -13,7 +13,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -158,9 +158,9 @@ public static function prepareBlockFields() */ public static function getData($parameters) { - global $smcFunc, $scripturl, $context; + global $smcFunc, $scripturl; - $titles = Helpers::getFromCache('all_titles', 'getAllTitles', '\Bugo\LightPortal\Subs', LP_CACHE_TIME, 'page'); + $titles = Helpers::cache('all_titles', 'getAllTitles', '\Bugo\LightPortal\Subs', LP_CACHE_TIME, 'page'); $request = $smcFunc['db_query']('', ' SELECT page_id, alias, type, num_views, num_comments @@ -171,7 +171,6 @@ public static function getData($parameters) ORDER BY ' . ($parameters['popularity_type'] == 'comments' ? 'num_comments' : 'num_views') . ' DESC LIMIT {int:limit}', array( - 'type' => 'page', 'status' => 1, 'current_time' => time(), 'permissions' => Helpers::getPermissions(), @@ -193,7 +192,7 @@ public static function getData($parameters) } $smcFunc['db_free_result']($request); - $context['lp_num_queries']++; + $smcFunc['lp_num_queries']++; return $pages; } @@ -217,7 +216,7 @@ public static function prepareContent(&$content, $type, $block_id, $cache_time, if ($type !== 'top_pages') return; - $top_pages = Helpers::getFromCache('top_pages_addon_b' . $block_id . '_u' . $user_info['id'], 'getData', __CLASS__, $cache_time, $parameters); + $top_pages = Helpers::cache('top_pages_addon_b' . $block_id . '_u' . $user_info['id'], 'getData', __CLASS__, $cache_time, $parameters); ob_start(); @@ -231,7 +230,7 @@ public static function prepareContent(&$content, $type, $block_id, $cache_time,
'; foreach ($top_pages as $page) { - if ($page['num_' . $parameters['popularity_type']] < 1 || empty($title = Helpers::getPublicTitle($page))) + if ($page['num_' . $parameters['popularity_type']] < 1 || empty($title = Helpers::getTitle($page))) continue; $width = $page['num_' . $parameters['popularity_type']] * 100 / $max; diff --git a/Sources/LightPortal/addons/TopPosters/TopPosters.php b/Sources/LightPortal/addons/TopPosters/TopPosters.php index 9a3f6c782..b40211730 100644 --- a/Sources/LightPortal/addons/TopPosters/TopPosters.php +++ b/Sources/LightPortal/addons/TopPosters/TopPosters.php @@ -13,7 +13,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -144,14 +144,13 @@ public static function prepareBlockFields() */ public static function getData($parameters) { - global $smcFunc, $scripturl, $modSettings, $context; + global $smcFunc, $memberContext, $scripturl; $request = $smcFunc['db_query']('', ' - SELECT mem.id_member, mem.real_name, mem.posts' . ($parameters['show_avatars'] ? ', mem.avatar, a.id_attach, a.attachment_type, a.filename' : '') . ' - FROM {db_prefix}members AS mem' . ($parameters['show_avatars'] ? ' - LEFT JOIN {db_prefix}attachments AS a ON (mem.id_member = a.id_member)' : '') . ' - WHERE mem.posts > {int:num_posts} - ORDER BY mem.posts DESC + SELECT id_member, real_name, posts + FROM {db_prefix}members + WHERE posts > {int:num_posts} + ORDER BY posts DESC LIMIT {int:num_posters}', array( 'num_posts' => 0, @@ -159,19 +158,28 @@ public static function getData($parameters) ) ); + $result = $smcFunc['db_fetch_all']($request); + + if (empty($result)) + return []; + + loadMemberData(array_column($result, 'id_member')); + $posters = []; - while ($row = $smcFunc['db_fetch_assoc']($request)) { + foreach ($result as $row) { + if (!isset($memberContext[$row['id_member']])) + loadMemberContext($row['id_member']); + $posters[] = array( 'name' => $row['real_name'], 'link' => allowedTo('profile_view') ? '' . $row['real_name'] . '' : $row['real_name'], - 'avatar' => $parameters['show_avatars'] ? ($row['avatar'] == '' ? ($row['id_attach'] > 0 ? (empty($row['attachment_type']) ? $scripturl . '?action=dlattach;attach=' . $row['id_attach'] . ';type=avatar' : $modSettings['custom_avatar_url'] . '/' . $row['filename']) : $modSettings['avatar_url'] . '/default.png') : (stristr($row['avatar'], 'http://') ? $row['avatar'] : $modSettings['avatar_url'] . '/' . $row['avatar'])) : null, + 'avatar' => $parameters['show_avatars'] ? $memberContext[$row['id_member']]['avatar']['image'] : null, 'posts' => $row['posts'] ); } $smcFunc['db_free_result']($request); - - $context++; + $smcFunc['lp_num_queries']++; return $posters; } @@ -195,7 +203,7 @@ public static function prepareContent(&$content, $type, $block_id, $cache_time, if ($type !== 'top_posters') return; - $top_posters = Helpers::getFromCache('top_posters_addon_b' . $block_id . '_u' . $user_info['id'], 'getData', __CLASS__, $cache_time, $parameters); + $top_posters = Helpers::cache('top_posters_addon_b' . $block_id . '_u' . $user_info['id'], 'getData', __CLASS__, $cache_time, $parameters); if (!empty($top_posters)) { ob_start(); @@ -209,15 +217,12 @@ public static function prepareContent(&$content, $type, $block_id, $cache_time, echo '
'; - if (!empty($poster['avatar'])) { - echo ' - ', $poster['name'], ' '; - } + if (!empty($poster['avatar'])) + echo $poster['avatar']; $width = $poster['posts'] * 100 / $max; - echo ' - ', $poster['link'], ' + echo ' ', $poster['link'], '
diff --git a/Sources/LightPortal/addons/TopTopics/TopTopics.php b/Sources/LightPortal/addons/TopTopics/TopTopics.php index 462f69d46..89d14b668 100644 --- a/Sources/LightPortal/addons/TopTopics/TopTopics.php +++ b/Sources/LightPortal/addons/TopTopics/TopTopics.php @@ -13,7 +13,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -183,7 +183,7 @@ public static function prepareContent(&$content, $type, $block_id, $cache_time, if ($type !== 'top_topics') return; - $top_topics = Helpers::getFromCache('top_topics_addon_b' . $block_id . '_u' . $user_info['id'], 'getData', __CLASS__, $cache_time, $parameters); + $top_topics = Helpers::cache('top_topics_addon_b' . $block_id . '_u' . $user_info['id'], 'getData', __CLASS__, $cache_time, $parameters); if (!empty($top_topics)) { ob_start(); diff --git a/Sources/LightPortal/addons/TopicRatingBar/TopicRatingBar.php b/Sources/LightPortal/addons/TopicRatingBar/TopicRatingBar.php index 65dd23df4..bba23fc53 100644 --- a/Sources/LightPortal/addons/TopicRatingBar/TopicRatingBar.php +++ b/Sources/LightPortal/addons/TopicRatingBar/TopicRatingBar.php @@ -11,7 +11,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -65,7 +65,7 @@ public static function frontTopicsOutput(&$topics, $row) * * @return void */ - public static function frontpageAssets() + public static function frontAssets() { global $context; diff --git a/Sources/LightPortal/addons/Translator/Translator.php b/Sources/LightPortal/addons/Translator/Translator.php index 42ecab02f..81955de9e 100644 --- a/Sources/LightPortal/addons/Translator/Translator.php +++ b/Sources/LightPortal/addons/Translator/Translator.php @@ -11,7 +11,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) diff --git a/Sources/LightPortal/addons/Trumbowyg/Trumbowyg.php b/Sources/LightPortal/addons/Trumbowyg/Trumbowyg.php index 64bd20212..6919f3f59 100644 --- a/Sources/LightPortal/addons/Trumbowyg/Trumbowyg.php +++ b/Sources/LightPortal/addons/Trumbowyg/Trumbowyg.php @@ -13,7 +13,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) diff --git a/Sources/LightPortal/addons/UserInfo/UserInfo.php b/Sources/LightPortal/addons/UserInfo/UserInfo.php index 778fc7c33..f236c8b61 100644 --- a/Sources/LightPortal/addons/UserInfo/UserInfo.php +++ b/Sources/LightPortal/addons/UserInfo/UserInfo.php @@ -3,7 +3,6 @@ namespace Bugo\LightPortal\Addons\UserInfo; use Bugo\LightPortal\Helpers; - /** * UserInfo * @@ -13,7 +12,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -70,7 +69,7 @@ public static function prepareContent(&$content, $type, $block_id, $cache_time) ob_start(); if ($context['user']['is_logged']) { - $userData = Helpers::getFromCache('user_info_addon_u' . $context['user']['id'], 'getData', __CLASS__, $cache_time); + $userData = Helpers::cache('user_info_addon_u' . $context['user']['id'], 'getData', __CLASS__, $cache_time); echo '
    @@ -78,7 +77,7 @@ public static function prepareContent(&$content, $type, $block_id, $cache_time) if (!empty($userData['avatar'])) { echo ' -
  • ', $userData['avatar']['image'], '
  • '; +
  • ', $userData['avatar']['image'], '
  • '; } $fa = false; diff --git a/Sources/LightPortal/addons/VkComments/VkComments.php b/Sources/LightPortal/addons/VkComments/VkComments.php index a93e75976..a1b6d14f2 100644 --- a/Sources/LightPortal/addons/VkComments/VkComments.php +++ b/Sources/LightPortal/addons/VkComments/VkComments.php @@ -11,7 +11,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) diff --git a/Sources/LightPortal/addons/WhosOnline/WhosOnline.php b/Sources/LightPortal/addons/WhosOnline/WhosOnline.php index 29eebf170..fc7aeb802 100644 --- a/Sources/LightPortal/addons/WhosOnline/WhosOnline.php +++ b/Sources/LightPortal/addons/WhosOnline/WhosOnline.php @@ -13,7 +13,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ if (!defined('SMF')) @@ -128,7 +128,12 @@ public static function prepareContent(&$content, $type, $block_id, $cache_time, if ($type !== 'whos_online') return; - $whos_online = Helpers::getFromCache('whos_online_addon_b' . $block_id . '_u' . $user_info['id'], 'getData', __CLASS__, $parameters['update_interval'] ?? $cache_time); + $whos_online = Helpers::cache( + 'whos_online_addon_b' . $block_id . '_u' . $user_info['id'], + 'getData', + __CLASS__, + $parameters['update_interval'] ?? $cache_time + ); if (!empty($whos_online)) { ob_start(); diff --git a/Sources/LightPortal/front/Article.php b/Sources/LightPortal/front/Article.php new file mode 100644 index 000000000..88acfda32 --- /dev/null +++ b/Sources/LightPortal/front/Article.php @@ -0,0 +1,164 @@ + + * @copyright 2019-2020 Bugo + * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later + * + * @version 1.3 + */ + +abstract class Article implements IArticle +{ + /** + * Show articles on the portal frontpage + * + * Выводим статьи на главной странице портала + * + * @return void + */ + public static function show() + { + global $modSettings, $context, $scripturl, $txt; + + isAllowedTo('light_portal_view'); + + $context['lp_need_lower_case'] = Helpers::isLowerCaseForDates(); + + switch ($modSettings['lp_frontpage_mode']) { + case 1: + return Page::show(); + + case 2: + self::prepare('topics'); + $context['sub_template'] = 'show_topics_as_articles'; + break; + + case 3: + self::prepare(); + $context['sub_template'] = 'show_pages_as_articles'; + break; + + default: + self::prepare('boards'); + $context['sub_template'] = 'show_boards_as_articles'; + } + + Subs::runAddons('frontCustomTemplate'); + + $context['lp_frontpage_layout'] = self::getNumColumns(); + $context['canonical_url'] = $scripturl; + + loadTemplate('LightPortal/ViewFrontPage'); + + $context['page_title'] = $modSettings['lp_frontpage_title'] ?: ($context['forum_name'] . ' - ' . $txt['lp_portal']); + $context['linktree'][] = array( + 'name' => $txt['lp_portal'] + ); + } + + /** + * Get the number columns for the frontpage layout + * + * Получаем количество колонок для макета главной страницы + * + * @return int + */ + public static function getNumColumns() + { + global $modSettings; + + $num_columns = 12; + + if (!empty($modSettings['lp_frontpage_layout'])) { + switch ($modSettings['lp_frontpage_layout']) { + case '1': + $num_columns /= 2; + break; + + case '2': + $num_columns /= 3; + break; + + case '3': + $num_columns /= 4; + break; + + default: + $num_columns /= 6; + } + } + + return $num_columns; + } + + /** + * Form an array of articles + * + * Формируем массив статей + * + * @param string $source (pages|topics|boards) + * @return void + */ + public static function prepare(string $source = 'pages') + { + global $modSettings, $context, $scripturl; + + switch ($source) { + case 'topics': + $class = TopicArticle::class; + break; + + case 'boards': + $class = BoardArticle::class; + break; + + default: + $class = PageArticle::class; + } + + $start = Helpers::request('start'); + $limit = $modSettings['lp_num_items_per_page'] ?? 12; + + $total_items = $class::getTotal(); + + if ($start >= $total_items) { + send_http_status(404); + $start = (floor(($total_items - 1) / $limit) + 1) * $limit - $limit; + } + + $articles = $class::getData($start, $limit); + + $articles = array_map(function ($article) use ($modSettings) { + if (!empty($article['date'])) { + $article['datetime'] = date('Y-m-d', $article['date']); + $article['date'] = Helpers::getFriendlyTime($article['date']); + } + + if (isset($article['title'])) + $article['title'] = Helpers::getTitle($article); + + if (empty($article['image']) && !empty($modSettings['lp_image_placeholder'])) + $article['image'] = $modSettings['lp_image_placeholder']; + + return $article; + }, $articles); + + $context['page_index'] = constructPageIndex($scripturl . '?action=portal', Helpers::request()->get('start'), $total_items, $limit); + $context['start'] = Helpers::request()->get('start'); + + $context['lp_frontpage_articles'] = $articles; + + Subs::runAddons('frontAssets'); + } +} \ No newline at end of file diff --git a/Sources/LightPortal/front/BoardArticle.php b/Sources/LightPortal/front/BoardArticle.php new file mode 100644 index 000000000..1d40c1faa --- /dev/null +++ b/Sources/LightPortal/front/BoardArticle.php @@ -0,0 +1,172 @@ + + * @copyright 2019-2020 Bugo + * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later + * + * @version 1.3 + */ + +if (!defined('SMF')) + die('Hacking attempt...'); + +class BoardArticle extends Article +{ + /** + * Get selected boards + * + * Получаем выбранные разделы + * + * @param int $start + * @param int $limit + * @return array + */ + public static function getData(int $start, int $limit): array + { + global $modSettings, $user_info, $smcFunc, $context, $scripturl; + + $selected_boards = !empty($modSettings['lp_frontpage_boards']) ? explode(',', $modSettings['lp_frontpage_boards']) : []; + + if (empty($selected_boards)) + return []; + + if (($boards = Helpers::cache()->get('articles_u' . $user_info['id'] . '_' . $start . '_' . $limit, LP_CACHE_TIME)) === null) { + $custom_columns = []; + $custom_tables = []; + $custom_wheres = []; + + $custom_parameters = [ + 'blank_string' => '', + 'current_member' => $user_info['id'], + 'selected_boards' => $selected_boards, + 'start' => $start, + 'limit' => $limit + ]; + + $custom_sorting = [ + 'b.id_last_msg DESC', + 'm.poster_time DESC', + 'm.poster_time', + ]; + + Subs::runAddons('frontBoards', array(&$custom_columns, &$custom_tables, &$custom_wheres, &$custom_parameters, &$custom_sorting)); + + $request = $smcFunc['db_query']('', ' + SELECT + b.id_board, b.name, b.description, b.redirect, CASE WHEN b.redirect != {string:blank_string} THEN 1 ELSE 0 END AS is_redirect, b.num_posts, + GREATEST(m.poster_time, m.modified_time) AS last_updated, m.id_msg, m.id_topic, c.name AS cat_name,' . ($user_info['is_guest'] ? ' 1 AS is_read, 0 AS new_from' : ' + (CASE WHEN COALESCE(lb.id_msg, 0) >= b.id_last_msg THEN 1 ELSE 0 END) AS is_read, COALESCE(lb.id_msg, -1) + 1 AS new_from') . (!empty($modSettings['lp_show_images_in_articles']) ? ', COALESCE(a.id_attach, 0) AS attach_id' : '') . (!empty($custom_columns) ? ', + ' . implode(', ', $custom_columns) : '') . ' + FROM {db_prefix}boards AS b + INNER JOIN {db_prefix}categories AS c ON (b.id_cat = c.id_cat) + LEFT JOIN {db_prefix}messages AS m ON (b.id_last_msg = m.id_msg)' . ($user_info['is_guest'] ? '' : ' + LEFT JOIN {db_prefix}log_boards AS lb ON (b.id_board = lb.id_board AND lb.id_member = {int:current_member})') . (!empty($modSettings['lp_show_images_in_articles']) ? ' + LEFT JOIN {db_prefix}attachments AS a ON (b.id_last_msg = a.id_msg AND a.id_thumb <> 0 AND a.width > 0 AND a.height > 0)' : '') . (!empty($custom_tables) ? ' + ' . implode("\n\t\t\t\t\t", $custom_tables) : '') . ' + WHERE b.id_board IN ({array_int:selected_boards}) + AND {query_see_board}' . (!empty($custom_wheres) ? ' + ' . implode("\n\t\t\t\t\t", $custom_wheres) : '') . ' + ORDER BY ' . (!empty($modSettings['lp_frontpage_order_by_num_replies']) ? 'b.num_posts DESC, ' : '') . $custom_sorting[$modSettings['lp_frontpage_article_sorting'] ?? 0] . ' + LIMIT {int:start}, {int:limit}', + $custom_parameters + ); + + $boards = []; + while ($row = $smcFunc['db_fetch_assoc']($request)) { + $board_name = parse_bbc($row['name'], false, '', $context['description_allowed_tags']); + $description = parse_bbc($row['description'], false, '', $context['description_allowed_tags']); + $cat_name = parse_bbc($row['cat_name'], false, '', $context['description_allowed_tags']); + + $image = null; + if (!empty($modSettings['lp_show_images_in_articles'])) { + $board_image = preg_match('/ $row['id_board'], + 'name' => $board_name, + 'teaser' => Helpers::getTeaser($description), + 'category' => $cat_name, + 'link' => $row['is_redirect'] ? $row['redirect'] : $scripturl . '?board=' . $row['id_board'] . '.0', + 'is_redirect' => $row['is_redirect'], + 'is_updated' => empty($row['is_read']), + 'num_posts' => $row['num_posts'], + 'image' => $image, + 'can_edit' => $user_info['is_admin'] || allowedTo('manage_boards') + ); + + if (!empty($row['last_updated'])) { + $boards[$row['id_board']]['last_post'] = $scripturl . '?topic=' . $row['id_topic'] . '.msg' . ($user_info['is_guest'] ? $row['id_msg'] : $row['new_from']) . (empty($row['is_read']) ? ';boardseen' : '') . '#new'; + + $boards[$row['id_board']]['date'] = $row['last_updated']; + } + + $boards[$row['id_board']]['msg_link'] = $boards[$row['id_board']]['link']; + + if (empty($boards[$row['id_board']]['is_redirect'])) + $boards[$row['id_board']]['msg_link'] = $scripturl . '?msg=' . $row['id_msg']; + + Subs::runAddons('frontBoardsOutput', array(&$boards, $row)); + } + + $smcFunc['db_free_result']($request); + $smcFunc['lp_num_queries']++; + + Helpers::cache()->put('articles_u' . $user_info['id'] . '_' . $start . '_' . $limit, $boards, LP_CACHE_TIME); + } + + return $boards; + } + + /** + * Get count of selected boards + * + * Получаем количество выбранных разделов + * + * @return int + */ + public static function getTotal(): int + { + global $modSettings, $user_info, $smcFunc; + + $selected_boards = !empty($modSettings['lp_frontpage_boards']) ? explode(',', $modSettings['lp_frontpage_boards']) : []; + + if (empty($selected_boards)) + return 0; + + if (($num_boards = Helpers::cache()->get('articles_u' . $user_info['id'] . '_total', LP_CACHE_TIME)) === null) { + $request = $smcFunc['db_query']('', ' + SELECT COUNT(b.id_board) + FROM {db_prefix}boards AS b + INNER JOIN {db_prefix}categories AS c ON (b.id_cat = c.id_cat) + WHERE b.id_board IN ({array_int:selected_boards}) + AND {query_see_board}', + array( + 'selected_boards' => $selected_boards + ) + ); + + [$num_boards] = $smcFunc['db_fetch_row']($request); + + $smcFunc['db_free_result']($request); + $smcFunc['lp_num_queries']++; + + Helpers::cache()->put('articles_u' . $user_info['id'] . '_total', (int) $num_boards, LP_CACHE_TIME); + } + + return (int) $num_boards; + } +} diff --git a/Sources/LightPortal/front/IArticle.php b/Sources/LightPortal/front/IArticle.php new file mode 100644 index 000000000..b14eda90a --- /dev/null +++ b/Sources/LightPortal/front/IArticle.php @@ -0,0 +1,23 @@ + + * @copyright 2019-2020 Bugo + * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later + * + * @version 1.3 + */ + +interface IArticle +{ + public static function show(); + public static function prepare(string $source); + public static function getData(int $start, int $limit): array; + public static function getTotal(): int; +} \ No newline at end of file diff --git a/Sources/LightPortal/front/PageArticle.php b/Sources/LightPortal/front/PageArticle.php new file mode 100644 index 000000000..1f1c094cc --- /dev/null +++ b/Sources/LightPortal/front/PageArticle.php @@ -0,0 +1,156 @@ + + * @copyright 2019-2020 Bugo + * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later + * + * @version 1.3 + */ + +if (!defined('SMF')) + die('Hacking attempt...'); + +class PageArticle extends Article +{ + /** + * Get active pages of the portal + * + * Получаем активные страницы портала + * + * @param int $start + * @param int $limit + * @return array + */ + public static function getData(int $start, int $limit): array + { + global $user_info, $smcFunc, $modSettings, $scripturl; + + //if (($pages = Helpers::cache()->get('articles_u' . $user_info['id'] . '_' . $start . '_' . $limit, LP_CACHE_TIME)) === null) { + $titles = Helpers::cache('all_titles', 'getAllTitles', '\Bugo\LightPortal\Subs', LP_CACHE_TIME, 'page'); + + $custom_columns = []; + $custom_tables = []; + $custom_wheres = []; + + $custom_parameters = [ + 'type' => 'page', + 'status' => Page::STATUS_ACTIVE, + 'current_time' => time(), + 'permissions' => Helpers::getPermissions(), + 'start' => $start, + 'limit' => $limit + ]; + + $custom_sorting = [ + 'CASE WHEN (SELECT lp_com.created_at FROM {db_prefix}lp_comments AS lp_com WHERE p.page_id = lp_com.page_id LIMIT 1) > 0 THEN 0 ELSE 1 END, comment_date DESC', + 'p.created_at DESC', + 'p.created_at', + ]; + + Subs::runAddons('frontPages', array(&$custom_columns, &$custom_tables, &$custom_wheres, &$custom_parameters, &$custom_sorting)); + + $request = $smcFunc['db_query']('', ' + SELECT + p.page_id, p.author_id, p.alias, p.content, p.description, p.type, p.status, p.num_views, p.num_comments, p.created_at, GREATEST(p.created_at, p.updated_at) AS date, + mem.real_name AS author_name, (SELECT lp_com.created_at FROM {db_prefix}lp_comments AS lp_com WHERE p.page_id = lp_com.page_id LIMIT 1) AS comment_date, (SELECT lp_com.author_id FROM {db_prefix}lp_comments AS lp_com WHERE p.page_id = lp_com.page_id LIMIT 1) AS comment_author_id, (SELECT real_name FROM {db_prefix}lp_comments AS lp_com LEFT JOIN {db_prefix}members ON (lp_com.author_id = id_member) WHERE lp_com.page_id = p.page_id LIMIT 1) AS comment_author_name' . (!empty($custom_columns) ? ', ' . implode(', ', $custom_columns) : '') . ' + FROM {db_prefix}lp_pages AS p + LEFT JOIN {db_prefix}members AS mem ON (p.author_id = mem.id_member)' . (!empty($custom_tables) ? ' + ' . implode("\n\t\t\t\t\t", $custom_tables) : '') . ' + WHERE p.status = {int:status} + AND p.created_at <= {int:current_time} + AND p.permissions IN ({array_int:permissions})' . (!empty($custom_wheres) ? ' + ' . implode("\n\t\t\t\t\t", $custom_wheres) : '') . ' + ORDER BY ' . (!empty($modSettings['lp_frontpage_order_by_num_replies']) ? 'num_comments DESC, ' : '') . $custom_sorting[$modSettings['lp_frontpage_article_sorting'] ?? 0] . ' + LIMIT {int:start}, {int:limit}', + $custom_parameters + ); + + $pages = []; + while ($row = $smcFunc['db_fetch_assoc']($request)) { + Helpers::parseContent($row['content'], $row['type']); + + $image = null; + if (!empty($modSettings['lp_show_images_in_articles'])) { + $first_post_image = preg_match('/ $row['page_id'], + 'author_id' => $author_id = empty($row['num_comments']) ? $row['author_id'] : $row['comment_author_id'], + 'author_link' => $scripturl . '?action=profile;u=' . $author_id, + 'author_name' => empty($row['num_comments']) ? $row['author_name'] : $row['comment_author_name'], + 'teaser' => Helpers::getTeaser($row['description'] ?: strip_tags($row['content'])), + 'type' => $row['type'], + 'num_views' => $row['num_views'], + 'num_comments' => $row['num_comments'], + 'date' => empty($modSettings['lp_frontpage_article_sorting']) && !empty($row['comment_date']) ? $row['comment_date'] : $row['created_at'], + 'is_new' => $user_info['last_login'] < $row['date'] && $row['author_id'] != $user_info['id'], + 'link' => $scripturl . '?page=' . $row['alias'], + 'image' => $image, + 'can_edit' => $user_info['is_admin'] || (allowedTo('light_portal_manage_own_pages') && $row['author_id'] == $user_info['id']) + ); + } + + $pages[$row['page_id']]['title'] = $titles[$row['page_id']]; + + Subs::runAddons('frontPagesOutput', array(&$pages, $row)); + } + + $smcFunc['db_free_result']($request); + $smcFunc['lp_num_queries']++; + + //Helpers::cache()->put('articles_u' . $user_info['id'] . '_' . $start . '_' . $limit, $pages, LP_CACHE_TIME); + //} + + return $pages; + } + + /** + * Get count of active pages + * + * Получаем количество активных страниц + * + * @return int + */ + public static function getTotal(): int + { + global $user_info, $smcFunc; + + if (($num_pages = Helpers::cache()->get('articles_u' . $user_info['id'] . '_total', LP_CACHE_TIME)) === null) { + $request = $smcFunc['db_query']('', ' + SELECT COUNT(page_id) + FROM {db_prefix}lp_pages + WHERE status = {int:status} + AND created_at <= {int:current_time} + AND permissions IN ({array_int:permissions})', + array( + 'status' => Page::STATUS_ACTIVE, + 'current_time' => time(), + 'permissions' => Helpers::getPermissions() + ) + ); + + [$num_pages] = $smcFunc['db_fetch_row']($request); + + $smcFunc['db_free_result']($request); + $smcFunc['lp_num_queries']++; + + Helpers::cache()->put('articles_u' . $user_info['id'] . '_total', (int) $num_pages, LP_CACHE_TIME); + } + + return (int) $num_pages; + } +} diff --git a/Sources/LightPortal/front/TopicArticle.php b/Sources/LightPortal/front/TopicArticle.php new file mode 100644 index 000000000..8b936812c --- /dev/null +++ b/Sources/LightPortal/front/TopicArticle.php @@ -0,0 +1,209 @@ + + * @copyright 2019-2020 Bugo + * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later + * + * @version 1.3 + */ + +if (!defined('SMF')) + die('Hacking attempt...'); + +class TopicArticle extends Article +{ + /** + * Get topics from selected boards + * + * Получаем темы из выбранных разделов + * + * @param int $start + * @param int $limit + * @return array + */ + public static function getData(int $start, int $limit): array + { + global $modSettings, $user_info, $smcFunc, $scripturl, $txt; + + $selected_boards = !empty($modSettings['lp_frontpage_boards']) ? explode(',', $modSettings['lp_frontpage_boards']) : []; + + if (empty($selected_boards)) + return []; + + if (($topics = Helpers::cache()->get('articles_u' . $user_info['id'] . '_' . $start . '_' . $limit, LP_CACHE_TIME)) === null) { + $custom_columns = []; + $custom_tables = []; + $custom_wheres = []; + + $custom_parameters = [ + 'current_member' => $user_info['id'], + 'is_approved' => 1, + 'id_poll' => 0, + 'id_redirect_topic' => 0, + 'attachment_type' => 0, + 'selected_boards' => $selected_boards, + 'start' => $start, + 'limit' => $limit + ]; + + $custom_sorting = [ + 't.id_last_msg DESC', + 'mf.poster_time DESC', + 'mf.poster_time', + ]; + + Subs::runAddons('frontTopics', array(&$custom_columns, &$custom_tables, &$custom_wheres, &$custom_parameters, &$custom_sorting)); + + $request = $smcFunc['db_query']('', ' + SELECT + t.id_topic, t.id_board, t.num_views, t.num_replies, t.is_sticky, t.id_first_msg, t.id_member_started, mf.subject, mf.body, mf.smileys_enabled, COALESCE(mem.real_name, mf.poster_name) AS poster_name, mf.poster_time, mf.id_member, ml.id_msg, ml.id_member AS last_poster_id, ml.poster_name AS last_poster_name, ml.body AS last_body, ml.poster_time AS last_msg_time, b.name, ' . (!empty($modSettings['lp_show_images_in_articles']) ? '( + SELECT id_attach + FROM {db_prefix}attachments + WHERE id_msg = t.id_first_msg + AND width <> 0 + AND height <> 0 + AND approved = {int:is_approved} + AND attachment_type = {int:attachment_type} + ORDER BY id_attach + LIMIT 1 + ) AS id_attach, ' : '') . ($user_info['is_guest'] ? '0' : 'COALESCE(lt.id_msg, lmr.id_msg, -1) + 1') . ' AS new_from, ml.id_msg_modified' . (!empty($custom_columns) ? ', + ' . implode(', ', $custom_columns) : '') . ' + FROM {db_prefix}topics AS t + INNER JOIN {db_prefix}messages AS ml ON (t.id_last_msg = ml.id_msg) + INNER JOIN {db_prefix}messages AS mf ON (t.id_first_msg = mf.id_msg) + INNER JOIN {db_prefix}boards AS b ON (t.id_board = b.id_board) + LEFT JOIN {db_prefix}members AS mem ON (mf.id_member = mem.id_member)' . ($user_info['is_guest'] ? '' : ' + LEFT JOIN {db_prefix}log_topics AS lt ON (t.id_topic = lt.id_topic AND lt.id_member = {int:current_member}) + LEFT JOIN {db_prefix}log_mark_read AS lmr ON (t.id_board = lmr.id_board AND lmr.id_member = {int:current_member})') . (!empty($custom_tables) ? ' + ' . implode("\n\t\t\t\t\t", $custom_tables) : '') . ' + WHERE t.approved = {int:is_approved} + AND t.id_poll = {int:id_poll} + AND t.id_redirect_topic = {int:id_redirect_topic} + AND t.id_board IN ({array_int:selected_boards}) + AND {query_wanna_see_board}' . (!empty($custom_wheres) ? ' + ' . implode("\n\t\t\t\t\t", $custom_wheres) : '') . ' + ORDER BY ' . (!empty($modSettings['lp_frontpage_order_by_num_replies']) ? 't.num_replies DESC, ' : '') . $custom_sorting[$modSettings['lp_frontpage_article_sorting'] ?? 0] . ' + LIMIT {int:start}, {int:limit}', + $custom_parameters + ); + + $topics = []; + while ($row = $smcFunc['db_fetch_assoc']($request)) { + if (!isset($topics[$row['id_topic']])) { + Helpers::cleanBbcode($row['subject']); + censorText($row['subject']); + censorText($row['body']); + censorText($row['last_body']); + + $image = null; + if (!empty($row['id_attach'])) + $image = $scripturl . '?action=dlattach;topic=' . $row['id_topic'] . '.0;attach=' . $row['id_attach'] . ';image'; + + if (!empty($modSettings['lp_show_images_in_articles']) && empty($image)) { + $body = parse_bbc($row['body'], false); + $first_post_image = preg_match('/' => ' ')), '
    '); + + $row['last_body'] = preg_replace('~\[spoiler.*].*?\[\/spoiler]~Usi', $txt['spoiler'] ?? '', $row['last_body']); + $row['last_body'] = preg_replace('~\[code.*].*?\[\/code]~Usi', $txt['code'], $row['last_body']); + $row['last_body'] = strip_tags(strtr(parse_bbc($row['last_body'], $row['smileys_enabled'], $row['id_msg']), array('
    ' => ' ')), '
    '); + + $topics[$row['id_topic']] = array( + 'id' => $row['id_topic'], + 'id_msg' => $row['id_first_msg'], + 'author_id' => $author_id = empty($row['num_replies']) ? $row['id_member'] : $row['last_poster_id'], + 'author_link' => $scripturl . '?action=profile;u=' . $author_id, + 'author_name' => empty($row['num_replies']) ? $row['poster_name'] : $row['last_poster_name'], + 'date' => empty($modSettings['lp_frontpage_article_sorting']) && !empty($row['last_msg_time']) ? $row['last_msg_time'] : $row['poster_time'], + 'subject' => $row['subject'], + 'teaser' => Helpers::getTeaser(empty($row['num_replies']) ? $row['body'] : $row['last_body']), + 'link' => $scripturl . '?topic=' . $row['id_topic'] . ($row['new_from'] > $row['id_msg_modified'] ? '.0' : '.new;topicseen#new'), + 'board_link' => $scripturl . '?board=' . $row['id_board'] . '.0', + 'board_name' => $row['name'], + 'is_sticky' => !empty($row['is_sticky']), + 'is_new' => $row['new_from'] <= $row['id_msg_modified'] && $row['last_poster_id'] != $user_info['id'], + 'num_views' => $row['num_views'], + 'num_replies' => $row['num_replies'], + 'css_class' => $row['is_sticky'] ? ' sticky' : '', + 'image' => $image, + 'can_edit' => $user_info['is_admin'] || ($row['id_member'] == $user_info['id'] && !empty($user_info['id'])) + ); + + $topics[$row['id_topic']]['msg_link'] = $topics[$row['id_topic']]['link']; + + if (!empty($topics[$row['id_topic']]['num_replies'])) + $topics[$row['id_topic']]['msg_link'] = $scripturl . '?msg=' . $row['id_msg']; + } + + Subs::runAddons('frontTopicsOutput', array(&$topics, $row)); + } + + $smcFunc['db_free_result']($request); + $smcFunc['lp_num_queries']++; + + Helpers::cache()->put('articles_u' . $user_info['id'] . '_' . $start . '_' . $limit, $topics, LP_CACHE_TIME); + } + + return $topics; + } + + /** + * Get count of active topics from selected boards + * + * Получаем количество активных тем из выбранных разделов + * + * @return int + */ + public static function getTotal(): int + { + global $modSettings, $user_info, $smcFunc; + + $selected_boards = !empty($modSettings['lp_frontpage_boards']) ? explode(',', $modSettings['lp_frontpage_boards']) : []; + + if (empty($selected_boards)) + return 0; + + if (($num_topics = Helpers::cache()->get('articles_u' . $user_info['id'] . '_total', LP_CACHE_TIME)) === null) { + $request = $smcFunc['db_query']('', ' + SELECT COUNT(t.id_topic) + FROM {db_prefix}topics AS t + INNER JOIN {db_prefix}boards AS b ON (t.id_board = b.id_board) + WHERE t.approved = {int:is_approved} + AND t.id_poll = {int:id_poll} + AND t.id_redirect_topic = {int:id_redirect_topic} + AND t.id_board IN ({array_int:selected_boards}) + AND {query_wanna_see_board}', + array( + 'is_approved' => 1, + 'id_poll' => 0, + 'id_redirect_topic' => 0, + 'selected_boards' => $selected_boards + ) + ); + + [$num_topics] = $smcFunc['db_fetch_row']($request); + + $smcFunc['db_free_result']($request); + $smcFunc['lp_num_queries']++; + + Helpers::cache()->put('articles_u' . $user_info['id'] . '_total', (int) $num_topics, LP_CACHE_TIME); + } + + return (int) $num_topics; + } +} diff --git a/Sources/LightPortal/front/index.php b/Sources/LightPortal/front/index.php new file mode 100644 index 000000000..69278ce68 --- /dev/null +++ b/Sources/LightPortal/front/index.php @@ -0,0 +1,9 @@ + \ No newline at end of file diff --git a/Sources/LightPortal/impex/BlockExport.php b/Sources/LightPortal/impex/BlockExport.php new file mode 100644 index 000000000..b8de2554a --- /dev/null +++ b/Sources/LightPortal/impex/BlockExport.php @@ -0,0 +1,156 @@ + + * @copyright 2019-2020 Bugo + * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later + * + * @version 1.3 + */ + +if (!defined('SMF')) + die('Hacking attempt...'); + +class BlockExport extends Export +{ + /** + * The page of export blocks + * + * Страница экспорта блоков + * + * @return void + */ + public static function main() + { + global $context, $txt, $scripturl; + + loadTemplate('LightPortal/ManageExport'); + + $context['page_title'] = $txt['lp_portal'] . ' - ' . $txt['lp_blocks_export']; + $context['page_area_title'] = $txt['lp_blocks_export']; + $context['canonical_url'] = $scripturl . '?action=admin;area=lp_blocks;sa=export'; + + $context[$context['admin_menu_name']]['tab_data'] = array( + 'title' => LP_NAME, + 'description' => $txt['lp_blocks_export_tab_description'] + ); + + self::run(); + + $context['lp_current_blocks'] = \Bugo\LightPortal\ManageBlocks::getAll(); + $context['lp_current_blocks'] = array_merge(array_flip(array_keys($txt['lp_block_placement_set'])), $context['lp_current_blocks']); + + $context['sub_template'] = 'manage_export_blocks'; + } + + /** + * Creating data in XML format + * + * Формируем данные в XML-формате + * + * @return array + */ + protected static function getData() + { + global $smcFunc; + + if (Helpers::post()->isEmpty('items')) + return []; + + $request = $smcFunc['db_query']('', ' + SELECT + b.block_id, b.icon, b.icon_type, b.type, b.content, b.placement, b.priority, b.permissions, b.status, b.areas, b.title_class, b.title_style, b.content_class, b.content_style, + pt.lang, pt.title, pp.name, pp.value + FROM {db_prefix}lp_blocks AS b + LEFT JOIN {db_prefix}lp_titles AS pt ON (b.block_id = pt.item_id AND pt.type = {string:type}) + LEFT JOIN {db_prefix}lp_params AS pp ON (b.block_id = pp.item_id AND pp.type = {string:type}) + WHERE b.block_id IN ({array_int:blocks})', + array( + 'type' => 'block', + 'blocks' => Helpers::post('items') + ) + ); + + $items = []; + while ($row = $smcFunc['db_fetch_assoc']($request)) { + if (!isset($items[$row['block_id']])) + $items[$row['block_id']] = array( + 'block_id' => $row['block_id'], + 'icon' => $row['icon'], + 'icon_type' => $row['icon_type'], + 'type' => $row['type'], + 'content' => $row['content'], + 'placement' => $row['placement'], + 'priority' => $row['priority'], + 'permissions' => $row['permissions'], + 'status' => $row['status'], + 'areas' => $row['areas'], + 'title_class' => $row['title_class'], + 'title_style' => $row['title_style'], + 'content_class' => $row['content_class'], + 'content_style' => $row['content_style'] + ); + + if (!empty($row['lang'])) + $items[$row['block_id']]['titles'][$row['lang']] = $row['title']; + + if (!empty($row['name'])) + $items[$row['block_id']]['params'][$row['name']] = $row['value']; + } + + $smcFunc['db_free_result']($request); + $smcFunc['lp_num_queries']++; + + return $items; + } + + /** + * Get filename with XML data + * + * Получаем имя файла с XML-данными + * + * @return string + */ + protected static function getXmlFile() + { + if (empty($items = self::getData())) + return ''; + + $xml = new \DomDocument('1.0', 'utf-8'); + $root = $xml->appendChild($xml->createElement('light_portal')); + + $xml->formatOutput = true; + + $xmlElements = $root->appendChild($xml->createElement('blocks')); + foreach ($items as $item) { + $xmlElement = $xmlElements->appendChild($xml->createElement('item')); + foreach ($item as $key => $val) { + $xmlName = $xmlElement->appendChild(in_array($key, ['block_id', 'priority', 'permissions', 'status']) ? $xml->createAttribute($key) : $xml->createElement($key)); + + if (in_array($key, ['titles', 'params'])) { + foreach ($item[$key] as $k => $v) { + $xmlTitle = $xmlName->appendChild($xml->createElement($k)); + $xmlTitle->appendChild($xml->createTextNode($v)); + } + } elseif ($key == 'content') { + $xmlName->appendChild($xml->createCDATASection($val)); + } else { + $xmlName->appendChild($xml->createTextNode($val)); + } + } + } + + $file = sys_get_temp_dir() . '/lp_blocks_backup.xml'; + $xml->save($file); + + return $file; + } +} diff --git a/Sources/LightPortal/impex/BlockImport.php b/Sources/LightPortal/impex/BlockImport.php new file mode 100644 index 000000000..9b5e5519a --- /dev/null +++ b/Sources/LightPortal/impex/BlockImport.php @@ -0,0 +1,193 @@ + + * @copyright 2019-2020 Bugo + * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later + * + * @version 1.3 + */ + +if (!defined('SMF')) + die('Hacking attempt...'); + +class BlockImport extends Import +{ + /** + * The page of import blocks + * + * Страница импорта блоков + * + * @return void + */ + public static function main() + { + global $context, $txt, $scripturl; + + loadTemplate('LightPortal/ManageImport'); + + $context['page_title'] = $txt['lp_portal'] . ' - ' . $txt['lp_blocks_import']; + $context['page_area_title'] = $txt['lp_blocks_import']; + $context['canonical_url'] = $scripturl . '?action=admin;area=lp_blocks;sa=import'; + + $context[$context['admin_menu_name']]['tab_data'] = array( + 'title' => LP_NAME, + 'description' => $txt['lp_blocks_import_tab_description'] + ); + + $context['sub_template'] = 'manage_import'; + + self::run(); + } + + /** + * Import from an XML file + * + * Импорт из XML-файла + * + * @return void + */ + protected static function run() + { + global $smcFunc; + + if (empty($_FILES['import_file'])) + return; + + $file = $_FILES['import_file']; + + if ($file['type'] !== 'text/xml') + return; + + $xml = simplexml_load_file($file['tmp_name']); + + if ($xml === false) + return; + + if (!isset($xml->blocks->item[0]['block_id'])) + fatal_lang_error('lp_wrong_import_file', false); + + $items = $titles = $params = []; + + foreach ($xml as $element) { + foreach ($element->item as $item) { + $items[] = [ + 'block_id' => $block_id = intval($item['block_id']), + 'icon' => $item->icon, + 'icon_type' => $item->icon_type, + 'type' => $item->type, + 'content' => $item->content, + 'placement' => $item->placement, + 'priority' => intval($item['priority']), + 'permissions' => intval($item['permissions']), + 'status' => intval($item['status']), + 'areas' => $item->areas, + 'title_class' => $item->title_class, + 'title_style' => $item->title_style, + 'content_class' => $item->content_class, + 'content_style' => $item->content_style + ]; + + if (!empty($item->titles)) { + foreach ($item->titles as $title) { + foreach ($title as $k => $v) { + $titles[] = [ + 'item_id' => $block_id, + 'type' => 'block', + 'lang' => $k, + 'title' => $v + ]; + } + } + } + + if (!empty($item->params)) { + foreach ($item->params as $param) { + foreach ($param as $k => $v) { + $params[] = [ + 'item_id' => $block_id, + 'type' => 'block', + 'name' => $k, + 'value' => $v + ]; + } + } + } + } + } + + if (!empty($items)) { + $result = $smcFunc['db_insert']('replace', + '{db_prefix}lp_blocks', + array( + 'block_id' => 'int', + 'icon' => 'string-60', + 'icon_type' => 'string-10', + 'type' => 'string', + 'content' => 'string-' . MAX_MSG_LENGTH, + 'placement' => 'string-10', + 'priority' => 'int', + 'permissions' => 'int', + 'status' => 'int', + 'areas' => 'string', + 'title_class' => 'string', + 'title_style' => 'string', + 'content_class' => 'string', + 'content_style' => 'string' + ), + $items, + array('block_id'), + 2 + ); + + $smcFunc['lp_num_queries']++; + } + + if (!empty($titles) && !empty($result)) { + $result = $smcFunc['db_insert']('replace', + '{db_prefix}lp_titles', + array( + 'item_id' => 'int', + 'type' => 'string', + 'lang' => 'string', + 'title' => 'string' + ), + $titles, + array('item_id', 'type', 'lang'), + 2 + ); + + $smcFunc['lp_num_queries']++; + } + + if (!empty($params) && !empty($result)) { + $result = $smcFunc['db_insert']('replace', + '{db_prefix}lp_params', + array( + 'item_id' => 'int', + 'type' => 'string', + 'name' => 'string', + 'value' => 'string' + ), + $params, + array('item_id', 'type', 'name'), + 2 + ); + + $smcFunc['lp_num_queries']++; + } + + if (empty($result)) + fatal_lang_error('lp_import_failed', false); + + Helpers::cache()->flush(); + } +} diff --git a/Sources/LightPortal/ShareTools.php b/Sources/LightPortal/impex/Export.php similarity index 61% rename from Sources/LightPortal/ShareTools.php rename to Sources/LightPortal/impex/Export.php index d3b8b2840..768265ba6 100644 --- a/Sources/LightPortal/ShareTools.php +++ b/Sources/LightPortal/impex/Export.php @@ -1,9 +1,9 @@ 0) - $result .= ', '; - - $result .= "('" . implode("', '", $items[$i]) . "')"; - } - - return $result; - } -} +} \ No newline at end of file diff --git a/Sources/LightPortal/impex/IExport.php b/Sources/LightPortal/impex/IExport.php new file mode 100644 index 000000000..55633c20b --- /dev/null +++ b/Sources/LightPortal/impex/IExport.php @@ -0,0 +1,20 @@ + + * @copyright 2019-2020 Bugo + * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later + * + * @version 1.3 + */ + +interface IExport +{ + public static function main(); +} \ No newline at end of file diff --git a/Sources/LightPortal/impex/IImport.php b/Sources/LightPortal/impex/IImport.php new file mode 100644 index 000000000..aa6d147a1 --- /dev/null +++ b/Sources/LightPortal/impex/IImport.php @@ -0,0 +1,20 @@ + + * @copyright 2019-2020 Bugo + * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later + * + * @version 1.3 + */ + +interface IImport +{ + public static function main(); +} \ No newline at end of file diff --git a/Sources/LightPortal/impex/Import.php b/Sources/LightPortal/impex/Import.php new file mode 100644 index 000000000..839356f1f --- /dev/null +++ b/Sources/LightPortal/impex/Import.php @@ -0,0 +1,20 @@ + + * @copyright 2019-2020 Bugo + * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later + * + * @version 1.3 + */ + +abstract class Import implements IImport +{ + abstract protected static function run(); +} \ No newline at end of file diff --git a/Sources/LightPortal/impex/PageExport.php b/Sources/LightPortal/impex/PageExport.php new file mode 100644 index 000000000..7cff2af80 --- /dev/null +++ b/Sources/LightPortal/impex/PageExport.php @@ -0,0 +1,274 @@ + + * @copyright 2019-2020 Bugo + * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later + * + * @version 1.3 + */ + +if (!defined('SMF')) + die('Hacking attempt...'); + +class PageExport extends Export +{ + /** + * Prepare to export + * + * Экспорт страниц + * + * @return void + */ + public static function main() + { + global $context, $txt, $scripturl, $sourcedir; + + $context['page_title'] = $txt['lp_portal'] . ' - ' . $txt['lp_pages_export']; + $context['page_area_title'] = $txt['lp_pages_export']; + $context['canonical_url'] = $scripturl . '?action=admin;area=lp_pages;sa=export'; + + $context[$context['admin_menu_name']]['tab_data'] = array( + 'title' => LP_NAME, + 'description' => $txt['lp_pages_export_tab_description'] + ); + + self::run(); + + $listOptions = array( + 'id' => 'pages', + 'items_per_page' => \Bugo\LightPortal\ManagePages::$num_pages, + 'title' => $txt['lp_pages_export'], + 'no_items_label' => $txt['lp_no_items'], + 'base_href' => $scripturl . '?action=admin;area=lp_pages;sa=export', + 'default_sort_col' => 'id', + 'get_items' => array( + 'function' => '\Bugo\LightPortal\ManagePages::getAll' + ), + 'get_count' => array( + 'function' => '\Bugo\LightPortal\ManagePages::getTotalQuantity' + ), + 'columns' => array( + 'id' => array( + 'header' => array( + 'value' => '#', + 'style' => 'width: 5%' + ), + 'data' => array( + 'db' => 'id', + 'class' => 'centertext' + ), + 'sort' => array( + 'default' => 'p.page_id', + 'reverse' => 'p.page_id DESC' + ) + ), + 'alias' => array( + 'header' => array( + 'value' => $txt['lp_page_alias'] + ), + 'data' => array( + 'db' => 'alias', + 'class' => 'centertext word_break' + ), + 'sort' => array( + 'default' => 'p.alias DESC', + 'reverse' => 'p.alias' + ) + ), + 'title' => array( + 'header' => array( + 'value' => $txt['lp_title'] + ), + 'data' => array( + 'function' => function ($entry) use ($scripturl) + { + $title = Helpers::getTitle($entry); + + return '' . $title . ''; + }, + 'class' => 'word_break' + ), + 'sort' => array( + 'default' => 't.title DESC', + 'reverse' => 't.title' + ) + ), + 'actions' => array( + 'header' => array( + 'value' => '' + ), + 'data' => array( + 'function' => function ($entry) + { + return ''; + }, + 'class' => 'centertext' + ) + ) + ), + 'form' => array( + 'href' => $scripturl . '?action=admin;area=lp_pages;sa=export' + ), + 'additional_rows' => array( + array( + 'position' => 'below_table_data', + 'value' => ' + + ', + 'class' => 'floatright' + ) + ) + ); + + require_once($sourcedir . '/Subs-List.php'); + createList($listOptions); + + $context['sub_template'] = 'show_list'; + $context['default_list'] = 'pages'; + } + + /** + * Creating data in XML format + * + * Формируем данные в XML-формате + * + * @return mixed + */ + protected static function getData() + { + global $smcFunc; + + if (Helpers::post()->isEmpty('pages') && Helpers::post()->has('export_all') === false) + return false; + + $pages = !empty(Helpers::post('pages')) && Helpers::post()->has('export_all') === false ? Helpers::post('pages') : null; + + $request = $smcFunc['db_query']('', ' + SELECT + p.page_id, p.author_id, p.alias, p.description, p.content, p.type, p.permissions, p.status, p.num_views, p.num_comments, p.created_at, p.updated_at, + pt.lang, pt.title, pp.name, pp.value, t.value AS keyword, com.id, com.parent_id, com.author_id AS com_author_id, com.message, com.created_at AS com_created_at + FROM {db_prefix}lp_pages AS p + LEFT JOIN {db_prefix}lp_titles AS pt ON (p.page_id = pt.item_id AND pt.type = {string:type}) + LEFT JOIN {db_prefix}lp_params AS pp ON (p.page_id = pp.item_id AND pp.type = {string:type}) + LEFT JOIN {db_prefix}lp_tags AS t ON (p.page_id = t.page_id) + LEFT JOIN {db_prefix}lp_comments AS com ON (p.page_id = com.page_id)' . (!empty($pages) ? ' + WHERE p.page_id IN ({array_int:pages})' : ''), + array( + 'type' => 'page', + 'pages' => $pages + ) + ); + + $items = []; + while ($row = $smcFunc['db_fetch_assoc']($request)) { + if (!isset($items[$row['page_id']])) + $items[$row['page_id']] = array( + 'page_id' => $row['page_id'], + 'author_id' => $row['author_id'], + 'alias' => $row['alias'], + 'description' => trim($row['description']), + 'content' => $row['content'], + 'type' => $row['type'], + 'permissions' => $row['permissions'], + 'status' => $row['status'], + 'num_views' => $row['num_views'], + 'num_comments' => $row['num_comments'], + 'created_at' => $row['created_at'], + 'updated_at' => $row['updated_at'] + ); + + if (!empty($row['lang'])) + $items[$row['page_id']]['titles'][$row['lang']] = $row['title']; + + if (!empty($row['name'])) + $items[$row['page_id']]['params'][$row['name']] = $row['value']; + + if (!empty($row['keyword'])) + $items[$row['page_id']]['keywords'][] = $row['keyword']; + + if (!empty($row['message'])) { + $items[$row['page_id']]['comments'][$row['id']] = array( + 'id' => $row['id'], + 'parent_id' => $row['parent_id'], + 'author_id' => $row['com_author_id'], + 'message' => trim($row['message']), + 'created_at' => $row['com_created_at'] + ); + } + } + + $smcFunc['db_free_result']($request); + $smcFunc['lp_num_queries']++; + + return $items; + } + + /** + * Get filename with XML data + * + * Получаем имя файла с XML-данными + * + * @return string + */ + protected static function getXmlFile() + { + if (empty($items = self::getData())) + return ''; + + $xml = new \DomDocument('1.0', 'utf-8'); + $root = $xml->appendChild($xml->createElement('light_portal')); + + $xml->formatOutput = true; + + $xmlElements = $root->appendChild($xml->createElement('pages')); + foreach ($items as $item) { + $xmlElement = $xmlElements->appendChild($xml->createElement('item')); + foreach ($item as $key => $val) { + $xmlName = $xmlElement->appendChild( + in_array($key, ['page_id', 'author_id', 'permissions', 'status', 'num_views', 'num_comments', 'created_at', 'updated_at']) + ? $xml->createAttribute($key) + : $xml->createElement($key) + ); + + if (in_array($key, ['titles', 'params'])) { + foreach ($item[$key] as $k => $v) { + $xmlTitle = $xmlName->appendChild($xml->createElement($k)); + $xmlTitle->appendChild($xml->createTextNode($v)); + } + } elseif (in_array($key, ['description', 'content'])) { + $xmlName->appendChild($xml->createCDATASection($val)); + } elseif ($key == 'keywords' && !empty($val)) { + $xmlName->appendChild($xml->createTextNode(implode(', ', array_unique($val)))); + } elseif ($key == 'comments') { + foreach ($item[$key] as $k => $comment) { + $xmlComment = $xmlName->appendChild($xml->createElement('comment')); + foreach ($comment as $label => $text) { + $xmlCommentElem = $xmlComment->appendChild($label == 'message' ? $xml->createElement($label) : $xml->createAttribute($label)); + $xmlCommentElem->appendChild($label == 'message' ? $xml->createCDATASection($text) : $xml->createTextNode($text)); + } + } + } else { + $xmlName->appendChild($xml->createTextNode($val)); + } + } + } + + $file = sys_get_temp_dir() . '/lp_pages_backup.xml'; + $xml->save($file); + + return $file; + } +} diff --git a/Sources/LightPortal/impex/PageImport.php b/Sources/LightPortal/impex/PageImport.php new file mode 100644 index 000000000..413da8076 --- /dev/null +++ b/Sources/LightPortal/impex/PageImport.php @@ -0,0 +1,280 @@ + + * @copyright 2019-2020 Bugo + * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later + * + * @version 1.3 + */ + +if (!defined('SMF')) + die('Hacking attempt...'); + +class PageImport extends Import +{ + /** + * Page import + * + * Импорт страниц + * + * @return void + */ + public static function main() + { + global $context, $txt, $scripturl; + + loadTemplate('LightPortal/ManageImport'); + + $context['page_title'] = $txt['lp_portal'] . ' - ' . $txt['lp_pages_import']; + $context['page_area_title'] = $txt['lp_pages_import']; + $context['canonical_url'] = $scripturl . '?action=admin;area=lp_pages;sa=import'; + + $context[$context['admin_menu_name']]['tab_data'] = array( + 'title' => LP_NAME, + 'description' => $txt['lp_pages_import_tab_description'] + ); + + $context['sub_template'] = 'manage_import'; + + self::run(); + } + + /** + * Import from an XML file + * + * Импорт из XML-файла + * + * @return void + */ + protected static function run() + { + global $db_temp_cache, $db_cache, $smcFunc; + + if (empty($_FILES['import_file'])) + return; + + // Might take some time. + @set_time_limit(600); + + // Don't allow the cache to get too full + $db_temp_cache = $db_cache; + $db_cache = []; + + $file = $_FILES['import_file']; + + if ($file['type'] !== 'text/xml') + return; + + $xml = simplexml_load_file($file['tmp_name']); + + if ($xml === false) + return; + + if (!isset($xml->pages->item[0]['page_id'])) + fatal_lang_error('lp_wrong_import_file', false); + + $items = $titles = $params = $tags = $comments = []; + + foreach ($xml as $element) { + foreach ($element->item as $item) { + $items[] = [ + 'page_id' => $page_id = intval($item['page_id']), + 'author_id' => intval($item['author_id']), + 'alias' => (string) $item->alias, + 'description' => $item->description, + 'content' => $item->content, + 'type' => (string) $item->type, + 'permissions' => intval($item['permissions']), + 'status' => intval($item['status']), + 'num_views' => intval($item['num_views']), + 'num_comments' => intval($item['num_comments']), + 'created_at' => intval($item['created_at']), + 'updated_at' => intval($item['updated_at']) + ]; + + if (!empty($item->titles)) { + foreach ($item->titles as $title) { + foreach ($title as $k => $v) { + $titles[] = [ + 'item_id' => $page_id, + 'type' => 'page', + 'lang' => $k, + 'title' => $v + ]; + } + } + } + + if (!empty($item->comments)) { + foreach ($item->comments as $comment) { + foreach ($comment as $k => $v) { + $comments[] = [ + 'id' => intval($v['id']), + 'parent_id' => intval($v['parent_id']), + 'page_id' => intval($page_id), + 'author_id' => intval($v['author_id']), + 'message' => $v->message, + 'created_at' => intval($v['created_at']) + ]; + } + } + } + + if (!empty($item->params)) { + foreach ($item->params as $param) { + foreach ($param as $k => $v) { + $params[] = [ + 'item_id' => $page_id, + 'type' => 'page', + 'name' => $k, + 'value' => intval($v) + ]; + } + } + } + + if (!empty($item->keywords)) { + foreach (explode(', ', $item->keywords) as $value) { + $tags[] = [ + 'page_id' => $page_id, + 'value' => $value + ]; + } + } + } + } + + if (!empty($items)) { + $items = array_chunk($items, 100); + $count = sizeof($items); + + for ($i = 0; $i < $count; $i++) { + $result = $smcFunc['db_insert']('replace', + '{db_prefix}lp_pages', + array( + 'page_id' => 'int', + 'author_id' => 'int', + 'alias' => 'string-255', + 'description' => 'string-255', + 'content' => 'string-' . MAX_MSG_LENGTH, + 'type' => 'string-4', + 'permissions' => 'int', + 'status' => 'int', + 'num_views' => 'int', + 'num_comments' => 'int', + 'created_at' => 'int', + 'updated_at' => 'int' + ), + $items[$i], + array('page_id'), + 2 + ); + } + } + + if (!empty($titles) && !empty($result)) { + $titles = array_chunk($titles, 100); + $count = sizeof($titles); + + for ($i = 0; $i < $count; $i++) { + $result = $smcFunc['db_insert']('replace', + '{db_prefix}lp_titles', + array( + 'item_id' => 'int', + 'type' => 'string', + 'lang' => 'string', + 'title' => 'string' + ), + $titles[$i], + array('item_id', 'type', 'lang'), + 2 + ); + + $smcFunc['lp_num_queries']++; + } + } + + if (!empty($comments) && !empty($result)) { + $comments = array_chunk($comments, 100); + $count = sizeof($comments); + + for ($i = 0; $i < $count; $i++) { + $result = $smcFunc['db_insert']('replace', + '{db_prefix}lp_comments', + array( + 'id' => 'int', + 'parent_id' => 'int', + 'page_id' => 'int', + 'author_id' => 'int', + 'message' => 'string-' . MAX_MSG_LENGTH, + 'created_at' => 'int' + ), + $comments[$i], + array('id', 'page_id'), + 2 + ); + + $smcFunc['lp_num_queries']++; + } + } + + if (!empty($params) && !empty($result)) { + $params = array_chunk($params, 100); + $count = sizeof($params); + + for ($i = 0; $i < $count; $i++) { + $result = $smcFunc['db_insert']('replace', + '{db_prefix}lp_params', + array( + 'item_id' => 'int', + 'type' => 'string', + 'name' => 'string', + 'value' => 'string' + ), + $params[$i], + array('item_id', 'type', 'name'), + 2 + ); + + $smcFunc['lp_num_queries']++; + } + } + + if (!empty($tags) && !empty($result)) { + $tags = array_chunk($tags, 100); + $count = sizeof($tags); + + for ($i = 0; $i < $count; $i++) { + $result = $smcFunc['db_insert']('replace', + '{db_prefix}lp_tags', + array( + 'page_id' => 'int', + 'value' => 'string' + ), + $tags[$i], + array('page_id', 'value'), + 2 + ); + + $smcFunc['lp_num_queries']++; + } + } + + if (empty($result)) + fatal_lang_error('lp_import_failed', false); + + // Restore the cache + $db_cache = $db_temp_cache; + + Helpers::cache()->flush(); + } +} diff --git a/Sources/LightPortal/impex/index.php b/Sources/LightPortal/impex/index.php new file mode 100644 index 000000000..69278ce68 --- /dev/null +++ b/Sources/LightPortal/impex/index.php @@ -0,0 +1,9 @@ + \ No newline at end of file diff --git a/Sources/LightPortal/utils/Arr.php b/Sources/LightPortal/utils/Arr.php index f2922abd2..b45e0e4f3 100644 --- a/Sources/LightPortal/utils/Arr.php +++ b/Sources/LightPortal/utils/Arr.php @@ -11,7 +11,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ abstract class Arr @@ -21,40 +21,48 @@ abstract class Arr /** * Try run this object as a function * + * Пытаемся запустить данный объект как функцию + * * @param string $key + * @param mixed $default * @return mixed */ - public function __invoke($name, $default = null) + public function __invoke(string $key, $default = null) { - return static::get($name) ?? $default; + return static::get($key) ?? $default; } /** - * Get the session key + * Get the $obj[$key] value + * + * Получаем значение $obj[$key] * * @param string $key - * @param mixed $default * @return mixed */ - public static function &get($key) + public static function &get(string $key) { return static::$obj[$key]; } /** - * Put the key into a session + * Put $value into the $obj[$key] + * + * Сохраняем $value в ячейке $obj[$key] * * @param string $key * @param mixed $value * @return void */ - public static function put($key, &$value) + public static function put(string $key, $value) { static::$obj[$key] = &$value; } /** - * Get all request array + * Get all $obj values + * + * Получаем все содержимое $obj * * @return array */ @@ -66,6 +74,8 @@ public static function all() /** * Get only the request keys that defined in $keys * + * Получаем значения только запрошенных ключей $keys в $obj + * * @param array|string $keys * @return array */ @@ -87,6 +97,8 @@ public static function only($keys) /** * Get only the request keys that not defined in $keys * + * Получаем значения только тех ключей в $obj, которые не перечислены в $keys + * * @param array|string $keys * @return array */ @@ -106,13 +118,15 @@ public static function except($keys) } /** - * Push a value into the session key-array + * Push a value into the key-array + * + * Сохраняем значение $value в переменную-массив $key * * @param string $key * @param mixed $value * @return void */ - public static function push($key, $value) + public static function push(string $key, $value) { if (! static::has($key) || ! is_array(static::$obj[$key])) return; @@ -126,44 +140,22 @@ public static function push($key, $value) } /** - * Unset the session key + * Unset the $obj key + * + * Очищаем содержимое ячейки $obj[$key] * * @param string $key * @return void */ - public static function forget($key) + public static function forget(string $key) { unset(static::$obj[$key]); } /** - * Unset all session array + * Check if the key is set * - * @return void - */ - public static function flush() - { - unset(static::$obj); - } - - /** - * Get and unset the session key - * - * @param string $key - * @param mixed $default - * @return void - */ - public static function pull($key, $default = null) - { - $result = static::get($key, $default); - - static::forget($key); - - return $result; - } - - /** - * Check if the session key is set + * Проверяем, существует ли ключ $key в $obj * * @param string|array $key * @return bool @@ -182,23 +174,41 @@ public static function has($key) return isset(static::$obj[$key]); } + /** + * Alias for static::has method + * + * Псевдоним для метода static::has + * + * @param string|array $key + * @return bool + */ public static function exists($key) { - return static::has(static::$obj, $key); + return static::has($key); } /** - * Check if the session key exists + * Check if the key is not empty + * + * Проверяем, не пуста ли ячейка $obj[$key] * * @param string $key * @return bool */ - public static function filled($key) + public static function filled(string $key) { return ! static::isEmpty($key); } - public static function isEmpty($key) + /** + * Check if the key is empty + * + * Проверяем, пуста ли ячейка $obj[$key] + * + * @param string $key + * @return bool + */ + public static function isEmpty(string $key) { return empty(static::$obj[$key]); } diff --git a/Sources/LightPortal/utils/Cache.php b/Sources/LightPortal/utils/Cache.php new file mode 100644 index 000000000..0d9cf6ec0 --- /dev/null +++ b/Sources/LightPortal/utils/Cache.php @@ -0,0 +1,112 @@ + + * @copyright 2019-2020 Bugo + * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later + * + * @version 1.3 + */ + +if (!defined('SMF')) + die('Hacking attempt...'); + +class Cache +{ + private static $prefix = 'light_portal_'; + + /** + * Get data from cache + * + * Получаем данные из кэша + * + * @param string $key + * @param string|null $funcName + * @param string $class + * @param int $time (in seconds) + * @param mixed $vars + * @return mixed + */ + public function __invoke(string $key, ?string $funcName, string $class = 'self', int $time = 3600, ...$vars) + { + if (empty($key)) + return false; + + if ($funcName === null || $time === 0) + static::forget($key); + + if (($$key = static::get($key, $time)) === null) { + $$key = null; + + if (method_exists($class, $funcName)) { + $$key = $class == 'self' ? self::$funcName(...$vars) : $class::$funcName(...$vars); + } elseif (function_exists($funcName)) { + $$key = $funcName(...$vars); + } + + static::put($key, $$key, $time); + } + + return $$key; + } + + /** + * Get $key value from the cache + * + * Получаем значение ячейки $key из кэша + * + * @param string $key + * @param int $time + * @return mixed + */ + public static function get(string $key, $time = 120) + { + return cache_get_data(static::$prefix . $key, $time); + } + + /** + * Put $value into $key in the cache for $time ms + * + * Кладем $value в ячейку $key в кэше, на $time мс + * + * @param string $key + * @param mixed $value + * @param int $time + * @return void + */ + public static function put(string $key, $value, $time = 120) + { + cache_put_data(static::$prefix . $key, $value, $time); + } + + /** + * Clear $key from the cache + * + * Очищаем ячейку $key в кэше + * + * @param string $key + * @return void + */ + public static function forget(string $key) + { + self::put($key, null); + } + + /** + * Clear cache + * + * Очищаем кэш + * + * @return void + */ + public static function flush() + { + clean_cache(); + } +} diff --git a/Sources/LightPortal/utils/Post.php b/Sources/LightPortal/utils/Post.php new file mode 100644 index 000000000..661e7b2cb --- /dev/null +++ b/Sources/LightPortal/utils/Post.php @@ -0,0 +1,25 @@ + + * @copyright 2019-2020 Bugo + * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later + * + * @version 1.3 + */ + +class Post extends Request +{ + public static $obj; + + public function __construct() + { + static::$obj = &$_POST; + } +} diff --git a/Sources/LightPortal/utils/Request.php b/Sources/LightPortal/utils/Request.php index e675e4c2f..37bd69e93 100644 --- a/Sources/LightPortal/utils/Request.php +++ b/Sources/LightPortal/utils/Request.php @@ -11,7 +11,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ class Request extends Arr @@ -20,22 +20,26 @@ class Request extends Arr public function __construct() { - static::$obj = $_REQUEST; + static::$obj = &$_REQUEST; } /** - * Get the current path + * Get the current $_SERVER['REQUEST_URI'] + * + * Получаем текущий $_SERVER['REQUEST_URI'] * * @return string */ public static function path() { - return $_SERVER['REQUEST_URI'] ?? ''; + return Server('REQUEST_URI', ''); } /** * Get the full url without queries * + * Получаем полный URL без параметров + * * @return string */ public static function url() @@ -46,16 +50,20 @@ public static function url() /** * Get the current page url * + * Получаем URL текущей страницы + * * @return string */ public static function fullUrl() { - return $_SERVER['REQUEST_URL'] ?? ''; + return Server('REQUEST_URL', ''); } /** * Get the current page url with queries * + * Получаем URL текущей страницы, вместе с параметрами запроса + * * @param array $query * @return string */ @@ -73,6 +81,8 @@ public static function fullUrlWithQuery(array $query = []) /** * Check if the current action matches one of given patterns * + * Проверяем, соответствует ли текущий action одному из указанных в $patterns + * * @param string|array ...$patterns * @return bool */ diff --git a/Sources/LightPortal/utils/Server.php b/Sources/LightPortal/utils/Server.php new file mode 100644 index 000000000..79a829cc7 --- /dev/null +++ b/Sources/LightPortal/utils/Server.php @@ -0,0 +1,25 @@ + + * @copyright 2019-2020 Bugo + * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later + * + * @version 1.3 + */ + +class Server extends Arr +{ + public static $obj; + + public function __construct() + { + static::$obj = &$_SERVER; + } +} diff --git a/Sources/LightPortal/utils/Session.php b/Sources/LightPortal/utils/Session.php index 2a33f066e..70640e0d5 100644 --- a/Sources/LightPortal/utils/Session.php +++ b/Sources/LightPortal/utils/Session.php @@ -11,7 +11,7 @@ * @copyright 2019-2020 Bugo * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * - * @version 1.2 + * @version 1.3 */ class Session extends Arr @@ -20,6 +20,6 @@ class Session extends Arr public function __construct() { - static::$obj = $_SESSION; + static::$obj = &$_SESSION; } } diff --git a/Themes/default/LightPortal/ManageBlocks.template.php b/Themes/default/LightPortal/ManageBlocks.template.php index 03672ca08..88592d666 100644 --- a/Themes/default/LightPortal/ManageBlocks.template.php +++ b/Themes/default/LightPortal/ManageBlocks.template.php @@ -307,7 +307,14 @@ function template_block_post() - + '; + + if (!empty($context['lp_block']['id'])) { + echo ' + '; + } + + echo '
diff --git a/Themes/default/LightPortal/ManagePages.template.php b/Themes/default/LightPortal/ManagePages.template.php index 192ea3d9d..56078b218 100644 --- a/Themes/default/LightPortal/ManagePages.template.php +++ b/Themes/default/LightPortal/ManagePages.template.php @@ -71,12 +71,30 @@ function template_page_post()
- + '; + + if (!empty($context['lp_page']['id'])) { + echo ' + '; + } + + echo '
- '; + + + '; } diff --git a/Themes/default/LightPortal/ManageSettings.template.php b/Themes/default/LightPortal/ManageSettings.template.php index a394e002f..ac976abde 100644 --- a/Themes/default/LightPortal/ManageSettings.template.php +++ b/Themes/default/LightPortal/ManageSettings.template.php @@ -121,6 +121,9 @@ function template_callback_panel_layout() +
+ +
@@ -208,6 +211,9 @@ function template_callback_panel_layout() +
+ +
diff --git a/Themes/default/LightPortal/ViewBlock.template.php b/Themes/default/LightPortal/ViewBlock.template.php index 429145d98..7cf249dc9 100644 --- a/Themes/default/LightPortal/ViewBlock.template.php +++ b/Themes/default/LightPortal/ViewBlock.template.php @@ -34,7 +34,7 @@ function template_portal_above() if (!empty($context['lp_blocks']['left'])) { echo '
-