From a21dc5a788a241a6c5300a5711863997743aba3f Mon Sep 17 00:00:00 2001 From: Bugo Date: Fri, 1 Mar 2024 12:53:21 +0500 Subject: [PATCH 01/25] Update source language strings --- src/Sources/LightPortal/Areas/ConfigArea.php | 22 ++--- src/Sources/LightPortal/Integration.php | 20 ++--- .../LightPortal/LightPortal.english.php | 86 +++++++++---------- 3 files changed, 60 insertions(+), 68 deletions(-) diff --git a/src/Sources/LightPortal/Areas/ConfigArea.php b/src/Sources/LightPortal/Areas/ConfigArea.php index 517f74cd..bacfb39f 100644 --- a/src/Sources/LightPortal/Areas/ConfigArea.php +++ b/src/Sources/LightPortal/Areas/ConfigArea.php @@ -15,8 +15,7 @@ namespace Bugo\LightPortal\Areas; use Bugo\Compat\{Config, Db, Lang, Theme, User, Utils}; -use Bugo\LightPortal\Areas\Configs\{BasicConfig, ExtraConfig}; -use Bugo\LightPortal\Areas\Configs\{FeedbackConfig, MiscConfig, PanelConfig}; +use Bugo\LightPortal\Areas\Configs\{BasicConfig, ExtraConfig, FeedbackConfig, MiscConfig, PanelConfig}; use Bugo\LightPortal\Areas\Exports\{BlockExport, CategoryExport, PageExport, PluginExport, TagExport}; use Bugo\LightPortal\Areas\Imports\{BlockImport, CategoryImport, PageImport, PluginImport, TagImport}; use Bugo\LightPortal\Helper; @@ -183,11 +182,10 @@ public function adminAreas(array &$areas): void */ public function helpadmin(): void { - Lang::$txt['lp_standalone_url_help'] = sprintf( - Lang::$txt['lp_standalone_url_help'], + Lang::$txt['lp_standalone_url_help'] = Lang::getTxt('lp_standalone_url_help', [ Config::$boardurl . '/portal.php', Config::$scripturl - ); + ]); } /** @@ -218,23 +216,21 @@ public function settingAreas(): void class="floatright" src="https://user-images.githubusercontent.com/229402/143980485-16ba84b8-9d8d-4c06-abeb-af949d594f66.png" alt="' . LP_NAME . ' logo" - >' . sprintf( - Lang::$txt['lp_base_info'], + >' . Lang::getTxt('lp_base_info', [ LP_VERSION, phpversion(), Utils::$smcFunc['db_title'], - Db::$db->get_version() - ) + Db::$db->get_version(), + ]) ], 'extra' => [ 'description' => Lang::$txt['lp_extra_info'] ], 'panels' => [ - 'description' => sprintf( - Lang::$txt['lp_panels_info'], + 'description' => Lang::getTxt('lp_panels_info', [ LP_NAME, - 'https://evgenyrodionov.github.io/flexboxgrid2/' - ) + 'https://evgenyrodionov.github.io/flexboxgrid2/', + ]) ], 'misc' => [ 'description' => Lang::$txt['lp_misc_info'] diff --git a/src/Sources/LightPortal/Integration.php b/src/Sources/LightPortal/Integration.php index 89005293..5734634e 100644 --- a/src/Sources/LightPortal/Integration.php +++ b/src/Sources/LightPortal/Integration.php @@ -428,11 +428,10 @@ public function whosOnline(array $actions): string $result = sprintf(Lang::$txt['lp_who_viewing_frontpage'], Config::$scripturl); if ($this->isStandaloneMode()) { - $result = sprintf( - Lang::$txt['lp_who_viewing_index'], + $result = Lang::getTxt('lp_who_viewing_index', [ Config::$modSettings['lp_standalone_url'], Config::$scripturl - ); + ]); } } @@ -453,11 +452,10 @@ public function whosOnline(array $actions): string $tags = $this->getEntityData('tag'); $result = isset($actions['id']) - ? sprintf( - Lang::$txt['lp_who_viewing_the_tag'], + ? Lang::getTxt('lp_who_viewing_the_tag', [ LP_BASE_URL . ';sa=tags;id=' . $actions['id'], $tags[$actions['id']] - ) + ]) : sprintf( Lang::$txt['lp_who_viewing_tags'], LP_BASE_URL . ';sa=tags' @@ -468,11 +466,10 @@ public function whosOnline(array $actions): string $categories = $this->getEntityData('category'); $result = isset($actions['id']) - ? sprintf( - Lang::$txt['lp_who_viewing_the_category'], + ? Lang::getTxt('lp_who_viewing_the_category', [ LP_BASE_URL . ';sa=categories;id=' . $actions['id'], $categories[$actions['id']]['name'] - ) + ]) : sprintf( Lang::$txt['lp_who_viewing_categories'], LP_BASE_URL . ';sa=categories' @@ -481,11 +478,10 @@ public function whosOnline(array $actions): string } if ($actions['action'] === 'forum') { - $result = sprintf( - Lang::$txt['who_index'], + $result = Lang::getTxt('who_index', [ Config::$scripturl . '?action=forum', Utils::$context['forum_name'] - ); + ]); } return $result; diff --git a/src/Themes/default/languages/LightPortal/LightPortal.english.php b/src/Themes/default/languages/LightPortal/LightPortal.english.php index b26dc616..9167596c 100644 --- a/src/Themes/default/languages/LightPortal/LightPortal.english.php +++ b/src/Themes/default/languages/LightPortal/LightPortal.english.php @@ -28,7 +28,7 @@ // Settings $txt['lp_settings'] = 'Portal settings'; $txt['lp_base'] = 'Settings for the frontpage and articles'; -$txt['lp_base_info'] = 'The mod version: %1$s, PHP version: %2$s, %3$s version: %4$s.
One can discuss bugs and features of the portal at simplemachines.org.
The portal always needs new testers, translators, and front-page template makers.'; +$txt['lp_base_info'] = 'The mod version: {0}, PHP version: {1}, {2} version: {3}.
One can discuss bugs and features of the portal at simplemachines.org.
The portal always needs new testers, translators, and front-page template makers.'; $txt['lp_frontpage_title'] = 'The frontpage title'; $txt['lp_frontpage_mode'] = 'The portal frontpage'; @@ -60,7 +60,7 @@ $txt['lp_show_layout_switcher'] = 'Show layout switcher'; $txt['lp_frontpage_num_columns'] = 'Number of columns for displaying articles'; $txt['lp_frontpage_num_columns_set'] = '{columns, plural, - one {# column} + one {# column} other {# columns} }'; $txt['lp_show_pagination'] = 'Show the pagination'; @@ -70,7 +70,7 @@ $txt['lp_standalone_mode_title'] = 'Standalone mode'; $txt['lp_standalone_url'] = 'The frontpage URL in the standalone mode'; -$txt['lp_standalone_url_help'] = 'You can specify your own URL to display as the portal frontpage (for instance, %1$s).
In this case, the forum frontpage will remain available at %2$s.

As an example, the portal.php file is included with the portal — you can use it.

Disable the "Enable local storage of cookies" option if you want to place portal.php outside the forum directory (Maintenance => Server Settings => Cookies and Sessions).'; +$txt['lp_standalone_url_help'] = 'You can specify your own URL to display as the portal frontpage (for instance, {0}).
In this case, the forum frontpage will remain available at {1}.

As an example, the portal.php file is included with the portal — you can use it.

Disable the "Enable local storage of cookies" option if you want to place portal.php outside the forum directory (Maintenance => Server Settings => Cookies and Sessions).'; $txt['lp_disabled_actions'] = 'Disabled actions'; $txt['lp_disabled_actions_subtext'] = 'Specify the areas that should be DISABLED in the standalone mode.'; $txt['lp_disabled_actions_help'] = 'For example, if you need to disable the Search area (index.php?action=search), add search into the text field.'; @@ -108,7 +108,7 @@ // Panels $txt['lp_panels'] = 'Panels'; -$txt['lp_panels_info'] = 'Here you can customize the width of some panels, as well as the direction of blocks.
%1$s uses 12 column grid system to display blocks in 6 panels.'; +$txt['lp_panels_info'] = 'Here you can customize the width of some panels, as well as the direction of blocks.
{0} uses 12 column grid system to display blocks in 6 panels.'; $txt['lp_swap_header_footer'] = 'Swap the header and the footer'; $txt['lp_swap_left_right'] = 'Swap the left panel and the right panel'; $txt['lp_swap_top_bottom'] = 'Swap the center (top) and the center (bottom)'; @@ -153,7 +153,7 @@ $txt['lp_blocks_add'] = 'Add block'; $txt['lp_blocks_add_title'] = 'Adding a block'; $txt['lp_blocks_add_description'] = 'Blocks can contain any content, depending on their type.'; -$txt['lp_blocks_add_instruction'] = 'Select the desired block by clicking on it. If the block you need is not on the list, check if the corresponding plugin is enabled.'; +$txt['lp_blocks_add_instruction'] = 'Select the desired block by clicking on it. If the block you need is not on the list, check if the corresponding plugin is enabled.'; $txt['lp_blocks_edit_title'] = 'Editing block'; $txt['lp_blocks_edit_description'] = $txt['lp_blocks_add_description']; $txt['lp_block_type'] = 'Block type'; @@ -166,7 +166,7 @@ $txt['lp_block_areas'] = 'Display areas'; $txt['lp_block_areas_subtext'] = 'Specify one or more areas (separate by comma) to display the block in'; $txt['lp_block_areas_th'] = 'Custom areas'; -$txt['lp_block_areas_values'][0] = 'on area index.php?action=custom_action (for example: %1$s)'; +$txt['lp_block_areas_values'][0] = 'on area index.php?action=custom_action (for example: %s)'; $txt['lp_block_areas_values'][1] = 'everywhere, except custom_action (used as an exception, in addition to the preset areas)'; $txt['lp_block_areas_values'][2] = 'on page index.php?page=alias'; $txt['lp_block_areas_values'][3] = 'only inside the board with identifier id (including all topics inside the board)'; @@ -243,7 +243,7 @@ $txt['lp_category'] = 'Category'; $txt['lp_no_category'] = 'Uncategorized'; $txt['lp_all_categories'] = 'All categories of the portal'; -$txt['lp_all_pages_with_category'] = 'All pages in category "%1$s"'; +$txt['lp_all_pages_with_category'] = 'All pages in category "%s"'; $txt['lp_all_pages_without_category'] = 'All pages without category'; $txt['lp_category_not_found'] = 'The specified category was not found.'; $txt['lp_no_categories'] = 'There are no categories yet.'; @@ -259,7 +259,7 @@ $txt['lp_tags_edit_title'] = 'Editing tag'; $txt['lp_tags_edit_description'] = 'Make the necessary changes.'; $txt['lp_all_page_tags'] = 'All portal page tags'; -$txt['lp_all_tags_by_key'] = 'All pages with the "%1$s" tag'; +$txt['lp_all_tags_by_key'] = 'All pages with the "%s" tag'; $txt['lp_tag_not_found'] = 'The specified tag was not found.'; $txt['lp_no_tags'] = 'There are no tags yet.'; $txt['lp_tag_column'] = 'Keyword'; @@ -322,12 +322,12 @@ $txt['lp_import_run'] = 'Run import'; $txt['lp_export_all'] = 'Export all'; $txt['lp_import_all'] = 'Import all'; -$txt['lp_import_success'] = 'Imported: %1$s'; +$txt['lp_import_success'] = 'Imported: %s'; // Plugins $txt['lp_plugins'] = 'Plugins'; $txt['lp_plugins_manage'] = 'Manage plugins'; -$txt['lp_plugins_manage_description'] = 'The installed portal plugins are listed here. You can always create a new one using the instructions.'; +$txt['lp_plugins_manage_description'] = 'The installed portal plugins are listed here. You can always create a new one using the instructions.'; $txt['lp_plugins_desc'] = 'Plugins extend the capabilities of the portal and its components, providing additional features that are not available in the core.'; $txt['lp_plugins_types'][0] = 'Block'; $txt['lp_plugins_types'][1] = 'SSI'; @@ -356,20 +356,20 @@ $txt['alert_page_comment'] = 'When my page gets a comment'; $txt['alert_new_comment_page_comment'] = '{gender, select, female {{member_link} left a comment {content_subject}} - male {{member_link} left a comment {content_subject}} - other {{member_link} left a comment {content_subject}} + male {{member_link} left a comment {content_subject}} + other {{member_link} left a comment {content_subject}} }'; $txt['alert_page_comment_reply'] = 'When my comment gets a reply'; $txt['alert_new_reply_page_comment_reply'] = '{gender, select, female {{member_link} left a reply to your comment {content_subject}} - male {{member_link} left a reply to your comment {content_subject}} - other {{member_link} left a reply to your comment {content_subject}} + male {{member_link} left a reply to your comment {content_subject}} + other {{member_link} left a reply to your comment {content_subject}} }'; $txt['alert_page_unapproved'] = 'When a new unapproved page appears'; $txt['alert_new_page_page_unapproved'] = '{gender, select, female {{member_link} created a page {content_subject}} - male {{member_link} created a page {content_subject}} - other {{member_link} created a page {content_subject}} + male {{member_link} created a page {content_subject}} + other {{member_link} created a page {content_subject}} }'; // Emails @@ -399,17 +399,17 @@ $txt['lp_wrong_import_file'] = 'Wrong file to import...'; $txt['lp_import_failed'] = 'Failed to import...'; $txt['lp_wrong_template'] = 'Wrong template. Choose a template that matches the content.'; -$txt['lp_addon_not_installed'] = 'Plugin %1$s is not installed'; -$txt['lp_addon_not_activated'] = 'Plugin %1$s is not activated'; +$txt['lp_addon_not_installed'] = 'Plugin %s is not installed'; +$txt['lp_addon_not_activated'] = 'Plugin %s is not activated'; // Who -$txt['lp_who_viewing_frontpage'] = 'Viewing the portal frontpage.'; -$txt['lp_who_viewing_index'] = 'Viewing the portal frontpage or the forum index.'; -$txt['lp_who_viewing_page'] = 'Viewing the portal page.'; -$txt['lp_who_viewing_tags'] = 'Viewing the portal page tags.'; -$txt['lp_who_viewing_the_tag'] = 'Viewing the page list with %2$s tag.'; -$txt['lp_who_viewing_categories'] = 'Viewing the portal page categories.'; -$txt['lp_who_viewing_the_category'] = 'Viewing the page list within %2$s category.'; +$txt['lp_who_viewing_frontpage'] = 'Viewing the portal frontpage.'; +$txt['lp_who_viewing_index'] = 'Viewing the portal frontpage or the forum index.'; +$txt['lp_who_viewing_page'] = 'Viewing the portal page.'; +$txt['lp_who_viewing_tags'] = 'Viewing the portal page tags.'; +$txt['lp_who_viewing_the_tag'] = 'Viewing the page list with {1} tag.'; +$txt['lp_who_viewing_categories'] = 'Viewing the portal page categories.'; +$txt['lp_who_viewing_the_category'] = 'Viewing the page list within {1} category.'; // Permissions $txt['permissionname_light_portal_view'] = $txt['group_perms_name_light_portal_view'] = 'View the portal elements'; @@ -429,79 +429,79 @@ // Time units $txt['lp_months_set'] = '{months, plural, - one {a month} + =1 {a month} other {# months} }'; $txt['lp_days_set'] = '{days, plural, - one {a day} + =1 {a day} other {# days} }'; $txt['lp_hours_set'] = '{hours, plural, - one {an hour} + =1 {an hour} other {# hours} }'; $txt['lp_minutes_set'] = '{minutes, plural, - one {a minute} + =1 {a minute} other {# minutes} }'; $txt['lp_seconds_set'] = '{seconds, plural, - one {a second} + =1 {a second} other {# seconds} }'; $txt['lp_tomorrow'] = 'Tomorrow at '; $txt['lp_just_now'] = 'Just now'; -$txt['lp_time_label_in'] = 'In %1$s'; +$txt['lp_time_label_in'] = 'In %s'; $txt['lp_time_label_ago'] = ' ago'; // Social units $txt['lp_replies_set'] = '{replies, plural, - one {# reply} + one {# reply} other {# replies} }'; $txt['lp_views_set'] = '{views, plural, - one {# view} + one {# view} other {# views} }'; $txt['lp_comments_set'] = '{comments, plural, - one {# comment} + one {# comment} other {# comments} }'; $txt['lp_articles_set'] = '{articles, plural, - one {# article} + one {# article} other {# articles} }'; // Other units $txt['lp_pages_set'] = '{pages, plural, - one {# page} + one {# page} other {# pages} }'; $txt['lp_blocks_set'] = '{blocks, plural, - one {# block} + one {# block} other {# blocks} }'; $txt['lp_users_set'] = '{users, plural, - one {# user} + one {# user} other {# users} }'; $txt['lp_guests_set'] = '{guests, plural, - one {# guest} + one {# guest} other {# guests} }'; $txt['lp_spiders_set'] = '{spiders, plural, - one {# spider} + one {# spider} other {# spiders} }'; $txt['lp_hidden_set'] = '{hidden, plural, - one {# hidden} + one {# hidden} other {# hidden} }'; $txt['lp_buddies_set'] = '{buddies, plural, - one {# buddy} + one {# buddy} other {# buddies} }'; $txt['lp_queries_set'] = '{queries, plural, - one {# query} + one {# query} other {# queries} }'; From c21b78cf50fe7d4f30eafbb746bf8e97e630bcfa Mon Sep 17 00:00:00 2001 From: Bugo Date: Fri, 1 Mar 2024 14:15:45 +0500 Subject: [PATCH 02/25] Display tags field only if active tags count > 0 --- src/Sources/LightPortal/Areas/PageArea.php | 12 +++++++++--- .../languages/LightPortal/LightPortal.english.php | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Sources/LightPortal/Areas/PageArea.php b/src/Sources/LightPortal/Areas/PageArea.php index 5dbe898d..9a36f957 100644 --- a/src/Sources/LightPortal/Areas/PageArea.php +++ b/src/Sources/LightPortal/Areas/PageArea.php @@ -676,9 +676,15 @@ private function prepareFormFields(): void ->setAttribute('maxlength', 255) ->setValue(Utils::$context['lp_page']['description']); - CustomField::make('tags', Lang::$txt['lp_tags']) - ->setTab('seo') - ->setValue(static fn() => new TagSelect()); + if (empty(Utils::$context['lp_quantities']['active_tags'])) { + TextField::make('tags', '') + ->setAttribute('hidden', true) + ->setValue(''); + } else { + CustomField::make('tags', Lang::$txt['lp_tags']) + ->setTab('seo') + ->setValue(static fn() => new TagSelect()); + } if (Utils::$context['lp_page']['created_at'] >= time()) { CustomField::make('datetime', Lang::$txt['lp_page_publish_datetime']) diff --git a/src/Themes/default/languages/LightPortal/LightPortal.english.php b/src/Themes/default/languages/LightPortal/LightPortal.english.php index 9167596c..af581a7e 100644 --- a/src/Themes/default/languages/LightPortal/LightPortal.english.php +++ b/src/Themes/default/languages/LightPortal/LightPortal.english.php @@ -218,7 +218,7 @@ $txt['lp_page_alias_subtext'] = 'The page alias must begin with a Latin letter and consist of lowercase Latin letters, numbers, and underscores.'; $txt['lp_page_type'] = 'Page type'; $txt['lp_page_description'] = 'Description'; -$txt['lp_page_tags_placeholder'] = 'Select tags or add new'; +$txt['lp_page_tags_placeholder'] = 'Select tags'; $txt['lp_page_tags_empty'] = 'No tags yet'; $txt['lp_page_publish_datetime'] = 'Date and time of publication'; $txt['lp_page_author'] = 'Transfer of authorship'; From 0291a76cb80c9335d3864eed9872dd89f838031e Mon Sep 17 00:00:00 2001 From: Bugo Date: Sun, 3 Mar 2024 00:02:10 +0500 Subject: [PATCH 03/25] Remove Todays --- .../LightPortal/Addons/Todays/Todays.php | 168 ------------------ .../LightPortal/Addons/Todays/index.php | 6 - .../Addons/Todays/langs/english.php | 15 -- .../LightPortal/Addons/Todays/langs/index.php | 6 - .../LightPortal/Addons/Todays/style.css | 53 ------ 5 files changed, 248 deletions(-) delete mode 100644 src/Sources/LightPortal/Addons/Todays/Todays.php delete mode 100644 src/Sources/LightPortal/Addons/Todays/index.php delete mode 100644 src/Sources/LightPortal/Addons/Todays/langs/english.php delete mode 100644 src/Sources/LightPortal/Addons/Todays/langs/index.php delete mode 100644 src/Sources/LightPortal/Addons/Todays/style.css diff --git a/src/Sources/LightPortal/Addons/Todays/Todays.php b/src/Sources/LightPortal/Addons/Todays/Todays.php deleted file mode 100644 index a71c2e2f..00000000 --- a/src/Sources/LightPortal/Addons/Todays/Todays.php +++ /dev/null @@ -1,168 +0,0 @@ - - * @copyright 2020-2024 Bugo - * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later - * - * @category addon - * @version 17.02.24 - */ - -namespace Bugo\LightPortal\Addons\Todays; - -use Bugo\Compat\{Config, Lang, Utils}; -use Bugo\LightPortal\Addons\Block; -use Bugo\LightPortal\Areas\Fields\{RangeField, SelectField}; - -if (! defined('LP_NAME')) - die('No direct access...'); - -class Todays extends Block -{ - public string $type = 'block ssi'; - - public string $icon = 'fas fa-calendar-day'; - - public function init(): void - { - $this->applyHook('menu_buttons'); - } - - public function menuButtons(array &$buttons): void - { - $buttons['calendar']['show'] = Utils::$context['allow_calendar'] - && empty(Utils::$context['lp_todays_plugin']['hide_calendar_in_menu']); - } - - public function addSettings(array &$settings): void - { - $settings['todays'][] = [ - 'check', - 'hide_calendar_in_menu', - 'subtext' => sprintf( - Lang::$txt['lp_todays']['hide_calendar_in_menu_subtext'], - Config::$scripturl . '?action=admin;area=managecalendar;sa=settings' - ) - ]; - } - - public function prepareBlockParams(array &$params): void - { - if (Utils::$context['current_block']['type'] !== 'todays') - return; - - $params = [ - 'widget_type' => 'calendar', - 'max_items' => 1, - ]; - } - - public function validateBlockParams(array &$params): void - { - if (Utils::$context['current_block']['type'] !== 'todays') - return; - - $params = [ - 'widget_type' => FILTER_DEFAULT, - 'max_items' => FILTER_VALIDATE_INT, - ]; - } - - public function prepareBlockFields(): void - { - if (Utils::$context['current_block']['type'] !== 'todays') - return; - - SelectField::make('widget_type', Lang::$txt['lp_todays']['type']) - ->setTab('content') - ->setOptions(array_combine( - ['birthdays', 'holidays', 'events', 'calendar'], - Lang::$txt['lp_todays']['type_set'] - )) - ->setValue(Utils::$context['lp_block']['options']['widget_type']); - - RangeField::make('max_items', Lang::$txt['lp_todays']['max_items']) - ->setAfter(Lang::$txt['lp_todays']['max_items_subtext']) - ->setAttribute('min', 1) - ->setAttribute('max', 100) - ->setValue(Utils::$context['lp_block']['options']['max_items']); - } - - public function getData(string $type, string $output_method = 'echo') - { - return $this->getFromSsi('todays' . ucfirst($type), $output_method); - } - - public function prepareContent(object $data, array $parameters): void - { - if ($data->type !== 'todays') - return; - - $result = $this->getData($parameters['widget_type'], 'array'); - - if ($parameters['widget_type'] === 'calendar') { - if ($result['calendar_holidays'] || $result['calendar_birthdays'] || $result['calendar_events']) - $this->getData($parameters['widget_type']); - else - echo Lang::$txt['lp_todays']['empty_list']; - } elseif ($parameters['widget_type'] === 'events' && $result) { - echo ' -
    '; - - foreach ($result as $event) { - echo ' -
  • ', $event['start_date_local'], ' - ', $event['link'], ( - $event['can_edit'] ? ' *' : '' - ), '
  • '; - } - - echo ' -
'; - } elseif ($result) { - if ($parameters['widget_type'] !== 'birthdays' || count($result) <= $parameters['max_items']) { - $this->getData($parameters['widget_type']); - } else { - $visibleItems = array_slice($result, 0, $parameters['max_items']); - $visibleItems[$parameters['max_items'] - 1]['is_last'] = true; - $hiddenItems = array_slice($result, $parameters['max_items']); - - foreach ($visibleItems as $member) { - echo ' - - ' . $member['name'] . '' - . (isset($member['age']) ? ' (' . $member['age'] . ')' : '') . ' - ' . ($member['is_last'] ? '' : ', '); - } - - $hiddenContent = ''; - foreach ($hiddenItems as $member) { - if ($member['is_today']) - $hiddenContent .= ' - - ' . $member['name'] . '' - . (isset($member['age']) ? ' (' . $member['age'] . ')' : '') . ' - ' . ($member['is_last'] ? '' : ', '); - } - - if ($hiddenContent) - echo Lang::$txt['lp_todays']['and_more'], ' -
- - ', Lang::getTxt( - Lang::$txt['lp_todays']['birthdays_set'], - ['count' => count($result) - $parameters['max_items']] - ), ' - -
', $hiddenContent, '
-
'; - } - } else { - echo Lang::$txt['lp_todays']['empty_list']; - } - } -} diff --git a/src/Sources/LightPortal/Addons/Todays/index.php b/src/Sources/LightPortal/Addons/Todays/index.php deleted file mode 100644 index 66249736..00000000 --- a/src/Sources/LightPortal/Addons/Todays/index.php +++ /dev/null @@ -1,6 +0,0 @@ - 'Today', - 'description' => 'Displays the calendar, birthdays, holidays, or today\'s events.', - 'hide_calendar_in_menu' => 'Hide the "Calendar" item in the main menu', - 'hide_calendar_in_menu_subtext' => 'You need to enable Calendar to make this block work properly. But if you do not want to see it in the menu, you can hide it.', - 'type' => 'What to display', - 'type_set' => ['Birthdays', 'Holidays', 'Events', 'Calendar'], - 'max_items' => 'Maximum number of birthday men in the list', - 'max_items_subtext' => 'If there are more birthday men, the remaining ones will be hidden under the spoiler.', - 'and_more' => ' and more ', - 'birthdays_set' => '{count, plural, one {# birthday man} other {# birthday men}}', - 'empty_list' => 'There is nothing today.', -]; diff --git a/src/Sources/LightPortal/Addons/Todays/langs/index.php b/src/Sources/LightPortal/Addons/Todays/langs/index.php deleted file mode 100644 index 66249736..00000000 --- a/src/Sources/LightPortal/Addons/Todays/langs/index.php +++ /dev/null @@ -1,6 +0,0 @@ - Date: Sun, 3 Mar 2024 00:02:50 +0500 Subject: [PATCH 04/25] Trim spaces in titles on saving/editing --- src/Sources/LightPortal/Repositories/AbstractRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Sources/LightPortal/Repositories/AbstractRepository.php b/src/Sources/LightPortal/Repositories/AbstractRepository.php index b74a9a4e..d3468498 100644 --- a/src/Sources/LightPortal/Repositories/AbstractRepository.php +++ b/src/Sources/LightPortal/Repositories/AbstractRepository.php @@ -84,7 +84,7 @@ protected function saveTitles(int $item, string $method = ''): void 'item_id' => $item, 'type' => $this->entity, 'lang' => $lang, - 'title' => $title, + 'title' => Utils::$smcFunc['htmltrim']($title), ]; } From 2277f81611696249264be003c2898396976b5471 Mon Sep 17 00:00:00 2001 From: Bugo Date: Sun, 3 Mar 2024 00:03:13 +0500 Subject: [PATCH 05/25] Colorize some icon buttons --- src/Themes/default/css/light_portal/sass/hacks.scss | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/Themes/default/css/light_portal/sass/hacks.scss b/src/Themes/default/css/light_portal/sass/hacks.scss index 882faebc..2e6bcd32 100644 --- a/src/Themes/default/css/light_portal/sass/hacks.scss +++ b/src/Themes/default/css/light_portal/sass/hacks.scss @@ -175,4 +175,15 @@ i[class] { transform: scaleX(-1); } +} + +/* Icon colors */ +.fa-square-check { + color: red; +} +.fa-circle-check { + color: green; +} +.fa-check-double { + color: orange; } \ No newline at end of file From e93385e4e79466e650286ddde2033eead28c679e Mon Sep 17 00:00:00 2001 From: Bugo Date: Sun, 3 Mar 2024 00:04:05 +0500 Subject: [PATCH 06/25] Improve styles for article images --- .../default/css/light_portal/sass/page.scss | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/Themes/default/css/light_portal/sass/page.scss b/src/Themes/default/css/light_portal/sass/page.scss index 97d32884..b3624e15 100644 --- a/src/Themes/default/css/light_portal/sass/page.scss +++ b/src/Themes/default/css/light_portal/sass/page.scss @@ -18,9 +18,24 @@ section { } } - article { + article[itemprop='articleBody'] { .button { margin: 2px auto; } + + a:has(img) { + display: grid; + place-items: center; + + } + + img { + display: grid; + place-items: center; + border: 1px solid #ddd; + border-radius: 4px; + box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); + padding: 5px; + } } } \ No newline at end of file From 38377acb0aad30effee4eed872b79a83414f9395 Mon Sep 17 00:00:00 2001 From: Bugo Date: Sun, 3 Mar 2024 09:33:08 +0500 Subject: [PATCH 07/25] Fix an issue with shorten article titles --- src/Themes/default/css/light_portal/sass/frontpage_alt3.scss | 2 +- src/Themes/default/css/light_portal/sass/frontpage_default.scss | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Themes/default/css/light_portal/sass/frontpage_alt3.scss b/src/Themes/default/css/light_portal/sass/frontpage_alt3.scss index 0239e545..42abe2ac 100644 --- a/src/Themes/default/css/light_portal/sass/frontpage_alt3.scss +++ b/src/Themes/default/css/light_portal/sass/frontpage_alt3.scss @@ -45,7 +45,7 @@ -webkit-line-clamp: 2; -webkit-box-orient: vertical; line-height: 1; - text-wrap: balance; + text-wrap: wrap; } p { diff --git a/src/Themes/default/css/light_portal/sass/frontpage_default.scss b/src/Themes/default/css/light_portal/sass/frontpage_default.scss index c03d365c..349e3104 100644 --- a/src/Themes/default/css/light_portal/sass/frontpage_default.scss +++ b/src/Themes/default/css/light_portal/sass/frontpage_default.scss @@ -123,7 +123,7 @@ -webkit-line-clamp: 2; -webkit-box-orient: vertical; line-height: 1.3; - text-wrap: balance; + text-wrap: wrap; + div { display: flex; From 43335d8db102a1479defc69a165524b80e9b5ef2 Mon Sep 17 00:00:00 2001 From: Bugo Date: Mon, 4 Mar 2024 00:34:56 +0500 Subject: [PATCH 08/25] Refactor code --- src/Sources/LightPortal/Actions/Category.php | 30 +++++++++---------- src/Sources/LightPortal/Actions/Tag.php | 10 +++---- .../Addons/ArticleList/ArticleList.php | 10 +++---- .../Addons/CurrentMonth/CurrentMonth.php | 10 +++---- .../LightPortal/Addons/TagList/TagList.php | 4 +-- .../LightPortal/Areas/CategoryArea.php | 4 +-- .../LightPortal/Articles/PageArticle.php | 6 ++-- .../LightPortal/Lists/CategoryList.php | 4 +-- src/Sources/LightPortal/Lists/TagList.php | 6 ++-- .../Repositories/AbstractRepository.php | 7 ++++- .../Repositories/CategoryRepository.php | 4 +-- .../Repositories/PageRepository.php | 22 ++++++++------ .../Repositories/TagRepository.php | 4 +-- 13 files changed, 64 insertions(+), 57 deletions(-) diff --git a/src/Sources/LightPortal/Actions/Category.php b/src/Sources/LightPortal/Actions/Category.php index 903c01ff..0c5cca8a 100644 --- a/src/Sources/LightPortal/Actions/Category.php +++ b/src/Sources/LightPortal/Actions/Category.php @@ -183,30 +183,30 @@ public function showAll(): void 'function' => fn() => count($this->getAll()) ], 'columns' => [ - 'title' => [ + 'priority' => [ 'header' => [ - 'value' => Lang::$txt['lp_category'] + 'value' => Lang::$txt['lp_block_priority'] ], 'data' => [ - 'function' => static fn($entry) => $entry['icon'] . ' ' . '' . $entry['title'] . '' . - (empty($entry['description']) ? '' : '

' . $entry['description'] . '

') + 'db' => 'priority', + 'class' => 'centertext' ], 'sort' => [ - 'default' => 't.title DESC', - 'reverse' => 't.title' + 'default' => 'c.priority', + 'reverse' => 'c.priority DESC' ] ], - 'priority' => [ + 'title' => [ 'header' => [ - 'value' => Lang::$txt['lp_block_priority'] + 'value' => Lang::$txt['lp_category'] ], 'data' => [ - 'db' => 'priority', - 'class' => 'centertext' + 'function' => static fn($entry) => $entry['icon'] . ' ' . '' . $entry['title'] . '' . + (empty($entry['description']) ? '' : '

' . $entry['description'] . '

') ], 'sort' => [ - 'default' => 'c.priority', - 'reverse' => 'c.priority DESC' + 'default' => 'title DESC', + 'reverse' => 'title' ] ], 'num_pages' => [ @@ -233,12 +233,12 @@ public function showAll(): void Utils::obExit(); } - public function getAll(int $start = 0, int $limit = 0, string $sort = 't.title'): array + public function getAll(int $start = 0, int $limit = 0, string $sort = 'title'): array { $result = Db::$db->query('', ' SELECT COALESCE(c.category_id, 0) AS category_id, c.icon, c.description, c.priority, - COUNT(p.page_id) AS frequency, COALESCE(t.title, tf.title) AS cat_title + COUNT(p.page_id) AS frequency, COALESCE(t.title, tf.title) AS title FROM {db_prefix}lp_pages AS p LEFT JOIN {db_prefix}lp_categories AS c ON (p.category_id = c.category_id) LEFT JOIN {db_prefix}lp_titles AS t ON ( @@ -271,7 +271,7 @@ public function getAll(int $start = 0, int $limit = 0, string $sort = 't.title') while ($row = Db::$db->fetch_assoc($result)) { $items[$row['category_id']] = [ 'icon' => $this->getIcon($row['icon']), - 'title' => $row['cat_title'] ?: Lang::$txt['lp_no_category'], + 'title' => $row['title'] ?: Lang::$txt['lp_no_category'], 'description' => $row['description'] ?? '', 'link' => LP_BASE_URL . ';sa=categories;id=' . $row['category_id'], 'priority' => (int) $row['priority'], diff --git a/src/Sources/LightPortal/Actions/Tag.php b/src/Sources/LightPortal/Actions/Tag.php index 9b95c243..59ab77b5 100644 --- a/src/Sources/LightPortal/Actions/Tag.php +++ b/src/Sources/LightPortal/Actions/Tag.php @@ -191,8 +191,8 @@ public function showAll(): void 'class' => 'centertext' ], 'sort' => [ - 'default' => 'tag_title DESC', - 'reverse' => 'tag_title' + 'default' => 'title DESC', + 'reverse' => 'title' ] ], 'frequency' => [ @@ -219,10 +219,10 @@ public function showAll(): void Utils::obExit(); } - public function getAll(int $start = 0, int $limit = 0, string $sort = 'tag_title'): array + public function getAll(int $start = 0, int $limit = 0, string $sort = 'title'): array { $result = Db::$db->query('', ' - SELECT tag.tag_id, tag.icon, COALESCE(tt.title, tf.title) AS tag_title, COUNT(tag.tag_id) AS frequency + SELECT tag.tag_id, tag.icon, COALESCE(tt.title, tf.title) AS title, COUNT(tag.tag_id) AS frequency FROM {db_prefix}lp_pages AS p INNER JOIN {db_prefix}lp_page_tags AS pt ON (p.page_id = pt.page_id) INNER JOIN {db_prefix}lp_tags AS tag ON (pt.tag_id = tag.tag_id) @@ -256,7 +256,7 @@ public function getAll(int $start = 0, int $limit = 0, string $sort = 'tag_title while ($row = Db::$db->fetch_assoc($result)) { $items[$row['tag_id']] = [ 'icon' => $this->getIcon($row['icon']), - 'title' => $row['tag_title'], + 'title' => $row['title'], 'link' => LP_BASE_URL . ';sa=tags;id=' . $row['tag_id'], 'frequency' => (int) $row['frequency'], ]; diff --git a/src/Sources/LightPortal/Addons/ArticleList/ArticleList.php b/src/Sources/LightPortal/Addons/ArticleList/ArticleList.php index d1c08551..b0a046f8 100644 --- a/src/Sources/LightPortal/Addons/ArticleList/ArticleList.php +++ b/src/Sources/LightPortal/Addons/ArticleList/ArticleList.php @@ -10,7 +10,7 @@ * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * * @category addon - * @version 20.02.24 + * @version 01.03.24 */ namespace Bugo\LightPortal\Addons\ArticleList; @@ -194,7 +194,7 @@ public function prepareContent(object $data, array $parameters): void if ($data->type !== 'article_list') return; - $article_list = $this->cache('article_list_addon_b' . $data->id . '_u' . User::$info['id']) + $articles = $this->cache('article_list_addon_b' . $data->id . '_u' . User::$info['id']) ->setLifeTime($data->cacheTime) ->setFallback( self::class, @@ -202,12 +202,12 @@ public function prepareContent(object $data, array $parameters): void $parameters ); - if ($article_list) { + if ($articles) { echo '
'; if (empty($parameters['display_type'])) { - foreach ($article_list as $topic) { + foreach ($articles as $topic) { $content = ''; if ($topic['image']) { $content .= ' @@ -221,7 +221,7 @@ public function prepareContent(object $data, array $parameters): void echo sprintf(Utils::$context['lp_all_content_classes'][$parameters['body_class']], $content); } } else { - foreach ($article_list as $page) { + foreach ($articles as $page) { if (empty($title = $this->getTranslatedTitle($page['title']))) continue; diff --git a/src/Sources/LightPortal/Addons/CurrentMonth/CurrentMonth.php b/src/Sources/LightPortal/Addons/CurrentMonth/CurrentMonth.php index 11bc5455..4742bd7c 100644 --- a/src/Sources/LightPortal/Addons/CurrentMonth/CurrentMonth.php +++ b/src/Sources/LightPortal/Addons/CurrentMonth/CurrentMonth.php @@ -10,12 +10,12 @@ * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * * @category addon - * @version 17.02.24 + * @version 01.03.24 */ namespace Bugo\LightPortal\Addons\CurrentMonth; -use Bugo\Compat\{Config, Lang, Theme, User, Utils}; +use Bugo\Compat\{Calendar, Config, Lang, Theme, User, Utils}; use Bugo\LightPortal\Addons\Block; if (! defined('LP_NAME')) @@ -35,9 +35,7 @@ public function prepareBlockParams(array &$params): void public function getData(): array { - $this->require('Subs-Calendar'); - - $today = getTodayInfo(); + $today = Calendar::getTodayInfo(); $year = $today['year']; $month = $today['month']; $day = $today['day']; @@ -58,7 +56,7 @@ public function getData(): array 'show_week_links' => (int) (Config::$modSettings['cal_week_links'] ?? 0) ]; - return getCalendarGrid(date_format($startObject, 'Y-m-d'), $options, has_picker: false); + return Calendar::getCalendarGrid(date_format($startObject, 'Y-m-d'), $options, has_picker: false); } public function prepareContent(object $data): void diff --git a/src/Sources/LightPortal/Addons/TagList/TagList.php b/src/Sources/LightPortal/Addons/TagList/TagList.php index 0ea3c345..c1ea5b3b 100644 --- a/src/Sources/LightPortal/Addons/TagList/TagList.php +++ b/src/Sources/LightPortal/Addons/TagList/TagList.php @@ -10,7 +10,7 @@ * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * * @category addon - * @version 26.02.24 + * @version 03.03.24 */ namespace Bugo\LightPortal\Addons\TagList; @@ -105,7 +105,7 @@ public function prepareContent(object $data, array $parameters): void if ($parameters['source'] == 'lp_tags') { $tagList = $this->cache('tag_list_addon_b' . $data->id . '_u' . User::$info['id']) ->setLifeTime($data->cacheTime) - ->setFallback(Tag::class, 'getAll', 0, 0, $parameters['sorting'] === 'name' ? 'tag_title' : 'frequency DESC'); + ->setFallback(Tag::class, 'getAll', 0, 0, $parameters['sorting'] === 'name' ? 'title' : 'frequency DESC'); } else { $tagList = $this->cache('tag_list_addon_b' . $data->id . '_u' . User::$info['id']) ->setLifeTime($data->cacheTime) diff --git a/src/Sources/LightPortal/Areas/CategoryArea.php b/src/Sources/LightPortal/Areas/CategoryArea.php index d89bc72e..49caf07a 100644 --- a/src/Sources/LightPortal/Areas/CategoryArea.php +++ b/src/Sources/LightPortal/Areas/CategoryArea.php @@ -108,8 +108,8 @@ public function main(): void 'class' => 'word_break', ], 'sort' => [ - 'default' => 't.title DESC', - 'reverse' => 't.title', + 'default' => 'title DESC', + 'reverse' => 'title', ], ], 'priority' => [ diff --git a/src/Sources/LightPortal/Articles/PageArticle.php b/src/Sources/LightPortal/Articles/PageArticle.php index f909292c..2c40f8d3 100644 --- a/src/Sources/LightPortal/Articles/PageArticle.php +++ b/src/Sources/LightPortal/Articles/PageArticle.php @@ -263,7 +263,7 @@ private function prepareTags(array &$pages): void return; $result = Db::$db->query('', ' - SELECT t.tag_id, t.icon, pt.page_id, COALESCE(tt.title, tf.title) AS tag_title + SELECT t.tag_id, t.icon, pt.page_id, COALESCE(tt.title, tf.title) AS title FROM {db_prefix}lp_tags AS t LEFT JOIN {db_prefix}lp_page_tags AS pt ON (t.tag_id = pt.tag_id) LEFT JOIN {db_prefix}lp_titles AS tt ON ( @@ -274,7 +274,7 @@ private function prepareTags(array &$pages): void ) WHERE pt.page_id IN ({array_int:pages}) AND t.status = {int:status} - ORDER BY tag_title', + ORDER BY title', [ 'lang' => User::$info['language'], 'fallback_lang' => Config::$language, @@ -286,7 +286,7 @@ private function prepareTags(array &$pages): void while ($row = Db::$db->fetch_assoc($result)) { $pages[$row['page_id']]['tags'][] = [ 'icon' => $this->getIcon($row['icon']), - 'title' => $row['tag_title'], + 'title' => $row['title'], 'href' => LP_BASE_URL . ';sa=tags;id=' . $row['tag_id'], ]; } diff --git a/src/Sources/LightPortal/Lists/CategoryList.php b/src/Sources/LightPortal/Lists/CategoryList.php index 0885212a..b5624f59 100644 --- a/src/Sources/LightPortal/Lists/CategoryList.php +++ b/src/Sources/LightPortal/Lists/CategoryList.php @@ -30,7 +30,7 @@ public function __invoke(): array public function getAll(): array { $result = Db::$db->query('', /** @lang text */ ' - SELECT c.category_id, c.icon, c.description, c.priority, COALESCE(t.title, tf.title) AS cat_title + SELECT c.category_id, c.icon, c.description, c.priority, COALESCE(t.title, tf.title) AS title FROM {db_prefix}lp_categories AS c LEFT JOIN {db_prefix}lp_titles AS t ON ( c.category_id = t.item_id AND t.type = {literal:category} AND t.lang = {string:lang} @@ -58,7 +58,7 @@ public function getAll(): array $items[$row['category_id']] = [ 'id' => (int) $row['category_id'], 'icon' => $row['icon'], - 'title' => $row['cat_title'], + 'title' => $row['title'], 'description' => $row['description'], 'priority' => (int) $row['priority'], ]; diff --git a/src/Sources/LightPortal/Lists/TagList.php b/src/Sources/LightPortal/Lists/TagList.php index 003be2bf..6bfe5b8b 100644 --- a/src/Sources/LightPortal/Lists/TagList.php +++ b/src/Sources/LightPortal/Lists/TagList.php @@ -30,7 +30,7 @@ public function __invoke(): array public function getAll(): array { $result = Db::$db->query('', /** @lang text */ ' - SELECT tag.tag_id, tag.icon, COALESCE(t.title, tf.title) AS tag_title + SELECT tag.tag_id, tag.icon, COALESCE(t.title, tf.title) AS title FROM {db_prefix}lp_tags AS tag LEFT JOIN {db_prefix}lp_titles AS t ON ( tag.tag_id = t.item_id AND t.type = {literal:tag} AND t.lang = {string:lang} @@ -39,7 +39,7 @@ public function getAll(): array tag.tag_id = tf.item_id AND tf.type = {literal:tag} AND tf.lang = {string:fallback_lang} ) WHERE tag.status = {int:status} - ORDER BY t.title', + ORDER BY title', [ 'lang' => User::$info['language'], 'fallback_lang' => Config::$language, @@ -52,7 +52,7 @@ public function getAll(): array $items[$row['tag_id']] = [ 'id' => (int) $row['tag_id'], 'icon' => $row['icon'], - 'title' => $row['tag_title'], + 'title' => $row['title'], ]; } diff --git a/src/Sources/LightPortal/Repositories/AbstractRepository.php b/src/Sources/LightPortal/Repositories/AbstractRepository.php index d3468498..6a74005f 100644 --- a/src/Sources/LightPortal/Repositories/AbstractRepository.php +++ b/src/Sources/LightPortal/Repositories/AbstractRepository.php @@ -80,11 +80,16 @@ protected function saveTitles(int $item, string $method = ''): void $titles = []; foreach (Utils::$context['lp_' . $this->entity]['titles'] as $lang => $title) { + $title = Utils::$smcFunc['htmltrim']($title); + + if ($method === '' && $title === '') + continue; + $titles[] = [ 'item_id' => $item, 'type' => $this->entity, 'lang' => $lang, - 'title' => Utils::$smcFunc['htmltrim']($title), + 'title' => $title, ]; } diff --git a/src/Sources/LightPortal/Repositories/CategoryRepository.php b/src/Sources/LightPortal/Repositories/CategoryRepository.php index a71c8f04..e995a21e 100644 --- a/src/Sources/LightPortal/Repositories/CategoryRepository.php +++ b/src/Sources/LightPortal/Repositories/CategoryRepository.php @@ -27,7 +27,7 @@ final class CategoryRepository extends AbstractRepository public function getAll(int $start, int $limit, string $sort): array { $result = Db::$db->query('', /** @lang text */ ' - SELECT c.category_id, c.icon, c.description, c.priority, c.status, COALESCE(t.title, tf.title) AS cat_title + SELECT c.category_id, c.icon, c.description, c.priority, c.status, COALESCE(t.title, tf.title) AS title FROM {db_prefix}lp_categories AS c LEFT JOIN {db_prefix}lp_titles AS t ON ( c.category_id = t.item_id AND t.type = {literal:category} AND t.lang = {string:lang} @@ -54,7 +54,7 @@ public function getAll(int $start, int $limit, string $sort): array 'desc' => $row['description'], 'priority' => (int) $row['priority'], 'status' => (int) $row['status'], - 'title' => $row['cat_title'], + 'title' => $row['title'], ]; } diff --git a/src/Sources/LightPortal/Repositories/PageRepository.php b/src/Sources/LightPortal/Repositories/PageRepository.php index 83a37c3a..e0a62098 100644 --- a/src/Sources/LightPortal/Repositories/PageRepository.php +++ b/src/Sources/LightPortal/Repositories/PageRepository.php @@ -394,9 +394,12 @@ public function getRelatedPages(array $page): array } $result = Db::$db->query('', ' - SELECT p.page_id, p.alias, p.content, p.type, (' . $searchFormula . ') AS related, t.title + SELECT + p.page_id, p.alias, p.content, p.type, (' . $searchFormula . ') AS related, + COALESCE(t.title, tf.title) AS 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}) + LEFT JOIN {db_prefix}lp_titles AS tf ON (p.page_id = tf.item_id AND tf.lang = {string:fallback_lang}) WHERE (' . $searchFormula . ') > 0 AND p.status = {int:status} AND p.created_at <= {int:current_time} @@ -405,11 +408,12 @@ public function getRelatedPages(array $page): array ORDER BY related DESC LIMIT 4', [ - 'current_lang' => Utils::$context['user']['language'], - 'status' => $page['status'], - 'current_time' => time(), - 'permissions' => $this->getPermissions(), - 'current_page' => $page['id'], + 'current_lang' => Utils::$context['user']['language'], + 'fallback_lang' => Config::$language, + 'status' => $page['status'], + 'current_time' => time(), + 'permissions' => $this->getPermissions(), + 'current_page' => $page['id'], ] ); @@ -641,7 +645,7 @@ private function saveTags(int $item, string $method = ''): void private function getTags(int $item): array { $result = Db::$db->query('', ' - SELECT tag.tag_id, tag.icon, COALESCE(t.title, tf.title) AS tag_title + SELECT tag.tag_id, tag.icon, COALESCE(t.title, tf.title) AS title FROM {db_prefix}lp_tags AS tag INNER JOIN {db_prefix}lp_page_tags AS pt ON (tag.tag_id = pt.tag_id) LEFT JOIN {db_prefix}lp_titles AS t ON ( @@ -652,7 +656,7 @@ private function getTags(int $item): array ) WHERE tag.status = {int:status} AND pt.page_id = {int:page_id} - ORDER BY tag_title', + ORDER BY title', [ 'lang' => User::$info['language'], 'fallback_lang' => Config::$language, @@ -665,7 +669,7 @@ private function getTags(int $item): array while ($row = Db::$db->fetch_assoc($result)) { $items[$row['tag_id']] = [ 'icon' => $this->getIcon($row['icon'] ?: 'fas fa-tag'), - 'title' => $row['tag_title'], + 'title' => $row['title'], 'href' => LP_BASE_URL . ';sa=tags;id=' . $row['tag_id'], ]; } diff --git a/src/Sources/LightPortal/Repositories/TagRepository.php b/src/Sources/LightPortal/Repositories/TagRepository.php index 10776540..7a0a474c 100644 --- a/src/Sources/LightPortal/Repositories/TagRepository.php +++ b/src/Sources/LightPortal/Repositories/TagRepository.php @@ -27,7 +27,7 @@ final class TagRepository extends AbstractRepository public function getAll(int $start, int $limit, string $sort): array { $result = Db::$db->query('', /** @lang text */ ' - SELECT tag.tag_id, tag.icon, tag.status, COALESCE(t.title, tf.title) AS tag_title + SELECT tag.tag_id, tag.icon, tag.status, COALESCE(t.title, tf.title) AS title FROM {db_prefix}lp_tags AS tag LEFT JOIN {db_prefix}lp_titles AS t ON ( tag.tag_id = t.item_id AND t.type = {literal:tag} AND t.lang = {string:lang} @@ -52,7 +52,7 @@ public function getAll(int $start, int $limit, string $sort): array 'id' => (int) $row['tag_id'], 'icon' => $this->getIcon($row['icon']), 'status' => (int) $row['status'], - 'title' => $row['tag_title'], + 'title' => $row['title'], ]; } From 78514f8b50d8dcaef6e772337088d1111a678e49 Mon Sep 17 00:00:00 2001 From: Bugo Date: Mon, 4 Mar 2024 00:36:34 +0500 Subject: [PATCH 09/25] Store language in key on caching articles --- src/Sources/LightPortal/Actions/FrontPage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Sources/LightPortal/Actions/FrontPage.php b/src/Sources/LightPortal/Actions/FrontPage.php index 7143b96b..4b715fbc 100644 --- a/src/Sources/LightPortal/Actions/FrontPage.php +++ b/src/Sources/LightPortal/Actions/FrontPage.php @@ -81,7 +81,7 @@ public function prepare(ArticleInterface $article): void $article->init(); - $key = 'articles_u' . Utils::$context['user']['id'] . '_' . $start . '_' . $limit; + $key = 'articles_u' . User::$info['id'] . '_' . User::$info['language'] . '_' . $start . '_' . $limit; if (($data = $this->cache()->get($key)) === null) { $data['total'] = $article->getTotalCount(); From 17e7c261d4ede5056d398c78f2d15c3b8e2d3512 Mon Sep 17 00:00:00 2001 From: Bugo Date: Mon, 4 Mar 2024 00:37:18 +0500 Subject: [PATCH 10/25] Rename column in tag list --- .../default/languages/LightPortal/LightPortal.english.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Themes/default/languages/LightPortal/LightPortal.english.php b/src/Themes/default/languages/LightPortal/LightPortal.english.php index af581a7e..170b149c 100644 --- a/src/Themes/default/languages/LightPortal/LightPortal.english.php +++ b/src/Themes/default/languages/LightPortal/LightPortal.english.php @@ -262,7 +262,7 @@ $txt['lp_all_tags_by_key'] = 'All pages with the "%s" tag'; $txt['lp_tag_not_found'] = 'The specified tag was not found.'; $txt['lp_no_tags'] = 'There are no tags yet.'; -$txt['lp_tag_column'] = 'Keyword'; +$txt['lp_tag_column'] = 'Tag'; $txt['lp_frequency_column'] = 'Frequency'; // Sorting From dc5adeed5c03872138e3485408b72f287a203464 Mon Sep 17 00:00:00 2001 From: Bugo Date: Mon, 4 Mar 2024 17:44:53 +0500 Subject: [PATCH 11/25] Fix an issue with displaying categories/tags in SMF 3.0 --- src/Sources/LightPortal/Integration.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Sources/LightPortal/Integration.php b/src/Sources/LightPortal/Integration.php index 5734634e..a0834ff6 100644 --- a/src/Sources/LightPortal/Integration.php +++ b/src/Sources/LightPortal/Integration.php @@ -15,7 +15,7 @@ namespace Bugo\LightPortal; use Bugo\LightPortal\Compilers\Zero; -use Bugo\Compat\{Config, Db, Lang, User, Utils}; +use Bugo\Compat\{Config, Db, Lang, Theme, User, Utils}; use Bugo\LightPortal\Actions\{BoardIndex, Block, Category}; use Bugo\LightPortal\Actions\{FrontPage, Page, Tag}; @@ -127,6 +127,8 @@ public function actions(array &$actions): void $actions['forum'] = [false, [new BoardIndex(), 'show']]; + Theme::load(); + if ($this->request()->is(LP_ACTION) && Utils::$context['current_subaction'] === 'categories') (new Category())->show(new Page()); From 9aac973cddc531e03775b41830f028bf5aae7b34 Mon Sep 17 00:00:00 2001 From: Bugo Date: Mon, 4 Mar 2024 17:51:03 +0500 Subject: [PATCH 12/25] Replace Utils::$smcFunc['htmlspecialchars'] with Utils::htmlspecialchars --- src/Sources/LightPortal/Actions/Comment.php | 4 ++-- src/Sources/LightPortal/Addons/Search/Search.php | 6 +++--- src/Sources/LightPortal/Addons/SimpleChat/Chat.php | 4 ++-- src/Sources/LightPortal/Areas/Area.php | 2 +- src/Sources/LightPortal/Areas/BlockArea.php | 2 +- src/Sources/LightPortal/Areas/CategoryArea.php | 2 +- src/Sources/LightPortal/Areas/PageArea.php | 4 ++-- src/Sources/LightPortal/Repositories/AbstractRepository.php | 2 +- src/Sources/LightPortal/Repositories/PageRepository.php | 2 +- 9 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Sources/LightPortal/Actions/Comment.php b/src/Sources/LightPortal/Actions/Comment.php index 16550c09..dcbee2c1 100644 --- a/src/Sources/LightPortal/Actions/Comment.php +++ b/src/Sources/LightPortal/Actions/Comment.php @@ -113,7 +113,7 @@ private function add(): void exit(json_encode($result)); $parentId = $this->filterVar($data['parent_id'], 'int'); - $message = Utils::$smcFunc['htmlspecialchars']($data['message']); + $message = Utils::htmlspecialchars($data['message']); $author = $this->filterVar($data['author'], 'int'); $pageId = Utils::$context['lp_page']['id']; $pageUrl = Utils::$context['canonical_url']; @@ -179,7 +179,7 @@ private function update(): void exit(json_encode($result)); $item = $data['comment_id']; - $message = Utils::$smcFunc['htmlspecialchars']($data['message']); + $message = Utils::htmlspecialchars($data['message']); if (empty($item) || empty($message) || empty(trim($message))) exit(json_encode($result)); diff --git a/src/Sources/LightPortal/Addons/Search/Search.php b/src/Sources/LightPortal/Addons/Search/Search.php index cc2628e7..dfbc7ae2 100644 --- a/src/Sources/LightPortal/Addons/Search/Search.php +++ b/src/Sources/LightPortal/Addons/Search/Search.php @@ -10,7 +10,7 @@ * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later * * @category addon - * @version 19.02.24 + * @version 04.03.24 */ namespace Bugo\LightPortal\Addons\Search; @@ -81,7 +81,7 @@ private function prepareQuickResults(): void if (empty($data['phrase'])) return; - $query = Utils::$smcFunc['htmltrim'](Utils::$smcFunc['htmlspecialchars']($data['phrase'])); + $query = Utils::$smcFunc['htmltrim'](Utils::htmlspecialchars($data['phrase'])); exit(json_encode($this->query($query))); } @@ -94,7 +94,7 @@ private function getResults(): array if ($this->request()->isNotEmpty('search') === false) return []; - $query = Utils::$smcFunc['htmltrim'](Utils::$smcFunc['htmlspecialchars']($this->request('search'))); + $query = Utils::$smcFunc['htmltrim'](Utils::htmlspecialchars($this->request('search'))); if (empty($query)) return []; diff --git a/src/Sources/LightPortal/Addons/SimpleChat/Chat.php b/src/Sources/LightPortal/Addons/SimpleChat/Chat.php index 33abe6e4..b5b19561 100644 --- a/src/Sources/LightPortal/Addons/SimpleChat/Chat.php +++ b/src/Sources/LightPortal/Addons/SimpleChat/Chat.php @@ -10,7 +10,7 @@ * @license https://opensource.org/licenses/MIT MIT * * @category addon - * @version 19.02.24 + * @version 04.03.24 */ namespace Bugo\LightPortal\Addons\SimpleChat; @@ -77,7 +77,7 @@ public function addMessage(): void [ 'block_id' => $data['block_id'], 'user_id' => User::$info['id'], - 'message' => $message = Utils::$smcFunc['htmlspecialchars']($data['message']), + 'message' => $message = Utils::htmlspecialchars($data['message']), 'created_at' => $time = time(), ], ['id'], diff --git a/src/Sources/LightPortal/Areas/Area.php b/src/Sources/LightPortal/Areas/Area.php index d88639ec..5d8fe0f2 100644 --- a/src/Sources/LightPortal/Areas/Area.php +++ b/src/Sources/LightPortal/Areas/Area.php @@ -41,7 +41,7 @@ public function createBbcEditor(string $content = ''): void public function prepareContent(array $object): string { if ($object['type'] === 'html') { - $object['content'] = Utils::$smcFunc['htmlspecialchars']($object['content']); + $object['content'] = Utils::htmlspecialchars($object['content']); } return $object['content']; diff --git a/src/Sources/LightPortal/Areas/BlockArea.php b/src/Sources/LightPortal/Areas/BlockArea.php index 3828f492..74abf0dc 100644 --- a/src/Sources/LightPortal/Areas/BlockArea.php +++ b/src/Sources/LightPortal/Areas/BlockArea.php @@ -353,7 +353,7 @@ private function preparePreview(): void Security::checkSubmitOnce('free'); Utils::$context['preview_title'] = Utils::$context['lp_block']['titles'][Utils::$context['user']['language']] ?? ''; - Utils::$context['preview_content'] = Utils::$smcFunc['htmlspecialchars'](Utils::$context['lp_block']['content'], ENT_QUOTES); + Utils::$context['preview_content'] = Utils::htmlspecialchars(Utils::$context['lp_block']['content'], ENT_QUOTES); $this->cleanBbcode(Utils::$context['preview_title']); Lang::censorText(Utils::$context['preview_title']); diff --git a/src/Sources/LightPortal/Areas/CategoryArea.php b/src/Sources/LightPortal/Areas/CategoryArea.php index 49caf07a..7a59d40c 100644 --- a/src/Sources/LightPortal/Areas/CategoryArea.php +++ b/src/Sources/LightPortal/Areas/CategoryArea.php @@ -333,7 +333,7 @@ private function preparePreview(): void Security::checkSubmitOnce('free'); Utils::$context['preview_title'] = Utils::$context['lp_category']['titles'][Utils::$context['user']['language']]; - Utils::$context['preview_content'] = Utils::$smcFunc['htmlspecialchars'](Utils::$context['lp_category']['description'], ENT_QUOTES); + Utils::$context['preview_content'] = Utils::htmlspecialchars(Utils::$context['lp_category']['description'], ENT_QUOTES); $this->cleanBbcode(Utils::$context['preview_title']); Lang::censorText(Utils::$context['preview_title']); diff --git a/src/Sources/LightPortal/Areas/PageArea.php b/src/Sources/LightPortal/Areas/PageArea.php index 9a36f957..f8e47f00 100644 --- a/src/Sources/LightPortal/Areas/PageArea.php +++ b/src/Sources/LightPortal/Areas/PageArea.php @@ -444,7 +444,7 @@ private function calculateParams(): void { $searchParamString = trim($this->request('search', '')); $searchParams = [ - 'string' => Utils::$smcFunc['htmlspecialchars']($searchParamString), + 'string' => Utils::htmlspecialchars($searchParamString), ]; Utils::$context['search_params'] = empty($searchParamString) @@ -727,7 +727,7 @@ private function preparePreview(): void Security::checkSubmitOnce('free'); Utils::$context['preview_title'] = Utils::$context['lp_page']['titles'][Utils::$context['user']['language']]; - Utils::$context['preview_content'] = Utils::$smcFunc['htmlspecialchars']( + Utils::$context['preview_content'] = Utils::htmlspecialchars( Utils::$context['lp_page']['content'], ENT_QUOTES ); diff --git a/src/Sources/LightPortal/Repositories/AbstractRepository.php b/src/Sources/LightPortal/Repositories/AbstractRepository.php index 6a74005f..f4f6adb5 100644 --- a/src/Sources/LightPortal/Repositories/AbstractRepository.php +++ b/src/Sources/LightPortal/Repositories/AbstractRepository.php @@ -68,7 +68,7 @@ protected function prepareBbcContent(array &$entity): void if ($entity['type'] !== 'bbc') return; - $entity['content'] = Utils::$smcFunc['htmlspecialchars']($entity['content'], ENT_QUOTES); + $entity['content'] = Utils::htmlspecialchars($entity['content'], ENT_QUOTES); Msg::preparseCode($entity['content']); } diff --git a/src/Sources/LightPortal/Repositories/PageRepository.php b/src/Sources/LightPortal/Repositories/PageRepository.php index e0a62098..e3bddcf0 100644 --- a/src/Sources/LightPortal/Repositories/PageRepository.php +++ b/src/Sources/LightPortal/Repositories/PageRepository.php @@ -153,7 +153,7 @@ public function getData(int|string $item): array $image = Config::$modSettings['lp_page_og_image'] == 1 ? array_shift($allImages) : array_pop($allImages); - $ogImage = Utils::$smcFunc['htmlspecialchars']($image); + $ogImage = Utils::htmlspecialchars($image); } } From baf9daa6a85bd0334b8549b2fd915a9a9beeaf6a Mon Sep 17 00:00:00 2001 From: Bugo Date: Tue, 5 Mar 2024 00:26:03 +0500 Subject: [PATCH 13/25] Fix an issue with non-focused title field when it is not filled --- src/Sources/LightPortal/Areas/Area.php | 1 + src/Themes/default/scripts/light_portal/admin.js | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/src/Sources/LightPortal/Areas/Area.php b/src/Sources/LightPortal/Areas/Area.php index 5d8fe0f2..968d96c1 100644 --- a/src/Sources/LightPortal/Areas/Area.php +++ b/src/Sources/LightPortal/Areas/Area.php @@ -73,6 +73,7 @@ public function prepareTitleFields(string $entity = 'page', bool $required = tru Date: Tue, 5 Mar 2024 00:26:30 +0500 Subject: [PATCH 14/25] Update rules for page images --- src/Themes/default/css/light_portal/sass/page.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Themes/default/css/light_portal/sass/page.scss b/src/Themes/default/css/light_portal/sass/page.scss index b3624e15..9a7ec143 100644 --- a/src/Themes/default/css/light_portal/sass/page.scss +++ b/src/Themes/default/css/light_portal/sass/page.scss @@ -30,8 +30,8 @@ section { } img { - display: grid; - place-items: center; + display: block; + margin: 2em auto; border: 1px solid #ddd; border-radius: 4px; box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); From 0bb78e010f86011e8e8e018b2dfddcb8625207fb Mon Sep 17 00:00:00 2001 From: Bugo Date: Tue, 5 Mar 2024 00:27:33 +0500 Subject: [PATCH 15/25] Fix an issue when cache did not work --- src/Sources/LightPortal/Helper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Sources/LightPortal/Helper.php b/src/Sources/LightPortal/Helper.php index c3412535..40c14258 100644 --- a/src/Sources/LightPortal/Helper.php +++ b/src/Sources/LightPortal/Helper.php @@ -39,7 +39,7 @@ public function post(?string $key = null, mixed $default = null): mixed public function cache(?string $key = null): Cache { - return new Cache($key); + return (new Cache($key))->setLifeTime(LP_CACHE_TIME); } public function files(?string $key = null): mixed From 6d045a54b084de606806352cd37d0eaa3e2f241a Mon Sep 17 00:00:00 2001 From: Bugo Date: Tue, 5 Mar 2024 12:49:53 +0500 Subject: [PATCH 16/25] Add a simple poll --- src/Themes/default/LightPortal/ViewDebug.template.php | 10 ++++++++++ .../languages/LightPortal/LightPortal.english.php | 1 + 2 files changed, 11 insertions(+) diff --git a/src/Themes/default/LightPortal/ViewDebug.template.php b/src/Themes/default/LightPortal/ViewDebug.template.php index 72c3b71c..daed6f9a 100644 --- a/src/Themes/default/LightPortal/ViewDebug.template.php +++ b/src/Themes/default/LightPortal/ViewDebug.template.php @@ -12,6 +12,16 @@ function template_docs_above(): void ', Lang::$txt['admin_search_type_online'], '
'; + + echo ' + +
+
+ ', Lang::$txt['lp_feedback_question'], ' + + +
+
'; } function template_docs_below() diff --git a/src/Themes/default/languages/LightPortal/LightPortal.english.php b/src/Themes/default/languages/LightPortal/LightPortal.english.php index 170b149c..9522b9d2 100644 --- a/src/Themes/default/languages/LightPortal/LightPortal.english.php +++ b/src/Themes/default/languages/LightPortal/LightPortal.english.php @@ -24,6 +24,7 @@ $txt['lp_no_such_members'] = 'Nobody here by that name'; $txt['lp_promote_to_fp'] = 'Promote to frontpage'; $txt['lp_remove_from_fp'] = 'Remove from frontpage'; +$txt['lp_feedback_question'] = 'Do you like appearance of this page?'; // Settings $txt['lp_settings'] = 'Portal settings'; From f8167f70cadd3184c42fffe60f6990f91e75c9eb Mon Sep 17 00:00:00 2001 From: Bugo Date: Tue, 5 Mar 2024 12:50:43 +0500 Subject: [PATCH 17/25] Add a new plugin - Events --- .../LightPortal/Addons/Events/Events.php | 130 +++++++++++++++ .../LightPortal/Addons/Events/index.php | 6 + .../Addons/Events/langs/english.php | 8 + .../LightPortal/Addons/Events/langs/index.php | 6 + .../LightPortal/Addons/Events/style.css | 25 +++ .../LightPortal/Addons/Events/template.php | 149 ++++++++++++++++++ 6 files changed, 324 insertions(+) create mode 100644 src/Sources/LightPortal/Addons/Events/Events.php create mode 100644 src/Sources/LightPortal/Addons/Events/index.php create mode 100644 src/Sources/LightPortal/Addons/Events/langs/english.php create mode 100644 src/Sources/LightPortal/Addons/Events/langs/index.php create mode 100644 src/Sources/LightPortal/Addons/Events/style.css create mode 100644 src/Sources/LightPortal/Addons/Events/template.php diff --git a/src/Sources/LightPortal/Addons/Events/Events.php b/src/Sources/LightPortal/Addons/Events/Events.php new file mode 100644 index 00000000..709caf71 --- /dev/null +++ b/src/Sources/LightPortal/Addons/Events/Events.php @@ -0,0 +1,130 @@ + + * @copyright 2024 Bugo + * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later + * + * @category addon + * @version 03.03.24 + */ + +namespace Bugo\LightPortal\Addons\Events; + +use Bugo\Compat\{Calendar, Lang, User, Utils}; +use Bugo\LightPortal\Addons\Block; +use Bugo\LightPortal\Areas\Fields\CheckboxField; +use Bugo\LightPortal\Areas\Fields\NumberField; +use Bugo\LightPortal\Areas\Fields\RangeField; + +if (! defined('LP_NAME')) + die('No direct access...'); + +/** + * Generated by PluginMaker + */ +class Events extends Block +{ + public string $icon = 'fas fa-calendar-check'; + + public function prepareBlockParams(array &$params): void + { + if (Utils::$context['current_block']['type'] !== 'events') + return; + + $params = [ + 'show_birthdays' => false, + 'show_holidays' => false, + 'show_events' => true, + 'days_in_future' => 7, + 'update_interval' => 600, + ]; + } + + public function validateBlockParams(array &$params): void + { + if (Utils::$context['current_block']['type'] !== 'events') + return; + + $params = [ + 'show_birthdays' => FILTER_VALIDATE_BOOLEAN, + 'show_holidays' => FILTER_VALIDATE_BOOLEAN, + 'show_events' => FILTER_VALIDATE_BOOLEAN, + 'days_in_future' => FILTER_VALIDATE_INT, + 'update_interval' => FILTER_VALIDATE_INT, + ]; + } + + public function prepareBlockFields(): void + { + if (Utils::$context['current_block']['type'] !== 'events') + return; + + Lang::load('ManageCalendar'); + + CheckboxField::make('show_birthdays', Lang::$txt['setting_cal_showbdays']) + ->setTab('content') + ->setValue(Utils::$context['lp_block']['options']['show_birthdays']); + + CheckboxField::make('show_holidays', Lang::$txt['setting_cal_showholidays']) + ->setTab('content') + ->setValue(Utils::$context['lp_block']['options']['show_holidays']); + + CheckboxField::make('show_events', Lang::$txt['setting_cal_showevents']) + ->setTab('content') + ->setValue(Utils::$context['lp_block']['options']['show_events']); + + RangeField::make('days_in_future', Lang::$txt['lp_events']['days_in_future']) + ->setAttribute('max', 60) + ->setValue(Utils::$context['lp_block']['options']['days_in_future']); + + NumberField::make('update_interval', Lang::$txt['lp_events']['update_interval']) + ->setAttribute('min', 0) + ->setValue(Utils::$context['lp_block']['options']['update_interval']); + } + + public function changeIconSet(array &$set): void + { + $set['cake'] = 'fas fa-cake-candles'; + $set['event'] = 'fas fa-calendar-days'; + } + + public function getData(array $parameters): array + { + $now = time(); + $todayDate = date('Y-m-d', $now); + + $futureDate = empty($parameters['days_in_future']) + ? $todayDate + : date('Y-m-d', ($now + $parameters['days_in_future'] * 24 * 60 * 60)); + + $options = [ + 'show_birthdays' => (bool) $parameters['show_birthdays'], + 'show_holidays' => (bool) $parameters['show_holidays'], + 'show_events' => (bool) $parameters['show_events'], + ]; + + return Calendar::getCalendarList($todayDate, $futureDate, $options); + } + + public function prepareContent(object $data, array $parameters): void + { + if ($data->type !== 'events') + return; + + if ($this->request()->has('preview')) + $parameters['update_interval'] = 0; + + $data = $this->cache('events_addon_b' . $data->id . '_u' . User::$info['id']) + ->setLifeTime($parameters['update_interval'] ?? $data->cacheTime) + ->setFallback(self::class, 'getData', $parameters); + + $this->setTemplate(); + + template_show_events($data); + } +} diff --git a/src/Sources/LightPortal/Addons/Events/index.php b/src/Sources/LightPortal/Addons/Events/index.php new file mode 100644 index 00000000..66249736 --- /dev/null +++ b/src/Sources/LightPortal/Addons/Events/index.php @@ -0,0 +1,6 @@ + 'Events', + 'description' => 'Displays calendar summary such as birthdays, holidays and events.', + 'days_in_future' => 'Number of days in future to show events', + 'update_interval' => 'Data refresh interval, in seconds', +]; diff --git a/src/Sources/LightPortal/Addons/Events/langs/index.php b/src/Sources/LightPortal/Addons/Events/langs/index.php new file mode 100644 index 00000000..66249736 --- /dev/null +++ b/src/Sources/LightPortal/Addons/Events/langs/index.php @@ -0,0 +1,6 @@ + div:last-child { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); + grid-gap: 0 10px; + + @media screen and (max-width: 768px) { + & { + display: block; + } + } + } + + .fa-calendar { + color: forestgreen; + } + + .fa-cake-candles { + color: salmon; + } + + .fa-calendar-days { + color: rgb(59, 91, 152); + } +} diff --git a/src/Sources/LightPortal/Addons/Events/template.php b/src/Sources/LightPortal/Addons/Events/template.php new file mode 100644 index 00000000..944567b2 --- /dev/null +++ b/src/Sources/LightPortal/Addons/Events/template.php @@ -0,0 +1,149 @@ +'; + + if (! empty($data['events']) || ! empty($data['holidays'])) { + echo ' + ', Lang::$txt['birthdays'], ''; + } + + echo ' +
    '; + + foreach ($data['birthdays'] as $members) { + $list = []; + $localDate = ''; + + foreach ($members as $member) { + if (is_array($member)) { + $list[] = $member; + } else { + $localDate = $member; + unset($members['date_local']); + } + } + + foreach ($list as $member) { + $link = Config::$scripturl . '?action=profile;u=' . $member['id']; + $age = isset($member['age']) ? ' (' . $member['age'] . ')' : ''; + + echo ' +
  • + ', Icon::get('cake'), ' + ', $localDate, '', $member['name'], $age, ' +
  • '; + } + } + + echo ' +
+ '; +} + +function show_holidays(array $data): void +{ + if (empty($data['holidays'])) + return; + + echo ' +
'; + + if (! empty($data['events']) || ! empty($data['birthdays'])) { + echo ' + ', Lang::$txt['calendar_prompt'], ''; + } + + echo ' +
    '; + + foreach ($data['holidays'] as $holidays) { + $list = []; + $localDate = ''; + + foreach ($holidays as $key => $holiday) { + if (is_int($key)) { + $list[] = $holiday; + } else { + $localDate = $holiday; + unset($holidays['date_local']); + } + } + + foreach ($list as $holiday) { + echo ' +
  • + ', Icon::get('calendar'), ' + ', $localDate, ' – ', $holiday, ' +
  • '; + } + } + + echo ' +
+
'; +} + +function show_events(array $data): void +{ + if (empty($data['events'])) + return; + + echo ' +
'; + + if (! empty($data['birthdays']) || ! empty($data['holidays'])) { + echo ' + ', Lang::$txt['events'], ''; + } + + echo ' +
    '; + + foreach ($data['events'] as $events) { + foreach ($events as $event) { + if (empty($event['allday'])) { + $date = trim($event['start_date_local']) . ', ' . trim($event['start_time_local']) . ' – '; + + if ($event['start_date_local'] !== $event['end_date_local']) + $date .= trim($event['end_date_local']) . ', '; + + $date .= trim($event['end_time_local']); + } else { + $date = trim($event['start_date_local']) . ($event['start_date'] !== $event['end_date'] ? ' – ' . trim($event['end_date_local']) : ''); + } + + echo ' +
  • + ', Icon::get('event'), ' + ', $date, ' – ', $event['link'], ' +
  • '; + } + } + + echo ' +
+
'; +} From b0a2355b812036be78b34798b31992bc93a22954 Mon Sep 17 00:00:00 2001 From: Bugo Date: Wed, 6 Mar 2024 00:49:44 +0500 Subject: [PATCH 18/25] Update deploy.yml --- .github/workflows/deploy.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index ef0de4d4..c2067381 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -25,7 +25,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Node uses: actions/setup-node@v4 @@ -33,7 +33,7 @@ jobs: node-version: 20 - name: Install pnpm - uses: pnpm/action-setup@v2 + uses: pnpm/action-setup@v3 with: version: 8 run_install: false @@ -44,7 +44,7 @@ jobs: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - name: Setup pnpm cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ env.STORE_PATH }} key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} @@ -57,7 +57,7 @@ jobs: pnpm install - name: Setup Pages - uses: actions/configure-pages@v3 + uses: actions/configure-pages@v4 - name: Build with VitePress run: | @@ -66,7 +66,7 @@ jobs: touch .vitepress/dist/.nojekyll - name: Upload artifact - uses: actions/upload-pages-artifact@v2 + uses: actions/upload-pages-artifact@v3 with: path: docs/.vitepress/dist @@ -81,4 +81,4 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v2 + uses: actions/deploy-pages@v4 From 0681bd3084a64d82fc83e52fe5b102aaf043701d Mon Sep 17 00:00:00 2001 From: Bugo Date: Wed, 6 Mar 2024 00:50:57 +0500 Subject: [PATCH 19/25] Refactor code --- src/Sources/LightPortal/Actions/Category.php | 6 ++---- src/Sources/LightPortal/Actions/Tag.php | 6 ++---- src/Sources/LightPortal/Lists/IconList.php | 2 +- .../LightPortal/Utils/SessionManager.php | 14 ++++++------- src/database.php | 21 +++++++++++-------- 5 files changed, 24 insertions(+), 25 deletions(-) diff --git a/src/Sources/LightPortal/Actions/Category.php b/src/Sources/LightPortal/Actions/Category.php index 0c5cca8a..265aaa86 100644 --- a/src/Sources/LightPortal/Actions/Category.php +++ b/src/Sources/LightPortal/Actions/Category.php @@ -26,8 +26,9 @@ final class Category extends AbstractPageList { public function show(PageInterface $page): void { - if ($this->request()->hasNot('id')) + if ($this->request()->hasNot('id')) { $this->showAll(); + } $category = [ 'id' => (int) $this->request('id', 0) @@ -70,9 +71,6 @@ public function show(PageInterface $page): void $listOptions['get_items'] = [ 'function' => [$this, 'getPages'] ]; - $listOptions['get_count'] = [ - 'function' => [$this, 'getTotalCount'] - ]; if (isset($category['description'])) { $listOptions['additional_rows'] = [ diff --git a/src/Sources/LightPortal/Actions/Tag.php b/src/Sources/LightPortal/Actions/Tag.php index 59ab77b5..9c277d29 100644 --- a/src/Sources/LightPortal/Actions/Tag.php +++ b/src/Sources/LightPortal/Actions/Tag.php @@ -26,8 +26,9 @@ final class Tag extends AbstractPageList { public function show(PageInterface $page): void { - if ($this->request()->hasNot('id')) + if ($this->request()->hasNot('id')) { $this->showAll(); + } $tag = [ 'id' => (int) $this->request('id', 0) @@ -64,9 +65,6 @@ public function show(PageInterface $page): void $listOptions['get_items'] = [ 'function' => [$this, 'getPages'] ]; - $listOptions['get_count'] = [ - 'function' => [$this, 'getTotalCount'] - ]; new ItemList($listOptions); diff --git a/src/Sources/LightPortal/Lists/IconList.php b/src/Sources/LightPortal/Lists/IconList.php index 51c41492..f89cd234 100644 --- a/src/Sources/LightPortal/Lists/IconList.php +++ b/src/Sources/LightPortal/Lists/IconList.php @@ -70,7 +70,7 @@ public function getAll(): array 'pager' => 'pager', 'panels' => 'table-columns', 'plus_circle' => 'circle-plus', - 'plus' => 'plus', + 'plus' => 'plus fa-beat', 'preview' => 'check-double', 'quote' => 'quote-right', 'redirect' => 'diamond-turn-right', diff --git a/src/Sources/LightPortal/Utils/SessionManager.php b/src/Sources/LightPortal/Utils/SessionManager.php index a5d21500..10b9a880 100644 --- a/src/Sources/LightPortal/Utils/SessionManager.php +++ b/src/Sources/LightPortal/Utils/SessionManager.php @@ -39,7 +39,7 @@ public function __invoke(string $key): int public function getActiveBlocksCount(): int { - if ($this->session('lp')->isEmpty('active_blocks')) { + if ($this->session('lp')->get('active_blocks') === null) { $result = Db::$db->query('', ' SELECT COUNT(block_id) FROM {db_prefix}lp_blocks @@ -62,7 +62,7 @@ public function getActiveBlocksCount(): int public function getActivePagesCount(): int { - if ($this->session('lp')->isEmpty('active_pages')) { + if ($this->session('lp')->get('active_pages') === null) { $result = Db::$db->query('', ' SELECT COUNT(page_id) FROM {db_prefix}lp_pages @@ -87,7 +87,7 @@ public function getActivePagesCount(): int public function getMyPagesCount(): int { - if ($this->session('lp')->isEmpty('my_pages')) { + if ($this->session('lp')->get('my_pages') === null) { $result = Db::$db->query('', ' SELECT COUNT(page_id) FROM {db_prefix}lp_pages @@ -110,7 +110,7 @@ public function getMyPagesCount(): int public function getUnapprovedPagesCount(): int { - if ($this->session('lp')->isEmpty('unapproved_pages')) { + if ($this->session('lp')->get('unapproved_pages') === null) { $result = Db::$db->query('', ' SELECT COUNT(page_id) FROM {db_prefix}lp_pages @@ -133,7 +133,7 @@ public function getUnapprovedPagesCount(): int public function getInternalPagesCount(): int { - if ($this->session('lp')->isEmpty('internal_pages')) { + if ($this->session('lp')->get('internal_pages') === null) { $result = Db::$db->query('', ' SELECT COUNT(page_id) FROM {db_prefix}lp_pages @@ -156,7 +156,7 @@ public function getInternalPagesCount(): int public function getActiveCategoriesCount(): int { - if ($this->session('lp')->isEmpty('active_categories')) { + if ($this->session('lp')->get('active_categories') === null) { $result = Db::$db->query('', ' SELECT COUNT(category_id) FROM {db_prefix}lp_categories @@ -179,7 +179,7 @@ public function getActiveCategoriesCount(): int public function getActiveTagsCount(): int { - if ($this->session('lp')->isEmpty('active_tags')) { + if ($this->session('lp')->get('active_tags') === null) { $result = Db::$db->query('', ' SELECT COUNT(tag_id) FROM {db_prefix}lp_tags diff --git a/src/database.php b/src/database.php index 0f48ac02..dcd9c611 100644 --- a/src/database.php +++ b/src/database.php @@ -33,7 +33,7 @@ [ 'name' => 'icon', 'type' => 'varchar', - 'size' => 60, + 'size' => 255, 'null' => true ], [ @@ -121,7 +121,7 @@ [ 'name' => 'icon', 'type' => 'varchar', - 'size' => 60, + 'size' => 255, 'null' => true ], [ @@ -355,8 +355,8 @@ 'values' => [ [ 1, $user_info['id'], 'home', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc porttitor posuere accumsan. Aliquam erat volutpat. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Phasellus vel blandit dui. Aliquam nunc est, vehicula sit amet eleifend in, scelerisque quis sem. In aliquam nec lorem nec volutpat. Sed eu blandit erat. Suspendisse elementum lectus a ligula commodo, at lobortis justo accumsan. Aliquam mollis lectus ultricies, semper urna eu, fermentum eros. Sed a interdum odio. Quisque sit amet feugiat enim. Curabitur aliquam lectus at metus tristique tempus. Sed vitae nisi ultricies, tincidunt lacus non, ultrices ante.


-

Duis ac ex sed dolor suscipit vulputate at eu ligula. Aliquam efficitur ac ante convallis ultricies. Nullam pretium vitae purus dapibus tempor. Aenean vel fringilla eros. Proin lectus velit, tristique ut condimentum eu, semper sed ipsum. Duis venenatis dolor lectus, et ullamcorper tortor varius eu. Vestibulum quis nisi ut nunc mollis fringilla. Sed consectetur semper magna, eget blandit nulla commodo sed. Aenean sem ipsum, auctor eget enim id, scelerisque malesuada nibh. Nulla ornare pharetra laoreet. Phasellus dignissim nisl nec arcu cursus luctus.


-

Aliquam in quam ut diam consectetur semper. Aliquam commodo mi purus, bibendum laoreet massa tristique eget. Suspendisse ut purus nisi. Mauris euismod dolor nec scelerisque ullamcorper. Praesent imperdiet semper neque, ac luctus nunc ultricies eget. Praesent sodales ante sed dignissim vulputate. Ut vel ligula id sem feugiat sollicitudin non at metus. Aliquam vel est non sapien sodales semper. Suspendisse potenti. Sed convallis quis turpis eu pulvinar. Vivamus nulla elit, condimentum vitae commodo eu, pellentesque ullamcorper enim. Maecenas faucibus dolor nec enim interdum, quis iaculis lacus suscipit. Pellentesque aliquam, lectus id volutpat euismod, ante tellus mollis dui, sed placerat erat arcu sit amet purus.

', 'html', 3, time() +

Duis ac ex sed dolor suscipit vulputate at eu ligula. Aliquam efficitur ac ante convallis ultricies. Nullam pretium vitae purus dapibus tempor. Aenean vel fringilla eros. Proin lectus velit, tristique ut condimentum eu, semper sed ipsum. Duis venenatis dolor lectus, et ullamcorper tortor varius eu. Vestibulum quis nisi ut nunc mollis fringilla. Sed consectetur semper magna, eget blandit nulla commodo sed. Aenean sem ipsum, auctor eget enim id, scelerisque malesuada nibh. Nulla ornare pharetra laoreet. Phasellus dignissim nisl nec arcu cursus luctus.


+

Aliquam in quam ut diam consectetur semper. Aliquam commodo mi purus, bibendum laoreet massa tristique eget. Suspendisse ut purus nisi. Mauris euismod dolor nec scelerisque ullamcorper. Praesent imperdiet semper neque, ac luctus nunc ultricies eget. Praesent sodales ante sed dignissim vulputate. Ut vel ligula id sem feugiat sollicitudin non at metus. Aliquam vel est non sapien sodales semper. Suspendisse potenti. Sed convallis quis turpis eu pulvinar. Vivamus nulla elit, condimentum vitae commodo eu, pellentesque ullamcorper enim. Maecenas faucibus dolor nec enim interdum, quis iaculis lacus suscipit. Pellentesque aliquam, lectus id volutpat euismod, ante tellus mollis dui, sed placerat erat arcu sit amet purus.

', 'html', 3, time() ] ], 'keys' => ['page_id'] @@ -467,7 +467,7 @@ [ 'name' => 'icon', 'type' => 'varchar', - 'size' => 60, + 'size' => 255, 'null' => true ], [ @@ -505,7 +505,7 @@ [ 'name' => 'lang', 'type' => 'varchar', - 'size' => 60, + 'size' => 20, 'null' => false ], [ @@ -525,11 +525,14 @@ 'columns' => [ 'item_id' => 'int', 'type' => 'string-10', - 'lang' => 'string-60', + 'lang' => 'string-20', 'title' => 'string-255' ], - 'values' => [ - [1, 'page', $language, $mbname] + 'values' => empty($modSettings['userLanguage']) ? [ + [1, 'page', $language, $mbname], + ] : [ + [1, 'page', $language, $mbname], + [1, 'page', $user_info['language'], $mbname], ], 'keys' => ['item_id', 'type', 'lang'] ] From acf1755363d371a2bde58d7cdb583f287ad6731b Mon Sep 17 00:00:00 2001 From: Bugo Date: Sat, 9 Mar 2024 11:28:59 +0500 Subject: [PATCH 20/25] Fix an issue with "empty" comments --- configs/vite.comments.js | 7 ------- src/Themes/default/LightPortal/ViewPage.template.php | 10 ---------- .../default/scripts/light_portal/app_comments.js | 4 ++-- 3 files changed, 2 insertions(+), 19 deletions(-) diff --git a/configs/vite.comments.js b/configs/vite.comments.js index 8dc27936..86514bd6 100644 --- a/configs/vite.comments.js +++ b/configs/vite.comments.js @@ -10,17 +10,10 @@ export default defineConfig({ outDir: dist, emptyOutDir: false, rollupOptions: { - external: ['vue', 'vue-i18n', 'pinia', 'vue-showdown'], input: 'src/Themes/default/scripts/light_portal/app_comments.js', output: { entryFileNames: 'bundle_comments.js', format: 'esm', - globals: { - vue: 'Vue', - 'vue-i18n': 'VueI18n', - pinia: 'Pinia', - 'vue-showdown': 'VueShowdown', - }, }, }, }, diff --git a/src/Themes/default/LightPortal/ViewPage.template.php b/src/Themes/default/LightPortal/ViewPage.template.php index 9d9a816f..3825d0b3 100644 --- a/src/Themes/default/LightPortal/ViewPage.template.php +++ b/src/Themes/default/LightPortal/ViewPage.template.php @@ -209,16 +209,6 @@ function show_comments(): void '; } else { echo ' - '; } } diff --git a/src/Themes/default/scripts/light_portal/app_comments.js b/src/Themes/default/scripts/light_portal/app_comments.js index aa798447..e3361684 100644 --- a/src/Themes/default/scripts/light_portal/app_comments.js +++ b/src/Themes/default/scripts/light_portal/app_comments.js @@ -1,6 +1,6 @@ import { createApp } from 'vue'; import { createPinia } from 'pinia'; -import { VueShowdown, showdown } from 'vue-showdown'; +import { VueShowdownPlugin, showdown } from 'vue-showdown'; import '@github/markdown-toolbar-element'; import CommentList from '../../LightPortal/components/CommentList.vue'; import i18n from './dev/i18n'; @@ -32,7 +32,7 @@ const bindings = Object.keys(classMap).map((key) => ({ showdown.extension('bindings', bindings); -app.use(VueShowdown, { +app.use(VueShowdownPlugin, { flavor: 'github', options: { emoji: true, From b6bcff9800d2135546c47a57c98ed8fad1ad3230 Mon Sep 17 00:00:00 2001 From: Bugo Date: Sat, 9 Mar 2024 11:29:17 +0500 Subject: [PATCH 21/25] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 44e413f0..e637c89c 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ [![](https://img.shields.io/badge/Demo-Forum-brightgreen.svg)](https://demo.dragomano.ru) [![](https://img.shields.io/badge/Docs-Site-orange.svg)](https://dragomano.github.io/Light-Portal/) -- **Tested on:** PHP 8.3.1 / MariaDB 10.11.6 +- **Tested on:** PHP 8.0.30, 8.1.27, 8.2.16, 8.3.3 / MariaDB 10.11.6 - **Languages:** Russian, English, Polish, Spanish, French, Turkish, Ukrainian, German, Italian, Portuguese, Greek, Czech, Danish, Dutch, Norwegian, Swedish, Arabic ## Description ([обзор на русском](https://dragomano.ru/mods/light-portal)) From 2022a56f456795e170b2ebc9372f185fa7fc2c3d Mon Sep 17 00:00:00 2001 From: Bugo Date: Sun, 10 Mar 2024 07:06:54 +0500 Subject: [PATCH 22/25] Fix an issue with undefined description during page editing --- src/Themes/default/LightPortal/ManagePages.template.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Themes/default/LightPortal/ManagePages.template.php b/src/Themes/default/LightPortal/ManagePages.template.php index 1fcee64b..d415a58c 100644 --- a/src/Themes/default/LightPortal/ManagePages.template.php +++ b/src/Themes/default/LightPortal/ManagePages.template.php @@ -55,7 +55,7 @@ function template_page_post(): void

', Utils::$context['page_area_title'], '

- ', Lang::$txt['lp_' . Utils::$context['lp_page']['type']]['description'], ' + ', Lang::$txt['lp_' . Utils::$context['lp_page']['type']]['description'] ?? Utils::$context['lp_page']['type'], '
'; } From 690d2aee2509848190d642ef3d58a11fed4b4356 Mon Sep 17 00:00:00 2001 From: Bugo Date: Sun, 10 Mar 2024 07:07:48 +0500 Subject: [PATCH 23/25] Use fa-php-helper to get FA icon list --- src/Sources/LightPortal/Lists/IconList.php | 2051 +------------------- src/Sources/LightPortal/composer.json | 1 + 2 files changed, 13 insertions(+), 2039 deletions(-) diff --git a/src/Sources/LightPortal/Lists/IconList.php b/src/Sources/LightPortal/Lists/IconList.php index f89cd234..6f6ec786 100644 --- a/src/Sources/LightPortal/Lists/IconList.php +++ b/src/Sources/LightPortal/Lists/IconList.php @@ -14,6 +14,9 @@ namespace Bugo\LightPortal\Lists; +use Bugo\FontAwesomeHelper\BrandIcon; +use Bugo\FontAwesomeHelper\RegularIcon; +use Bugo\FontAwesomeHelper\SolidIcon; use Bugo\LightPortal\Helper; if (! defined('SMF')) @@ -113,2044 +116,14 @@ public function getAll(): array public function getList(): array { - return [ - 'fas fa-0', - 'fas fa-1', - 'fas fa-2', - 'fas fa-3', - 'fas fa-4', - 'fas fa-5', - 'fas fa-6', - 'fas fa-7', - 'fas fa-8', - 'fas fa-9', - 'fab fa-42-group', - 'fab fa-500px', - 'fas fa-a', - 'fab fa-accessible-icon', - 'fab fa-accusoft', - 'fas fa-address-book', - 'far fa-address-book', - 'fas fa-address-card', - 'far fa-address-card', - 'fab fa-adn', - 'fab fa-adversal', - 'fab fa-affiliatetheme', - 'fab fa-airbnb', - 'fab fa-algolia', - 'fas fa-align-center', - 'fas fa-align-justify', - 'fas fa-align-left', - 'fas fa-align-right', - 'fab fa-alipay', - 'fab fa-amazon', - 'fab fa-amazon-pay', - 'fab fa-amilia', - 'fas fa-anchor', - 'fas fa-anchor-circle-check', - 'fas fa-anchor-circle-exclamation', - 'fas fa-anchor-circle-xmark', - 'fas fa-anchor-lock', - 'fab fa-android', - 'fab fa-angellist', - 'fas fa-angle-down', - 'fas fa-angle-left', - 'fas fa-angle-right', - 'fas fa-angle-up', - 'fas fa-angles-down', - 'fas fa-angles-left', - 'fas fa-angles-right', - 'fas fa-angles-up', - 'fab fa-angrycreative', - 'fab fa-angular', - 'fas fa-ankh', - 'fab fa-app-store', - 'fab fa-app-store-ios', - 'fab fa-apper', - 'fab fa-apple', - 'fab fa-apple-pay', - 'fas fa-apple-whole', - 'fas fa-archway', - 'fas fa-arrow-down', - 'fas fa-arrow-down-1-9', - 'fas fa-arrow-down-9-1', - 'fas fa-arrow-down-a-z', - 'fas fa-arrow-down-long', - 'fas fa-arrow-down-short-wide', - 'fas fa-arrow-down-up-across-line', - 'fas fa-arrow-down-up-lock', - 'fas fa-arrow-down-wide-short', - 'fas fa-arrow-down-z-a', - 'fas fa-arrow-left', - 'fas fa-arrow-left-long', - 'fas fa-arrow-pointer', - 'fas fa-arrow-right', - 'fas fa-arrow-right-arrow-left', - 'fas fa-arrow-right-from-bracket', - 'fas fa-arrow-right-long', - 'fas fa-arrow-right-to-bracket', - 'fas fa-arrow-right-to-city', - 'fas fa-arrow-rotate-left', - 'fas fa-arrow-rotate-right', - 'fas fa-arrow-trend-down', - 'fas fa-arrow-trend-up', - 'fas fa-arrow-turn-down', - 'fas fa-arrow-turn-up', - 'fas fa-arrow-up', - 'fas fa-arrow-up-1-9', - 'fas fa-arrow-up-9-1', - 'fas fa-arrow-up-a-z', - 'fas fa-arrow-up-from-bracket', - 'fas fa-arrow-up-from-ground-water', - 'fas fa-arrow-up-from-water-pump', - 'fas fa-arrow-up-long', - 'fas fa-arrow-up-right-dots', - 'fas fa-arrow-up-right-from-square', - 'fas fa-arrow-up-short-wide', - 'fas fa-arrow-up-wide-short', - 'fas fa-arrow-up-z-a', - 'fas fa-arrows-down-to-line', - 'fas fa-arrows-down-to-people', - 'fas fa-arrows-left-right', - 'fas fa-arrows-left-right-to-line', - 'fas fa-arrows-rotate', - 'fas fa-arrows-spin', - 'fas fa-arrows-split-up-and-left', - 'fas fa-arrows-to-circle', - 'fas fa-arrows-to-dot', - 'fas fa-arrows-to-eye', - 'fas fa-arrows-turn-right', - 'fas fa-arrows-turn-to-dots', - 'fas fa-arrows-up-down', - 'fas fa-arrows-up-down-left-right', - 'fas fa-arrows-up-to-line', - 'fab fa-artstation', - 'fas fa-asterisk', - 'fab fa-asymmetrik', - 'fas fa-at', - 'fab fa-atlassian', - 'fas fa-atom', - 'fab fa-audible', - 'fas fa-audio-description', - 'fas fa-austral-sign', - 'fab fa-autoprefixer', - 'fab fa-avianex', - 'fab fa-aviato', - 'fas fa-award', - 'fab fa-aws', - 'fas fa-b', - 'fas fa-baby', - 'fas fa-baby-carriage', - 'fas fa-backward', - 'fas fa-backward-fast', - 'fas fa-backward-step', - 'fas fa-bacon', - 'fas fa-bacteria', - 'fas fa-bacterium', - 'fas fa-bag-shopping', - 'fas fa-bahai', - 'fas fa-baht-sign', - 'fas fa-ban', - 'fas fa-ban-smoking', - 'fas fa-bandage', - 'fab fa-bandcamp', - 'fas fa-bangladeshi-taka-sign', - 'fas fa-barcode', - 'fas fa-bars', - 'fas fa-bars-progress', - 'fas fa-bars-staggered', - 'fas fa-baseball', - 'fas fa-baseball-bat-ball', - 'fas fa-basket-shopping', - 'fas fa-basketball', - 'fas fa-bath', - 'fas fa-battery-empty', - 'fas fa-battery-full', - 'fas fa-battery-half', - 'fas fa-battery-quarter', - 'fas fa-battery-three-quarters', - 'fab fa-battle-net', - 'fas fa-bed', - 'fas fa-bed-pulse', - 'fas fa-beer-mug-empty', - 'fab fa-behance', - 'fas fa-bell', - 'far fa-bell', - 'fas fa-bell-concierge', - 'fas fa-bell-slash', - 'far fa-bell-slash', - 'fas fa-bezier-curve', - 'fas fa-bicycle', - 'fab fa-bilibili', - 'fab fa-bimobject', - 'fas fa-binoculars', - 'fas fa-biohazard', - 'fab fa-bitbucket', - 'fab fa-bitcoin', - 'fas fa-bitcoin-sign', - 'fab fa-bity', - 'fab fa-black-tie', - 'fab fa-blackberry', - 'fas fa-blender', - 'fas fa-blender-phone', - 'fas fa-blog', - 'fab fa-blogger', - 'fab fa-blogger-b', - 'fab fa-bluetooth', - 'fab fa-bluetooth-b', - 'fas fa-bold', - 'fas fa-bolt', - 'fas fa-bolt-lightning', - 'fas fa-bomb', - 'fas fa-bone', - 'fas fa-bong', - 'fas fa-book', - 'fas fa-book-atlas', - 'fas fa-book-bible', - 'fas fa-book-bookmark', - 'fas fa-book-journal-whills', - 'fas fa-book-medical', - 'fas fa-book-open', - 'fas fa-book-open-reader', - 'fas fa-book-quran', - 'fas fa-book-skull', - 'fas fa-book-tanakh', - 'fas fa-bookmark', - 'far fa-bookmark', - 'fab fa-bootstrap', - 'fas fa-border-all', - 'fas fa-border-none', - 'fas fa-border-top-left', - 'fas fa-bore-hole', - 'fab fa-bots', - 'fas fa-bottle-droplet', - 'fas fa-bottle-water', - 'fas fa-bowl-food', - 'fas fa-bowl-rice', - 'fas fa-bowling-ball', - 'fas fa-box', - 'fas fa-box-archive', - 'fas fa-box-open', - 'fas fa-box-tissue', - 'fas fa-boxes-packing', - 'fas fa-boxes-stacked', - 'fas fa-braille', - 'fas fa-brain', - 'fab fa-brave', - 'fab fa-brave-reverse', - 'fas fa-brazilian-real-sign', - 'fas fa-bread-slice', - 'fas fa-bridge', - 'fas fa-bridge-circle-check', - 'fas fa-bridge-circle-exclamation', - 'fas fa-bridge-circle-xmark', - 'fas fa-bridge-lock', - 'fas fa-bridge-water', - 'fas fa-briefcase', - 'fas fa-briefcase-medical', - 'fas fa-broom', - 'fas fa-broom-ball', - 'fas fa-brush', - 'fab fa-btc', - 'fas fa-bucket', - 'fab fa-buffer', - 'fas fa-bug', - 'fas fa-bug-slash', - 'fas fa-bugs', - 'fas fa-building', - 'far fa-building', - 'fas fa-building-circle-arrow-right', - 'fas fa-building-circle-check', - 'fas fa-building-circle-exclamation', - 'fas fa-building-circle-xmark', - 'fas fa-building-columns', - 'fas fa-building-flag', - 'fas fa-building-lock', - 'fas fa-building-ngo', - 'fas fa-building-shield', - 'fas fa-building-un', - 'fas fa-building-user', - 'fas fa-building-wheat', - 'fas fa-bullhorn', - 'fas fa-bullseye', - 'fas fa-burger', - 'fab fa-buromobelexperte', - 'fas fa-burst', - 'fas fa-bus', - 'fas fa-bus-simple', - 'fas fa-business-time', - 'fab fa-buy-n-large', - 'fab fa-buysellads', - 'fas fa-c', - 'fas fa-cable-car', - 'fas fa-cake-candles', - 'fas fa-calculator', - 'fas fa-calendar', - 'far fa-calendar', - 'fas fa-calendar-check', - 'far fa-calendar-check', - 'fas fa-calendar-day', - 'fas fa-calendar-days', - 'far fa-calendar-days', - 'fas fa-calendar-minus', - 'far fa-calendar-minus', - 'fas fa-calendar-plus', - 'far fa-calendar-plus', - 'fas fa-calendar-week', - 'fas fa-calendar-xmark', - 'far fa-calendar-xmark', - 'fas fa-camera', - 'fas fa-camera-retro', - 'fas fa-camera-rotate', - 'fas fa-campground', - 'fab fa-canadian-maple-leaf', - 'fas fa-candy-cane', - 'fas fa-cannabis', - 'fas fa-capsules', - 'fas fa-car', - 'fas fa-car-battery', - 'fas fa-car-burst', - 'fas fa-car-on', - 'fas fa-car-rear', - 'fas fa-car-side', - 'fas fa-car-tunnel', - 'fas fa-caravan', - 'fas fa-caret-down', - 'fas fa-caret-left', - 'fas fa-caret-right', - 'fas fa-caret-up', - 'fas fa-carrot', - 'fas fa-cart-arrow-down', - 'fas fa-cart-flatbed', - 'fas fa-cart-flatbed-suitcase', - 'fas fa-cart-plus', - 'fas fa-cart-shopping', - 'fas fa-cash-register', - 'fas fa-cat', - 'fab fa-cc-amazon-pay', - 'fab fa-cc-amex', - 'fab fa-cc-apple-pay', - 'fab fa-cc-diners-club', - 'fab fa-cc-discover', - 'fab fa-cc-jcb', - 'fab fa-cc-mastercard', - 'fab fa-cc-paypal', - 'fab fa-cc-stripe', - 'fab fa-cc-visa', - 'fas fa-cedi-sign', - 'fas fa-cent-sign', - 'fab fa-centercode', - 'fab fa-centos', - 'fas fa-certificate', - 'fas fa-chair', - 'fas fa-chalkboard', - 'fas fa-chalkboard-user', - 'fas fa-champagne-glasses', - 'fas fa-charging-station', - 'fas fa-chart-area', - 'fas fa-chart-bar', - 'far fa-chart-bar', - 'fas fa-chart-column', - 'fas fa-chart-gantt', - 'fas fa-chart-line', - 'fas fa-chart-pie', - 'fas fa-chart-simple', - 'fas fa-check', - 'fas fa-check-double', - 'fas fa-check-to-slot', - 'fas fa-cheese', - 'fas fa-chess', - 'fas fa-chess-bishop', - 'far fa-chess-bishop', - 'fas fa-chess-board', - 'fas fa-chess-king', - 'far fa-chess-king', - 'fas fa-chess-knight', - 'far fa-chess-knight', - 'fas fa-chess-pawn', - 'far fa-chess-pawn', - 'fas fa-chess-queen', - 'far fa-chess-queen', - 'fas fa-chess-rook', - 'far fa-chess-rook', - 'fas fa-chevron-down', - 'fas fa-chevron-left', - 'fas fa-chevron-right', - 'fas fa-chevron-up', - 'fas fa-child', - 'fas fa-child-combatant', - 'fas fa-child-dress', - 'fas fa-child-reaching', - 'fas fa-children', - 'fab fa-chrome', - 'fab fa-chromecast', - 'fas fa-church', - 'fas fa-circle', - 'far fa-circle', - 'fas fa-circle-arrow-down', - 'fas fa-circle-arrow-left', - 'fas fa-circle-arrow-right', - 'fas fa-circle-arrow-up', - 'fas fa-circle-check', - 'far fa-circle-check', - 'fas fa-circle-chevron-down', - 'fas fa-circle-chevron-left', - 'fas fa-circle-chevron-right', - 'fas fa-circle-chevron-up', - 'fas fa-circle-dollar-to-slot', - 'fas fa-circle-dot', - 'far fa-circle-dot', - 'fas fa-circle-down', - 'far fa-circle-down', - 'fas fa-circle-exclamation', - 'fas fa-circle-h', - 'fas fa-circle-half-stroke', - 'fas fa-circle-info', - 'fas fa-circle-left', - 'far fa-circle-left', - 'fas fa-circle-minus', - 'fas fa-circle-nodes', - 'fas fa-circle-notch', - 'fas fa-circle-pause', - 'far fa-circle-pause', - 'fas fa-circle-play', - 'far fa-circle-play', - 'fas fa-circle-plus', - 'fas fa-circle-question', - 'far fa-circle-question', - 'fas fa-circle-radiation', - 'fas fa-circle-right', - 'far fa-circle-right', - 'fas fa-circle-stop', - 'far fa-circle-stop', - 'fas fa-circle-up', - 'far fa-circle-up', - 'fas fa-circle-user', - 'far fa-circle-user', - 'fas fa-circle-xmark', - 'far fa-circle-xmark', - 'fas fa-city', - 'fas fa-clapperboard', - 'fas fa-clipboard', - 'far fa-clipboard', - 'fas fa-clipboard-check', - 'fas fa-clipboard-list', - 'fas fa-clipboard-question', - 'fas fa-clipboard-user', - 'fas fa-clock', - 'far fa-clock', - 'fas fa-clock-rotate-left', - 'fas fa-clone', - 'far fa-clone', - 'fas fa-closed-captioning', - 'far fa-closed-captioning', - 'fas fa-cloud', - 'fas fa-cloud-arrow-down', - 'fas fa-cloud-arrow-up', - 'fas fa-cloud-bolt', - 'fas fa-cloud-meatball', - 'fas fa-cloud-moon', - 'fas fa-cloud-moon-rain', - 'fas fa-cloud-rain', - 'fas fa-cloud-showers-heavy', - 'fas fa-cloud-showers-water', - 'fas fa-cloud-sun', - 'fas fa-cloud-sun-rain', - 'fab fa-cloudflare', - 'fab fa-cloudscale', - 'fab fa-cloudsmith', - 'fab fa-cloudversify', - 'fas fa-clover', - 'fab fa-cmplid', - 'fas fa-code', - 'fas fa-code-branch', - 'fas fa-code-commit', - 'fas fa-code-compare', - 'fas fa-code-fork', - 'fas fa-code-merge', - 'fas fa-code-pull-request', - 'fab fa-codepen', - 'fab fa-codiepie', - 'fas fa-coins', - 'fas fa-colon-sign', - 'fas fa-comment', - 'far fa-comment', - 'fas fa-comment-dollar', - 'fas fa-comment-dots', - 'far fa-comment-dots', - 'fas fa-comment-medical', - 'fas fa-comment-slash', - 'fas fa-comment-sms', - 'fas fa-comments', - 'far fa-comments', - 'fas fa-comments-dollar', - 'fas fa-compact-disc', - 'fas fa-compass', - 'far fa-compass', - 'fas fa-compass-drafting', - 'fas fa-compress', - 'fas fa-computer', - 'fas fa-computer-mouse', - 'fab fa-confluence', - 'fab fa-connectdevelop', - 'fab fa-contao', - 'fas fa-cookie', - 'fas fa-cookie-bite', - 'fas fa-copy', - 'far fa-copy', - 'fas fa-copyright', - 'far fa-copyright', - 'fab fa-cotton-bureau', - 'fas fa-couch', - 'fas fa-cow', - 'fab fa-cpanel', - 'fab fa-creative-commons', - 'fab fa-creative-commons-by', - 'fab fa-creative-commons-nc', - 'fab fa-creative-commons-nc-eu', - 'fab fa-creative-commons-nc-jp', - 'fab fa-creative-commons-nd', - 'fab fa-creative-commons-pd', - 'fab fa-creative-commons-pd-alt', - 'fab fa-creative-commons-remix', - 'fab fa-creative-commons-sa', - 'fab fa-creative-commons-sampling', - 'fab fa-creative-commons-sampling-plus', - 'fab fa-creative-commons-share', - 'fab fa-creative-commons-zero', - 'fas fa-credit-card', - 'far fa-credit-card', - 'fab fa-critical-role', - 'fas fa-crop', - 'fas fa-crop-simple', - 'fas fa-cross', - 'fas fa-crosshairs', - 'fas fa-crow', - 'fas fa-crown', - 'fas fa-crutch', - 'fas fa-cruzeiro-sign', - 'fab fa-css3', - 'fab fa-css3-alt', - 'fas fa-cube', - 'fas fa-cubes', - 'fas fa-cubes-stacked', - 'fab fa-cuttlefish', - 'fas fa-d', - 'fab fa-d-and-d', - 'fab fa-d-and-d-beyond', - 'fab fa-dailymotion', - 'fab fa-dashcube', - 'fas fa-database', - 'fab fa-debian', - 'fab fa-deezer', - 'fas fa-delete-left', - 'fab fa-delicious', - 'fas fa-democrat', - 'fab fa-deploydog', - 'fab fa-deskpro', - 'fas fa-desktop', - 'fab fa-dev', - 'fab fa-deviantart', - 'fas fa-dharmachakra', - 'fab fa-dhl', - 'fas fa-diagram-next', - 'fas fa-diagram-predecessor', - 'fas fa-diagram-project', - 'fas fa-diagram-successor', - 'fas fa-diamond', - 'fas fa-diamond-turn-right', - 'fab fa-diaspora', - 'fas fa-dice', - 'fas fa-dice-d20', - 'fas fa-dice-d6', - 'fas fa-dice-five', - 'fas fa-dice-four', - 'fas fa-dice-one', - 'fas fa-dice-six', - 'fas fa-dice-three', - 'fas fa-dice-two', - 'fab fa-digg', - 'fab fa-digital-ocean', - 'fab fa-discord', - 'fab fa-discourse', - 'fas fa-disease', - 'fas fa-display', - 'fas fa-divide', - 'fas fa-dna', - 'fab fa-dochub', - 'fab fa-docker', - 'fas fa-dog', - 'fas fa-dollar-sign', - 'fas fa-dolly', - 'fas fa-dong-sign', - 'fas fa-door-closed', - 'fas fa-door-open', - 'fas fa-dove', - 'fas fa-down-left-and-up-right-to-center', - 'fas fa-down-long', - 'fas fa-download', - 'fab fa-draft2digital', - 'fas fa-dragon', - 'fas fa-draw-polygon', - 'fab fa-dribbble', - 'fab fa-dropbox', - 'fas fa-droplet', - 'fas fa-droplet-slash', - 'fas fa-drum', - 'fas fa-drum-steelpan', - 'fas fa-drumstick-bite', - 'fab fa-drupal', - 'fas fa-dumbbell', - 'fas fa-dumpster', - 'fas fa-dumpster-fire', - 'fas fa-dungeon', - 'fab fa-dyalog', - 'fas fa-e', - 'fas fa-ear-deaf', - 'fas fa-ear-listen', - 'fab fa-earlybirds', - 'fas fa-earth-africa', - 'fas fa-earth-americas', - 'fas fa-earth-asia', - 'fas fa-earth-europe', - 'fas fa-earth-oceania', - 'fab fa-ebay', - 'fab fa-edge', - 'fab fa-edge-legacy', - 'fas fa-egg', - 'fas fa-eject', - 'fab fa-elementor', - 'fas fa-elevator', - 'fas fa-ellipsis', - 'fas fa-ellipsis-vertical', - 'fab fa-ello', - 'fab fa-ember', - 'fab fa-empire', - 'fas fa-envelope', - 'far fa-envelope', - 'fas fa-envelope-circle-check', - 'fas fa-envelope-open', - 'far fa-envelope-open', - 'fas fa-envelope-open-text', - 'fas fa-envelopes-bulk', - 'fab fa-envira', - 'fas fa-equals', - 'fas fa-eraser', - 'fab fa-erlang', - 'fab fa-ethereum', - 'fas fa-ethernet', - 'fab fa-etsy', - 'fas fa-euro-sign', - 'fab fa-evernote', - 'fas fa-exclamation', - 'fas fa-expand', - 'fab fa-expeditedssl', - 'fas fa-explosion', - 'fas fa-eye', - 'far fa-eye', - 'fas fa-eye-dropper', - 'fas fa-eye-low-vision', - 'fas fa-eye-slash', - 'far fa-eye-slash', - 'fas fa-f', - 'fas fa-face-angry', - 'far fa-face-angry', - 'fas fa-face-dizzy', - 'far fa-face-dizzy', - 'fas fa-face-flushed', - 'far fa-face-flushed', - 'fas fa-face-frown', - 'far fa-face-frown', - 'fas fa-face-frown-open', - 'far fa-face-frown-open', - 'fas fa-face-grimace', - 'far fa-face-grimace', - 'fas fa-face-grin', - 'far fa-face-grin', - 'fas fa-face-grin-beam', - 'far fa-face-grin-beam', - 'fas fa-face-grin-beam-sweat', - 'far fa-face-grin-beam-sweat', - 'fas fa-face-grin-hearts', - 'far fa-face-grin-hearts', - 'fas fa-face-grin-squint', - 'far fa-face-grin-squint', - 'fas fa-face-grin-squint-tears', - 'far fa-face-grin-squint-tears', - 'fas fa-face-grin-stars', - 'far fa-face-grin-stars', - 'fas fa-face-grin-tears', - 'far fa-face-grin-tears', - 'fas fa-face-grin-tongue', - 'far fa-face-grin-tongue', - 'fas fa-face-grin-tongue-squint', - 'far fa-face-grin-tongue-squint', - 'fas fa-face-grin-tongue-wink', - 'far fa-face-grin-tongue-wink', - 'fas fa-face-grin-wide', - 'far fa-face-grin-wide', - 'fas fa-face-grin-wink', - 'far fa-face-grin-wink', - 'fas fa-face-kiss', - 'far fa-face-kiss', - 'fas fa-face-kiss-beam', - 'far fa-face-kiss-beam', - 'fas fa-face-kiss-wink-heart', - 'far fa-face-kiss-wink-heart', - 'fas fa-face-laugh', - 'far fa-face-laugh', - 'fas fa-face-laugh-beam', - 'far fa-face-laugh-beam', - 'fas fa-face-laugh-squint', - 'far fa-face-laugh-squint', - 'fas fa-face-laugh-wink', - 'far fa-face-laugh-wink', - 'fas fa-face-meh', - 'far fa-face-meh', - 'fas fa-face-meh-blank', - 'far fa-face-meh-blank', - 'fas fa-face-rolling-eyes', - 'far fa-face-rolling-eyes', - 'fas fa-face-sad-cry', - 'far fa-face-sad-cry', - 'fas fa-face-sad-tear', - 'far fa-face-sad-tear', - 'fas fa-face-smile', - 'far fa-face-smile', - 'fas fa-face-smile-beam', - 'far fa-face-smile-beam', - 'fas fa-face-smile-wink', - 'far fa-face-smile-wink', - 'fas fa-face-surprise', - 'far fa-face-surprise', - 'fas fa-face-tired', - 'far fa-face-tired', - 'fab fa-facebook', - 'fab fa-facebook-f', - 'fab fa-facebook-messenger', - 'fas fa-fan', - 'fab fa-fantasy-flight-games', - 'fas fa-faucet', - 'fas fa-faucet-drip', - 'fas fa-fax', - 'fas fa-feather', - 'fas fa-feather-pointed', - 'fab fa-fedex', - 'fab fa-fedora', - 'fas fa-ferry', - 'fab fa-figma', - 'fas fa-file', - 'far fa-file', - 'fas fa-file-arrow-down', - 'fas fa-file-arrow-up', - 'fas fa-file-audio', - 'far fa-file-audio', - 'fas fa-file-circle-check', - 'fas fa-file-circle-exclamation', - 'fas fa-file-circle-minus', - 'fas fa-file-circle-plus', - 'fas fa-file-circle-question', - 'fas fa-file-circle-xmark', - 'fas fa-file-code', - 'far fa-file-code', - 'fas fa-file-contract', - 'fas fa-file-csv', - 'fas fa-file-excel', - 'far fa-file-excel', - 'fas fa-file-export', - 'fas fa-file-image', - 'far fa-file-image', - 'fas fa-file-import', - 'fas fa-file-invoice', - 'fas fa-file-invoice-dollar', - 'fas fa-file-lines', - 'far fa-file-lines', - 'fas fa-file-medical', - 'fas fa-file-pdf', - 'far fa-file-pdf', - 'fas fa-file-pen', - 'fas fa-file-powerpoint', - 'far fa-file-powerpoint', - 'fas fa-file-prescription', - 'fas fa-file-shield', - 'fas fa-file-signature', - 'fas fa-file-video', - 'far fa-file-video', - 'fas fa-file-waveform', - 'fas fa-file-word', - 'far fa-file-word', - 'fas fa-file-zipper', - 'far fa-file-zipper', - 'fas fa-fill', - 'fas fa-fill-drip', - 'fas fa-film', - 'fas fa-filter', - 'fas fa-filter-circle-dollar', - 'fas fa-filter-circle-xmark', - 'fas fa-fingerprint', - 'fas fa-fire', - 'fas fa-fire-burner', - 'fas fa-fire-extinguisher', - 'fas fa-fire-flame-curved', - 'fas fa-fire-flame-simple', - 'fab fa-firefox', - 'fab fa-firefox-browser', - 'fab fa-first-order', - 'fab fa-first-order-alt', - 'fab fa-firstdraft', - 'fas fa-fish', - 'fas fa-fish-fins', - 'fas fa-flag', - 'far fa-flag', - 'fas fa-flag-checkered', - 'fas fa-flag-usa', - 'fas fa-flask', - 'fas fa-flask-vial', - 'fab fa-flickr', - 'fab fa-flipboard', - 'fas fa-floppy-disk', - 'far fa-floppy-disk', - 'fas fa-florin-sign', - 'fab fa-fly', - 'fas fa-folder', - 'far fa-folder', - 'fas fa-folder-closed', - 'far fa-folder-closed', - 'fas fa-folder-minus', - 'fas fa-folder-open', - 'far fa-folder-open', - 'fas fa-folder-plus', - 'fas fa-folder-tree', - 'fas fa-font', - 'fas fa-font-awesome', - 'far fa-font-awesome', - 'fab fa-font-awesome', - 'fab fa-fonticons', - 'fab fa-fonticons-fi', - 'fas fa-football', - 'fab fa-fort-awesome', - 'fab fa-fort-awesome-alt', - 'fab fa-forumbee', - 'fas fa-forward', - 'fas fa-forward-fast', - 'fas fa-forward-step', - 'fab fa-foursquare', - 'fas fa-franc-sign', - 'fab fa-free-code-camp', - 'fab fa-freebsd', - 'fas fa-frog', - 'fab fa-fulcrum', - 'fas fa-futbol', - 'far fa-futbol', - 'fas fa-g', - 'fab fa-galactic-republic', - 'fab fa-galactic-senate', - 'fas fa-gamepad', - 'fas fa-gas-pump', - 'fas fa-gauge', - 'fas fa-gauge-high', - 'fas fa-gauge-simple', - 'fas fa-gauge-simple-high', - 'fas fa-gavel', - 'fas fa-gear', - 'fas fa-gears', - 'fas fa-gem', - 'far fa-gem', - 'fas fa-genderless', - 'fab fa-get-pocket', - 'fab fa-gg', - 'fab fa-gg-circle', - 'fas fa-ghost', - 'fas fa-gift', - 'fas fa-gifts', - 'fab fa-git', - 'fab fa-git-alt', - 'fab fa-github', - 'fab fa-github-alt', - 'fab fa-gitkraken', - 'fab fa-gitlab', - 'fab fa-gitter', - 'fas fa-glass-water', - 'fas fa-glass-water-droplet', - 'fas fa-glasses', - 'fab fa-glide', - 'fab fa-glide-g', - 'fas fa-globe', - 'fab fa-gofore', - 'fab fa-golang', - 'fas fa-golf-ball-tee', - 'fab fa-goodreads', - 'fab fa-goodreads-g', - 'fab fa-google', - 'fab fa-google-drive', - 'fab fa-google-pay', - 'fab fa-google-play', - 'fab fa-google-plus', - 'fab fa-google-plus-g', - 'fab fa-google-scholar', - 'fab fa-google-wallet', - 'fas fa-gopuram', - 'fas fa-graduation-cap', - 'fab fa-gratipay', - 'fab fa-grav', - 'fas fa-greater-than', - 'fas fa-greater-than-equal', - 'fas fa-grip', - 'fas fa-grip-lines', - 'fas fa-grip-lines-vertical', - 'fas fa-grip-vertical', - 'fab fa-gripfire', - 'fas fa-group-arrows-rotate', - 'fab fa-grunt', - 'fas fa-guarani-sign', - 'fab fa-guilded', - 'fas fa-guitar', - 'fab fa-gulp', - 'fas fa-gun', - 'fas fa-h', - 'fab fa-hacker-news', - 'fab fa-hackerrank', - 'fas fa-hammer', - 'fas fa-hamsa', - 'fas fa-hand', - 'far fa-hand', - 'fas fa-hand-back-fist', - 'far fa-hand-back-fist', - 'fas fa-hand-dots', - 'fas fa-hand-fist', - 'fas fa-hand-holding', - 'fas fa-hand-holding-dollar', - 'fas fa-hand-holding-droplet', - 'fas fa-hand-holding-hand', - 'fas fa-hand-holding-heart', - 'fas fa-hand-holding-medical', - 'fas fa-hand-lizard', - 'far fa-hand-lizard', - 'fas fa-hand-middle-finger', - 'fas fa-hand-peace', - 'far fa-hand-peace', - 'fas fa-hand-point-down', - 'far fa-hand-point-down', - 'fas fa-hand-point-left', - 'far fa-hand-point-left', - 'fas fa-hand-point-right', - 'far fa-hand-point-right', - 'fas fa-hand-point-up', - 'far fa-hand-point-up', - 'fas fa-hand-pointer', - 'far fa-hand-pointer', - 'fas fa-hand-scissors', - 'far fa-hand-scissors', - 'fas fa-hand-sparkles', - 'fas fa-hand-spock', - 'far fa-hand-spock', - 'fas fa-handcuffs', - 'fas fa-hands', - 'fas fa-hands-asl-interpreting', - 'fas fa-hands-bound', - 'fas fa-hands-bubbles', - 'fas fa-hands-clapping', - 'fas fa-hands-holding', - 'fas fa-hands-holding-child', - 'fas fa-hands-holding-circle', - 'fas fa-hands-praying', - 'fas fa-handshake', - 'far fa-handshake', - 'fas fa-handshake-angle', - 'fas fa-handshake-simple', - 'fas fa-handshake-simple-slash', - 'fas fa-handshake-slash', - 'fas fa-hanukiah', - 'fas fa-hard-drive', - 'far fa-hard-drive', - 'fab fa-hashnode', - 'fas fa-hashtag', - 'fas fa-hat-cowboy', - 'fas fa-hat-cowboy-side', - 'fas fa-hat-wizard', - 'fas fa-head-side-cough', - 'fas fa-head-side-cough-slash', - 'fas fa-head-side-mask', - 'fas fa-head-side-virus', - 'fas fa-heading', - 'fas fa-headphones', - 'fas fa-headphones-simple', - 'fas fa-headset', - 'fas fa-heart', - 'far fa-heart', - 'fas fa-heart-circle-bolt', - 'fas fa-heart-circle-check', - 'fas fa-heart-circle-exclamation', - 'fas fa-heart-circle-minus', - 'fas fa-heart-circle-plus', - 'fas fa-heart-circle-xmark', - 'fas fa-heart-crack', - 'fas fa-heart-pulse', - 'fas fa-helicopter', - 'fas fa-helicopter-symbol', - 'fas fa-helmet-safety', - 'fas fa-helmet-un', - 'fas fa-highlighter', - 'fas fa-hill-avalanche', - 'fas fa-hill-rockslide', - 'fas fa-hippo', - 'fab fa-hips', - 'fab fa-hire-a-helper', - 'fab fa-hive', - 'fas fa-hockey-puck', - 'fas fa-holly-berry', - 'fab fa-hooli', - 'fab fa-hornbill', - 'fas fa-horse', - 'fas fa-horse-head', - 'fas fa-hospital', - 'far fa-hospital', - 'fas fa-hospital-user', - 'fas fa-hot-tub-person', - 'fas fa-hotdog', - 'fas fa-hotel', - 'fab fa-hotjar', - 'fas fa-hourglass', - 'far fa-hourglass', - 'fas fa-hourglass-end', - 'fas fa-hourglass-half', - 'far fa-hourglass-half', - 'fas fa-hourglass-start', - 'fas fa-house', - 'fas fa-house-chimney', - 'fas fa-house-chimney-crack', - 'fas fa-house-chimney-medical', - 'fas fa-house-chimney-user', - 'fas fa-house-chimney-window', - 'fas fa-house-circle-check', - 'fas fa-house-circle-exclamation', - 'fas fa-house-circle-xmark', - 'fas fa-house-crack', - 'fas fa-house-fire', - 'fas fa-house-flag', - 'fas fa-house-flood-water', - 'fas fa-house-flood-water-circle-arrow-right', - 'fas fa-house-laptop', - 'fas fa-house-lock', - 'fas fa-house-medical', - 'fas fa-house-medical-circle-check', - 'fas fa-house-medical-circle-exclamation', - 'fas fa-house-medical-circle-xmark', - 'fas fa-house-medical-flag', - 'fas fa-house-signal', - 'fas fa-house-tsunami', - 'fas fa-house-user', - 'fab fa-houzz', - 'fas fa-hryvnia-sign', - 'fab fa-html5', - 'fab fa-hubspot', - 'fas fa-hurricane', - 'fas fa-i', - 'fas fa-i-cursor', - 'fas fa-ice-cream', - 'fas fa-icicles', - 'fas fa-icons', - 'fas fa-id-badge', - 'far fa-id-badge', - 'fas fa-id-card', - 'far fa-id-card', - 'fas fa-id-card-clip', - 'fab fa-ideal', - 'fas fa-igloo', - 'fas fa-image', - 'far fa-image', - 'fas fa-image-portrait', - 'fas fa-images', - 'far fa-images', - 'fab fa-imdb', - 'fas fa-inbox', - 'fas fa-indent', - 'fas fa-indian-rupee-sign', - 'fas fa-industry', - 'fas fa-infinity', - 'fas fa-info', - 'fab fa-instagram', - 'fab fa-instalod', - 'fab fa-intercom', - 'fab fa-internet-explorer', - 'fab fa-invision', - 'fab fa-ioxhost', - 'fas fa-italic', - 'fab fa-itch-io', - 'fab fa-itunes', - 'fab fa-itunes-note', - 'fas fa-j', - 'fas fa-jar', - 'fas fa-jar-wheat', - 'fab fa-java', - 'fas fa-jedi', - 'fab fa-jedi-order', - 'fab fa-jenkins', - 'fas fa-jet-fighter', - 'fas fa-jet-fighter-up', - 'fab fa-jira', - 'fab fa-joget', - 'fas fa-joint', - 'fab fa-joomla', - 'fab fa-js', - 'fab fa-jsfiddle', - 'fas fa-jug-detergent', - 'fas fa-k', - 'fas fa-kaaba', - 'fab fa-kaggle', - 'fas fa-key', - 'fab fa-keybase', - 'fas fa-keyboard', - 'far fa-keyboard', - 'fab fa-keycdn', - 'fas fa-khanda', - 'fab fa-kickstarter', - 'fab fa-kickstarter-k', - 'fas fa-kip-sign', - 'fas fa-kit-medical', - 'fas fa-kitchen-set', - 'fas fa-kiwi-bird', - 'fab fa-korvue', - 'fas fa-l', - 'fas fa-land-mine-on', - 'fas fa-landmark', - 'fas fa-landmark-dome', - 'fas fa-landmark-flag', - 'fas fa-language', - 'fas fa-laptop', - 'fas fa-laptop-code', - 'fas fa-laptop-file', - 'fas fa-laptop-medical', - 'fab fa-laravel', - 'fas fa-lari-sign', - 'fab fa-lastfm', - 'fas fa-layer-group', - 'fas fa-leaf', - 'fab fa-leanpub', - 'fas fa-left-long', - 'fas fa-left-right', - 'fas fa-lemon', - 'far fa-lemon', - 'fab fa-less', - 'fas fa-less-than', - 'fas fa-less-than-equal', - 'fab fa-letterboxd', - 'fas fa-life-ring', - 'far fa-life-ring', - 'fas fa-lightbulb', - 'far fa-lightbulb', - 'fab fa-line', - 'fas fa-lines-leaning', - 'fas fa-link', - 'fas fa-link-slash', - 'fab fa-linkedin', - 'fab fa-linkedin-in', - 'fab fa-linode', - 'fab fa-linux', - 'fas fa-lira-sign', - 'fas fa-list', - 'fas fa-list-check', - 'fas fa-list-ol', - 'fas fa-list-ul', - 'fas fa-litecoin-sign', - 'fas fa-location-arrow', - 'fas fa-location-crosshairs', - 'fas fa-location-dot', - 'fas fa-location-pin', - 'fas fa-location-pin-lock', - 'fas fa-lock', - 'fas fa-lock-open', - 'fas fa-locust', - 'fas fa-lungs', - 'fas fa-lungs-virus', - 'fab fa-lyft', - 'fas fa-m', - 'fab fa-magento', - 'fas fa-magnet', - 'fas fa-magnifying-glass', - 'fas fa-magnifying-glass-arrow-right', - 'fas fa-magnifying-glass-chart', - 'fas fa-magnifying-glass-dollar', - 'fas fa-magnifying-glass-location', - 'fas fa-magnifying-glass-minus', - 'fas fa-magnifying-glass-plus', - 'fab fa-mailchimp', - 'fas fa-manat-sign', - 'fab fa-mandalorian', - 'fas fa-map', - 'far fa-map', - 'fas fa-map-location', - 'fas fa-map-location-dot', - 'fas fa-map-pin', - 'fab fa-markdown', - 'fas fa-marker', - 'fas fa-mars', - 'fas fa-mars-and-venus', - 'fas fa-mars-and-venus-burst', - 'fas fa-mars-double', - 'fas fa-mars-stroke', - 'fas fa-mars-stroke-right', - 'fas fa-mars-stroke-up', - 'fas fa-martini-glass', - 'fas fa-martini-glass-citrus', - 'fas fa-martini-glass-empty', - 'fas fa-mask', - 'fas fa-mask-face', - 'fas fa-mask-ventilator', - 'fas fa-masks-theater', - 'fab fa-mastodon', - 'fas fa-mattress-pillow', - 'fab fa-maxcdn', - 'fas fa-maximize', - 'fab fa-mdb', - 'fas fa-medal', - 'fab fa-medapps', - 'fab fa-medium', - 'fab fa-medrt', - 'fab fa-meetup', - 'fab fa-megaport', - 'fas fa-memory', - 'fab fa-mendeley', - 'fas fa-menorah', - 'fas fa-mercury', - 'fas fa-message', - 'far fa-message', - 'fab fa-meta', - 'fas fa-meteor', - 'fab fa-microblog', - 'fas fa-microchip', - 'fas fa-microphone', - 'fas fa-microphone-lines', - 'fas fa-microphone-lines-slash', - 'fas fa-microphone-slash', - 'fas fa-microscope', - 'fab fa-microsoft', - 'fas fa-mill-sign', - 'fas fa-minimize', - 'fab fa-mintbit', - 'fas fa-minus', - 'fas fa-mitten', - 'fab fa-mix', - 'fab fa-mixcloud', - 'fab fa-mixer', - 'fab fa-mizuni', - 'fas fa-mobile', - 'fas fa-mobile-button', - 'fas fa-mobile-retro', - 'fas fa-mobile-screen', - 'fas fa-mobile-screen-button', - 'fab fa-modx', - 'fab fa-monero', - 'fas fa-money-bill', - 'fas fa-money-bill-1', - 'far fa-money-bill-1', - 'fas fa-money-bill-1-wave', - 'fas fa-money-bill-transfer', - 'fas fa-money-bill-trend-up', - 'fas fa-money-bill-wave', - 'fas fa-money-bill-wheat', - 'fas fa-money-bills', - 'fas fa-money-check', - 'fas fa-money-check-dollar', - 'fas fa-monument', - 'fas fa-moon', - 'far fa-moon', - 'fas fa-mortar-pestle', - 'fas fa-mosque', - 'fas fa-mosquito', - 'fas fa-mosquito-net', - 'fas fa-motorcycle', - 'fas fa-mound', - 'fas fa-mountain', - 'fas fa-mountain-city', - 'fas fa-mountain-sun', - 'fas fa-mug-hot', - 'fas fa-mug-saucer', - 'fas fa-music', - 'fas fa-n', - 'fas fa-naira-sign', - 'fab fa-napster', - 'fab fa-neos', - 'fas fa-network-wired', - 'fas fa-neuter', - 'fas fa-newspaper', - 'far fa-newspaper', - 'fab fa-nfc-directional', - 'fab fa-nfc-symbol', - 'fab fa-nimblr', - 'fab fa-node', - 'fab fa-node-js', - 'fas fa-not-equal', - 'fas fa-notdef', - 'fas fa-note-sticky', - 'far fa-note-sticky', - 'fas fa-notes-medical', - 'fab fa-npm', - 'fab fa-ns8', - 'fab fa-nutritionix', - 'fas fa-o', - 'fas fa-object-group', - 'far fa-object-group', - 'fas fa-object-ungroup', - 'far fa-object-ungroup', - 'fab fa-octopus-deploy', - 'fab fa-odnoklassniki', - 'fab fa-odysee', - 'fas fa-oil-can', - 'fas fa-oil-well', - 'fab fa-old-republic', - 'fas fa-om', - 'fab fa-opencart', - 'fab fa-openid', - 'fab fa-opensuse', - 'fab fa-opera', - 'fab fa-optin-monster', - 'fab fa-orcid', - 'fab fa-osi', - 'fas fa-otter', - 'fas fa-outdent', - 'fas fa-p', - 'fab fa-padlet', - 'fab fa-page4', - 'fab fa-pagelines', - 'fas fa-pager', - 'fas fa-paint-roller', - 'fas fa-paintbrush', - 'fas fa-palette', - 'fab fa-palfed', - 'fas fa-pallet', - 'fas fa-panorama', - 'fas fa-paper-plane', - 'far fa-paper-plane', - 'fas fa-paperclip', - 'fas fa-parachute-box', - 'fas fa-paragraph', - 'fas fa-passport', - 'fas fa-paste', - 'far fa-paste', - 'fab fa-patreon', - 'fas fa-pause', - 'fas fa-paw', - 'fab fa-paypal', - 'fas fa-peace', - 'fas fa-pen', - 'fas fa-pen-clip', - 'fas fa-pen-fancy', - 'fas fa-pen-nib', - 'fas fa-pen-ruler', - 'fas fa-pen-to-square', - 'far fa-pen-to-square', - 'fas fa-pencil', - 'fas fa-people-arrows', - 'fas fa-people-carry-box', - 'fas fa-people-group', - 'fas fa-people-line', - 'fas fa-people-pulling', - 'fas fa-people-robbery', - 'fas fa-people-roof', - 'fas fa-pepper-hot', - 'fab fa-perbyte', - 'fas fa-percent', - 'fab fa-periscope', - 'fas fa-person', - 'fas fa-person-arrow-down-to-line', - 'fas fa-person-arrow-up-from-line', - 'fas fa-person-biking', - 'fas fa-person-booth', - 'fas fa-person-breastfeeding', - 'fas fa-person-burst', - 'fas fa-person-cane', - 'fas fa-person-chalkboard', - 'fas fa-person-circle-check', - 'fas fa-person-circle-exclamation', - 'fas fa-person-circle-minus', - 'fas fa-person-circle-plus', - 'fas fa-person-circle-question', - 'fas fa-person-circle-xmark', - 'fas fa-person-digging', - 'fas fa-person-dots-from-line', - 'fas fa-person-dress', - 'fas fa-person-dress-burst', - 'fas fa-person-drowning', - 'fas fa-person-falling', - 'fas fa-person-falling-burst', - 'fas fa-person-half-dress', - 'fas fa-person-harassing', - 'fas fa-person-hiking', - 'fas fa-person-military-pointing', - 'fas fa-person-military-rifle', - 'fas fa-person-military-to-person', - 'fas fa-person-praying', - 'fas fa-person-pregnant', - 'fas fa-person-rays', - 'fas fa-person-rifle', - 'fas fa-person-running', - 'fas fa-person-shelter', - 'fas fa-person-skating', - 'fas fa-person-skiing', - 'fas fa-person-skiing-nordic', - 'fas fa-person-snowboarding', - 'fas fa-person-swimming', - 'fas fa-person-through-window', - 'fas fa-person-walking', - 'fas fa-person-walking-arrow-loop-left', - 'fas fa-person-walking-arrow-right', - 'fas fa-person-walking-dashed-line-arrow-right', - 'fas fa-person-walking-luggage', - 'fas fa-person-walking-with-cane', - 'fas fa-peseta-sign', - 'fas fa-peso-sign', - 'fab fa-phabricator', - 'fab fa-phoenix-framework', - 'fab fa-phoenix-squadron', - 'fas fa-phone', - 'fas fa-phone-flip', - 'fas fa-phone-slash', - 'fas fa-phone-volume', - 'fas fa-photo-film', - 'fab fa-php', - 'fab fa-pied-piper', - 'fab fa-pied-piper-alt', - 'fab fa-pied-piper-hat', - 'fab fa-pied-piper-pp', - 'fas fa-piggy-bank', - 'fas fa-pills', - 'fab fa-pinterest', - 'fab fa-pinterest-p', - 'fab fa-pix', - 'fab fa-pixiv', - 'fas fa-pizza-slice', - 'fas fa-place-of-worship', - 'fas fa-plane', - 'fas fa-plane-arrival', - 'fas fa-plane-circle-check', - 'fas fa-plane-circle-exclamation', - 'fas fa-plane-circle-xmark', - 'fas fa-plane-departure', - 'fas fa-plane-lock', - 'fas fa-plane-slash', - 'fas fa-plane-up', - 'fas fa-plant-wilt', - 'fas fa-plate-wheat', - 'fas fa-play', - 'fab fa-playstation', - 'fas fa-plug', - 'fas fa-plug-circle-bolt', - 'fas fa-plug-circle-check', - 'fas fa-plug-circle-exclamation', - 'fas fa-plug-circle-minus', - 'fas fa-plug-circle-plus', - 'fas fa-plug-circle-xmark', - 'fas fa-plus', - 'fas fa-plus-minus', - 'fas fa-podcast', - 'fas fa-poo', - 'fas fa-poo-storm', - 'fas fa-poop', - 'fas fa-power-off', - 'fas fa-prescription', - 'fas fa-prescription-bottle', - 'fas fa-prescription-bottle-medical', - 'fas fa-print', - 'fab fa-product-hunt', - 'fas fa-pump-medical', - 'fas fa-pump-soap', - 'fab fa-pushed', - 'fas fa-puzzle-piece', - 'fab fa-python', - 'fas fa-q', - 'fab fa-qq', - 'fas fa-qrcode', - 'fas fa-question', - 'fab fa-quinscape', - 'fab fa-quora', - 'fas fa-quote-left', - 'fas fa-quote-right', - 'fas fa-r', - 'fab fa-r-project', - 'fas fa-radiation', - 'fas fa-radio', - 'fas fa-rainbow', - 'fas fa-ranking-star', - 'fab fa-raspberry-pi', - 'fab fa-ravelry', - 'fab fa-react', - 'fab fa-reacteurope', - 'fab fa-readme', - 'fab fa-rebel', - 'fas fa-receipt', - 'fas fa-record-vinyl', - 'fas fa-rectangle-ad', - 'fas fa-rectangle-list', - 'far fa-rectangle-list', - 'fas fa-rectangle-xmark', - 'far fa-rectangle-xmark', - 'fas fa-recycle', - 'fab fa-red-river', - 'fab fa-reddit', - 'fab fa-reddit-alien', - 'fab fa-redhat', - 'fas fa-registered', - 'far fa-registered', - 'fab fa-renren', - 'fas fa-repeat', - 'fas fa-reply', - 'fas fa-reply-all', - 'fab fa-replyd', - 'fas fa-republican', - 'fab fa-researchgate', - 'fab fa-resolving', - 'fas fa-restroom', - 'fas fa-retweet', - 'fab fa-rev', - 'fas fa-ribbon', - 'fas fa-right-from-bracket', - 'fas fa-right-left', - 'fas fa-right-long', - 'fas fa-right-to-bracket', - 'fas fa-ring', - 'fas fa-road', - 'fas fa-road-barrier', - 'fas fa-road-bridge', - 'fas fa-road-circle-check', - 'fas fa-road-circle-exclamation', - 'fas fa-road-circle-xmark', - 'fas fa-road-lock', - 'fas fa-road-spikes', - 'fas fa-robot', - 'fas fa-rocket', - 'fab fa-rocketchat', - 'fab fa-rockrms', - 'fas fa-rotate', - 'fas fa-rotate-left', - 'fas fa-rotate-right', - 'fas fa-route', - 'fas fa-rss', - 'fas fa-ruble-sign', - 'fas fa-rug', - 'fas fa-ruler', - 'fas fa-ruler-combined', - 'fas fa-ruler-horizontal', - 'fas fa-ruler-vertical', - 'fas fa-rupee-sign', - 'fas fa-rupiah-sign', - 'fab fa-rust', - 'fas fa-s', - 'fas fa-sack-dollar', - 'fas fa-sack-xmark', - 'fab fa-safari', - 'fas fa-sailboat', - 'fab fa-salesforce', - 'fab fa-sass', - 'fas fa-satellite', - 'fas fa-satellite-dish', - 'fas fa-scale-balanced', - 'fas fa-scale-unbalanced', - 'fas fa-scale-unbalanced-flip', - 'fab fa-schlix', - 'fas fa-school', - 'fas fa-school-circle-check', - 'fas fa-school-circle-exclamation', - 'fas fa-school-circle-xmark', - 'fas fa-school-flag', - 'fas fa-school-lock', - 'fas fa-scissors', - 'fab fa-screenpal', - 'fas fa-screwdriver', - 'fas fa-screwdriver-wrench', - 'fab fa-scribd', - 'fas fa-scroll', - 'fas fa-scroll-torah', - 'fas fa-sd-card', - 'fab fa-searchengin', - 'fas fa-section', - 'fas fa-seedling', - 'fab fa-sellcast', - 'fab fa-sellsy', - 'fas fa-server', - 'fab fa-servicestack', - 'fas fa-shapes', - 'fas fa-share', - 'fas fa-share-from-square', - 'far fa-share-from-square', - 'fas fa-share-nodes', - 'fas fa-sheet-plastic', - 'fas fa-shekel-sign', - 'fas fa-shield', - 'fas fa-shield-cat', - 'fas fa-shield-dog', - 'fas fa-shield-halved', - 'fas fa-shield-heart', - 'fas fa-shield-virus', - 'fas fa-ship', - 'fas fa-shirt', - 'fab fa-shirtsinbulk', - 'fas fa-shoe-prints', - 'fab fa-shoelace', - 'fas fa-shop', - 'fas fa-shop-lock', - 'fas fa-shop-slash', - 'fab fa-shopify', - 'fab fa-shopware', - 'fas fa-shower', - 'fas fa-shrimp', - 'fas fa-shuffle', - 'fas fa-shuttle-space', - 'fas fa-sign-hanging', - 'fas fa-signal', - 'fab fa-signal-messenger', - 'fas fa-signature', - 'fas fa-signs-post', - 'fas fa-sim-card', - 'fab fa-simplybuilt', - 'fas fa-sink', - 'fab fa-sistrix', - 'fas fa-sitemap', - 'fab fa-sith', - 'fab fa-sitrox', - 'fab fa-sketch', - 'fas fa-skull', - 'fas fa-skull-crossbones', - 'fab fa-skyatlas', - 'fab fa-skype', - 'fab fa-slack', - 'fas fa-slash', - 'fas fa-sleigh', - 'fas fa-sliders', - 'fab fa-slideshare', - 'fas fa-smog', - 'fas fa-smoking', - 'fab fa-snapchat', - 'fas fa-snowflake', - 'far fa-snowflake', - 'fas fa-snowman', - 'fas fa-snowplow', - 'fas fa-soap', - 'fas fa-socks', - 'fas fa-solar-panel', - 'fas fa-sort', - 'fas fa-sort-down', - 'fas fa-sort-up', - 'fab fa-soundcloud', - 'fab fa-sourcetree', - 'fas fa-spa', - 'fab fa-space-awesome', - 'fas fa-spaghetti-monster-flying', - 'fab fa-speakap', - 'fab fa-speaker-deck', - 'fas fa-spell-check', - 'fas fa-spider', - 'fas fa-spinner', - 'fas fa-splotch', - 'fas fa-spoon', - 'fab fa-spotify', - 'fas fa-spray-can', - 'fas fa-spray-can-sparkles', - 'fas fa-square', - 'far fa-square', - 'fas fa-square-arrow-up-right', - 'fab fa-square-behance', - 'fas fa-square-caret-down', - 'far fa-square-caret-down', - 'fas fa-square-caret-left', - 'far fa-square-caret-left', - 'fas fa-square-caret-right', - 'far fa-square-caret-right', - 'fas fa-square-caret-up', - 'far fa-square-caret-up', - 'fas fa-square-check', - 'far fa-square-check', - 'fab fa-square-dribbble', - 'fas fa-square-envelope', - 'fab fa-square-facebook', - 'fab fa-square-font-awesome', - 'fab fa-square-font-awesome-stroke', - 'fas fa-square-full', - 'far fa-square-full', - 'fab fa-square-git', - 'fab fa-square-github', - 'fab fa-square-gitlab', - 'fab fa-square-google-plus', - 'fas fa-square-h', - 'fab fa-square-hacker-news', - 'fab fa-square-instagram', - 'fab fa-square-js', - 'fab fa-square-lastfm', - 'fab fa-square-letterboxd', - 'fas fa-square-minus', - 'far fa-square-minus', - 'fas fa-square-nfi', - 'fab fa-square-odnoklassniki', - 'fas fa-square-parking', - 'fas fa-square-pen', - 'fas fa-square-person-confined', - 'fas fa-square-phone', - 'fas fa-square-phone-flip', - 'fab fa-square-pied-piper', - 'fab fa-square-pinterest', - 'fas fa-square-plus', - 'far fa-square-plus', - 'fas fa-square-poll-horizontal', - 'fas fa-square-poll-vertical', - 'fab fa-square-reddit', - 'fas fa-square-root-variable', - 'fas fa-square-rss', - 'fas fa-square-share-nodes', - 'fab fa-square-snapchat', - 'fab fa-square-steam', - 'fab fa-square-threads', - 'fab fa-square-tumblr', - 'fab fa-square-twitter', - 'fas fa-square-up-right', - 'fab fa-square-viadeo', - 'fab fa-square-vimeo', - 'fas fa-square-virus', - 'fab fa-square-whatsapp', - 'fab fa-square-x-twitter', - 'fab fa-square-xing', - 'fas fa-square-xmark', - 'fab fa-square-youtube', - 'fab fa-squarespace', - 'fab fa-stack-exchange', - 'fab fa-stack-overflow', - 'fab fa-stackpath', - 'fas fa-staff-snake', - 'fas fa-stairs', - 'fas fa-stamp', - 'fas fa-stapler', - 'fas fa-star', - 'far fa-star', - 'fas fa-star-and-crescent', - 'fas fa-star-half', - 'far fa-star-half', - 'fas fa-star-half-stroke', - 'far fa-star-half-stroke', - 'fas fa-star-of-david', - 'fas fa-star-of-life', - 'fab fa-staylinked', - 'fab fa-steam', - 'fab fa-steam-symbol', - 'fas fa-sterling-sign', - 'fas fa-stethoscope', - 'fab fa-sticker-mule', - 'fas fa-stop', - 'fas fa-stopwatch', - 'fas fa-stopwatch-20', - 'fas fa-store', - 'fas fa-store-slash', - 'fab fa-strava', - 'fas fa-street-view', - 'fas fa-strikethrough', - 'fab fa-stripe', - 'fab fa-stripe-s', - 'fas fa-stroopwafel', - 'fab fa-stubber', - 'fab fa-studiovinari', - 'fab fa-stumbleupon', - 'fab fa-stumbleupon-circle', - 'fas fa-subscript', - 'fas fa-suitcase', - 'fas fa-suitcase-medical', - 'fas fa-suitcase-rolling', - 'fas fa-sun', - 'far fa-sun', - 'fas fa-sun-plant-wilt', - 'fab fa-superpowers', - 'fas fa-superscript', - 'fab fa-supple', - 'fab fa-suse', - 'fas fa-swatchbook', - 'fab fa-swift', - 'fab fa-symfony', - 'fas fa-synagogue', - 'fas fa-syringe', - 'fas fa-t', - 'fas fa-table', - 'fas fa-table-cells', - 'fas fa-table-cells-large', - 'fas fa-table-columns', - 'fas fa-table-list', - 'fas fa-table-tennis-paddle-ball', - 'fas fa-tablet', - 'fas fa-tablet-button', - 'fas fa-tablet-screen-button', - 'fas fa-tablets', - 'fas fa-tachograph-digital', - 'fas fa-tag', - 'fas fa-tags', - 'fas fa-tape', - 'fas fa-tarp', - 'fas fa-tarp-droplet', - 'fas fa-taxi', - 'fab fa-teamspeak', - 'fas fa-teeth', - 'fas fa-teeth-open', - 'fab fa-telegram', - 'fas fa-temperature-arrow-down', - 'fas fa-temperature-arrow-up', - 'fas fa-temperature-empty', - 'fas fa-temperature-full', - 'fas fa-temperature-half', - 'fas fa-temperature-high', - 'fas fa-temperature-low', - 'fas fa-temperature-quarter', - 'fas fa-temperature-three-quarters', - 'fab fa-tencent-weibo', - 'fas fa-tenge-sign', - 'fas fa-tent', - 'fas fa-tent-arrow-down-to-line', - 'fas fa-tent-arrow-left-right', - 'fas fa-tent-arrow-turn-left', - 'fas fa-tent-arrows-down', - 'fas fa-tents', - 'fas fa-terminal', - 'fas fa-text-height', - 'fas fa-text-slash', - 'fas fa-text-width', - 'fab fa-the-red-yeti', - 'fab fa-themeco', - 'fab fa-themeisle', - 'fas fa-thermometer', - 'fab fa-think-peaks', - 'fab fa-threads', - 'fas fa-thumbs-down', - 'far fa-thumbs-down', - 'fas fa-thumbs-up', - 'far fa-thumbs-up', - 'fas fa-thumbtack', - 'fas fa-ticket', - 'fas fa-ticket-simple', - 'fab fa-tiktok', - 'fas fa-timeline', - 'fas fa-toggle-off', - 'fas fa-toggle-on', - 'fas fa-toilet', - 'fas fa-toilet-paper', - 'fas fa-toilet-paper-slash', - 'fas fa-toilet-portable', - 'fas fa-toilets-portable', - 'fas fa-toolbox', - 'fas fa-tooth', - 'fas fa-torii-gate', - 'fas fa-tornado', - 'fas fa-tower-broadcast', - 'fas fa-tower-cell', - 'fas fa-tower-observation', - 'fas fa-tractor', - 'fab fa-trade-federation', - 'fas fa-trademark', - 'fas fa-traffic-light', - 'fas fa-trailer', - 'fas fa-train', - 'fas fa-train-subway', - 'fas fa-train-tram', - 'fas fa-transgender', - 'fas fa-trash', - 'fas fa-trash-arrow-up', - 'fas fa-trash-can', - 'far fa-trash-can', - 'fas fa-trash-can-arrow-up', - 'fas fa-tree', - 'fas fa-tree-city', - 'fab fa-trello', - 'fas fa-triangle-exclamation', - 'fas fa-trophy', - 'fas fa-trowel', - 'fas fa-trowel-bricks', - 'fas fa-truck', - 'fas fa-truck-arrow-right', - 'fas fa-truck-droplet', - 'fas fa-truck-fast', - 'fas fa-truck-field', - 'fas fa-truck-field-un', - 'fas fa-truck-front', - 'fas fa-truck-medical', - 'fas fa-truck-monster', - 'fas fa-truck-moving', - 'fas fa-truck-pickup', - 'fas fa-truck-plane', - 'fas fa-truck-ramp-box', - 'fas fa-tty', - 'fab fa-tumblr', - 'fas fa-turkish-lira-sign', - 'fas fa-turn-down', - 'fas fa-turn-up', - 'fas fa-tv', - 'fab fa-twitch', - 'fab fa-twitter', - 'fab fa-typo3', - 'fas fa-u', - 'fab fa-uber', - 'fab fa-ubuntu', - 'fab fa-uikit', - 'fab fa-umbraco', - 'fas fa-umbrella', - 'fas fa-umbrella-beach', - 'fab fa-uncharted', - 'fas fa-underline', - 'fab fa-uniregistry', - 'fab fa-unity', - 'fas fa-universal-access', - 'fas fa-unlock', - 'fas fa-unlock-keyhole', - 'fab fa-unsplash', - 'fab fa-untappd', - 'fas fa-up-down', - 'fas fa-up-down-left-right', - 'fas fa-up-long', - 'fas fa-up-right-and-down-left-from-center', - 'fas fa-up-right-from-square', - 'fas fa-upload', - 'fab fa-ups', - 'fab fa-upwork', - 'fab fa-usb', - 'fas fa-user', - 'far fa-user', - 'fas fa-user-astronaut', - 'fas fa-user-check', - 'fas fa-user-clock', - 'fas fa-user-doctor', - 'fas fa-user-gear', - 'fas fa-user-graduate', - 'fas fa-user-group', - 'fas fa-user-injured', - 'fas fa-user-large', - 'fas fa-user-large-slash', - 'fas fa-user-lock', - 'fas fa-user-minus', - 'fas fa-user-ninja', - 'fas fa-user-nurse', - 'fas fa-user-pen', - 'fas fa-user-plus', - 'fas fa-user-secret', - 'fas fa-user-shield', - 'fas fa-user-slash', - 'fas fa-user-tag', - 'fas fa-user-tie', - 'fas fa-user-xmark', - 'fas fa-users', - 'fas fa-users-between-lines', - 'fas fa-users-gear', - 'fas fa-users-line', - 'fas fa-users-rays', - 'fas fa-users-rectangle', - 'fas fa-users-slash', - 'fas fa-users-viewfinder', - 'fab fa-usps', - 'fab fa-ussunnah', - 'fas fa-utensils', - 'fas fa-v', - 'fab fa-vaadin', - 'fas fa-van-shuttle', - 'fas fa-vault', - 'fas fa-vector-square', - 'fas fa-venus', - 'fas fa-venus-double', - 'fas fa-venus-mars', - 'fas fa-vest', - 'fas fa-vest-patches', - 'fab fa-viacoin', - 'fab fa-viadeo', - 'fas fa-vial', - 'fas fa-vial-circle-check', - 'fas fa-vial-virus', - 'fas fa-vials', - 'fab fa-viber', - 'fas fa-video', - 'fas fa-video-slash', - 'fas fa-vihara', - 'fab fa-vimeo', - 'fab fa-vimeo-v', - 'fab fa-vine', - 'fas fa-virus', - 'fas fa-virus-covid', - 'fas fa-virus-covid-slash', - 'fas fa-virus-slash', - 'fas fa-viruses', - 'fab fa-vk', - 'fab fa-vnv', - 'fas fa-voicemail', - 'fas fa-volcano', - 'fas fa-volleyball', - 'fas fa-volume-high', - 'fas fa-volume-low', - 'fas fa-volume-off', - 'fas fa-volume-xmark', - 'fas fa-vr-cardboard', - 'fab fa-vuejs', - 'fas fa-w', - 'fas fa-walkie-talkie', - 'fas fa-wallet', - 'fas fa-wand-magic', - 'fas fa-wand-magic-sparkles', - 'fas fa-wand-sparkles', - 'fas fa-warehouse', - 'fab fa-watchman-monitoring', - 'fas fa-water', - 'fas fa-water-ladder', - 'fas fa-wave-square', - 'fab fa-waze', - 'fab fa-webflow', - 'fab fa-weebly', - 'fab fa-weibo', - 'fas fa-weight-hanging', - 'fas fa-weight-scale', - 'fab fa-weixin', - 'fab fa-whatsapp', - 'fas fa-wheat-awn', - 'fas fa-wheat-awn-circle-exclamation', - 'fas fa-wheelchair', - 'fas fa-wheelchair-move', - 'fas fa-whiskey-glass', - 'fab fa-whmcs', - 'fas fa-wifi', - 'fab fa-wikipedia-w', - 'fas fa-wind', - 'fas fa-window-maximize', - 'far fa-window-maximize', - 'fas fa-window-minimize', - 'far fa-window-minimize', - 'fas fa-window-restore', - 'far fa-window-restore', - 'fab fa-windows', - 'fas fa-wine-bottle', - 'fas fa-wine-glass', - 'fas fa-wine-glass-empty', - 'fab fa-wirsindhandwerk', - 'fab fa-wix', - 'fab fa-wizards-of-the-coast', - 'fab fa-wodu', - 'fab fa-wolf-pack-battalion', - 'fas fa-won-sign', - 'fab fa-wordpress', - 'fab fa-wordpress-simple', - 'fas fa-worm', - 'fab fa-wpbeginner', - 'fab fa-wpexplorer', - 'fab fa-wpforms', - 'fab fa-wpressr', - 'fas fa-wrench', - 'fas fa-x', - 'fas fa-x-ray', - 'fab fa-x-twitter', - 'fab fa-xbox', - 'fab fa-xing', - 'fas fa-xmark', - 'fas fa-xmarks-lines', - 'fas fa-y', - 'fab fa-y-combinator', - 'fab fa-yahoo', - 'fab fa-yammer', - 'fab fa-yandex', - 'fab fa-yandex-international', - 'fab fa-yarn', - 'fab fa-yelp', - 'fas fa-yen-sign', - 'fas fa-yin-yang', - 'fab fa-yoast', - 'fab fa-youtube', - 'fas fa-z', - 'fab fa-zhihu' - ]; + $solidIcons = new SolidIcon(); + $regularIcons = new RegularIcon(); + $brandIcons = new BrandIcon(); + + return array_merge( + array_map(static fn($icon): string => 'fas fa-' . $icon, $solidIcons->getAll()), + array_map(static fn($icon): string => 'far fa-' . $icon, $regularIcons->getAll()), + array_map(static fn($icon): string => 'fab fa-' . $icon, $brandIcons->getAll()), + ); } } diff --git a/src/Sources/LightPortal/composer.json b/src/Sources/LightPortal/composer.json index 66d69af8..f53984bd 100644 --- a/src/Sources/LightPortal/composer.json +++ b/src/Sources/LightPortal/composer.json @@ -5,6 +5,7 @@ "ext-intl": "*", "ext-simplexml": "*", "ext-zip": "*", + "bugo/fa-php-helper": "^0.1.0", "bugo/smf-compat": "^0.1.4", "eftec/bladeone": "^4.11", "laminas/laminas-loader": "^2.9" From 219b304cdb848207d0efdd7fc667816188b76705 Mon Sep 17 00:00:00 2001 From: Bugo Date: Sun, 10 Mar 2024 07:08:30 +0500 Subject: [PATCH 24/25] Update UI for guests (UserInfo) --- src/Sources/LightPortal/Addons/UserInfo/template.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Sources/LightPortal/Addons/UserInfo/template.php b/src/Sources/LightPortal/Addons/UserInfo/template.php index 0c4fc49d..55c9c937 100644 --- a/src/Sources/LightPortal/Addons/UserInfo/template.php +++ b/src/Sources/LightPortal/Addons/UserInfo/template.php @@ -67,7 +67,7 @@ function show_user_info_for_guests(): void
  • ', Lang::$txt['hello_member'], ' ', Lang::$txt['guest'], '
  • *
  • -
  • '; +
  • '; if (Utils::$context['can_register']) { echo ' From 905571e9c41a3009b0a358d399e8907b91dec697 Mon Sep 17 00:00:00 2001 From: Bugo Date: Sun, 10 Mar 2024 08:58:30 +0500 Subject: [PATCH 25/25] Update version --- src/Sources/LightPortal/Integration.php | 2 +- src/package-info.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Sources/LightPortal/Integration.php b/src/Sources/LightPortal/Integration.php index a0834ff6..5d096364 100644 --- a/src/Sources/LightPortal/Integration.php +++ b/src/Sources/LightPortal/Integration.php @@ -56,7 +56,7 @@ public function init(): void Utils::$context['lp_num_queries'] ??= 0; defined('LP_NAME') || define('LP_NAME', 'Light Portal'); - defined('LP_VERSION') || define('LP_VERSION', '2.6.0'); + defined('LP_VERSION') || define('LP_VERSION', '2.6.1'); defined('LP_PLUGIN_LIST') || define('LP_PLUGIN_LIST', 'https://d8d75ea98b25aa12.mokky.dev/addons'); defined('LP_ADDON_URL') || define('LP_ADDON_URL', Config::$boardurl . '/Sources/LightPortal/Addons'); defined('LP_ADDON_DIR') || define('LP_ADDON_DIR', __DIR__ . '/Addons'); diff --git a/src/package-info.xml b/src/package-info.xml index 10e0b27d..bb4865d5 100644 --- a/src/package-info.xml +++ b/src/package-info.xml @@ -3,7 +3,7 @@ Bugo:LightPortal Light Portal - 2.6.0 + 2.6.1 modification @@ -30,7 +30,7 @@ - +