├── .editorconfig ├── LICENSE ├── src ├── Sources │ └── LightPortal │ │ ├── .editorconfig │ │ ├── .meta-storm.xml │ │ ├── Actions │ │ ├── AbstractPageList.php │ │ ├── ActionInterface.php │ │ ├── Block.php │ │ ├── BoardIndex.php │ │ ├── CardList.php │ │ ├── CardListInterface.php │ │ ├── Category.php │ │ ├── Comment.php │ │ ├── FrontPage.php │ │ ├── Page.php │ │ ├── PageListInterface.php │ │ ├── Tag.php │ │ └── index.php │ │ ├── Areas │ │ ├── BlockArea.php │ │ ├── CategoryArea.php │ │ ├── ConfigArea.php │ │ ├── Configs │ │ │ ├── AbstractConfig.php │ │ │ ├── BasicConfig.php │ │ │ ├── ExtraConfig.php │ │ │ ├── FeedbackConfig.php │ │ │ ├── MiscConfig.php │ │ │ ├── PanelConfig.php │ │ │ ├── VarFactory.php │ │ │ └── index.php │ │ ├── CreditArea.php │ │ ├── Exports │ │ │ ├── AbstractExport.php │ │ │ ├── BlockExport.php │ │ │ ├── CategoryExport.php │ │ │ ├── ExportInterface.php │ │ │ ├── PageExport.php │ │ │ ├── PluginExport.php │ │ │ ├── TagExport.php │ │ │ └── index.php │ │ ├── Imports │ │ │ ├── AbstractCustomBlockImport.php │ │ │ ├── AbstractCustomCategoryImport.php │ │ │ ├── AbstractCustomImport.php │ │ │ ├── AbstractCustomPageImport.php │ │ │ ├── AbstractImport.php │ │ │ ├── BlockImport.php │ │ │ ├── CategoryImport.php │ │ │ ├── CustomImportInterface.php │ │ │ ├── ImportInterface.php │ │ │ ├── PageImport.php │ │ │ ├── PluginImport.php │ │ │ ├── TagImport.php │ │ │ ├── Traits │ │ │ │ ├── CanInsertDataTrait.php │ │ │ │ ├── HasComments.php │ │ │ │ ├── HasParams.php │ │ │ │ ├── HasTitles.php │ │ │ │ ├── HasTransactions.php │ │ │ │ └── index.php │ │ │ └── index.php │ │ ├── PageArea.php │ │ ├── PluginArea.php │ │ ├── TagArea.php │ │ ├── Traits │ │ │ ├── HasArea.php │ │ │ ├── HasQuery.php │ │ │ └── index.php │ │ └── index.php │ │ ├── Articles │ │ ├── AbstractArticle.php │ │ ├── ArticleInterface.php │ │ ├── BoardArticle.php │ │ ├── ChosenPageArticle.php │ │ ├── ChosenTopicArticle.php │ │ ├── PageArticle.php │ │ ├── TopicArticle.php │ │ └── index.php │ │ ├── Container.php │ │ ├── Enums │ │ ├── Action.php │ │ ├── AlertAction.php │ │ ├── ContentClass.php │ │ ├── ContentType.php │ │ ├── EntryType.php │ │ ├── Hook.php │ │ ├── Permission.php │ │ ├── Placement.php │ │ ├── PluginType.php │ │ ├── PortalHook.php │ │ ├── PortalSubAction.php │ │ ├── Status.php │ │ ├── Tab.php │ │ ├── TitleClass.php │ │ ├── Traits │ │ │ ├── HasHtml.php │ │ │ ├── HasNames.php │ │ │ ├── HasValues.php │ │ │ └── index.php │ │ ├── VarType.php │ │ └── index.php │ │ ├── Events │ │ ├── EventManager.php │ │ ├── EventManagerFactory.php │ │ ├── HasEvents.php │ │ └── index.php │ │ ├── Hooks │ │ ├── Actions.php │ │ ├── AlertTypes.php │ │ ├── BuildRoute.php │ │ ├── CurrentAction.php │ │ ├── DefaultAction.php │ │ ├── DeleteMembers.php │ │ ├── DisplayButtons.php │ │ ├── DownloadRequest.php │ │ ├── FetchAlerts.php │ │ ├── HasCommonChecks.php │ │ ├── Init.php │ │ ├── LoadIllegalGuestPermissions.php │ │ ├── LoadPermissions.php │ │ ├── LoadTheme.php │ │ ├── MenuButtons.php │ │ ├── PermissionsList.php │ │ ├── PreCssOutput.php │ │ ├── ProfileAreas.php │ │ ├── ProfilePopup.php │ │ ├── Redirect.php │ │ ├── RouteParsers.php │ │ ├── WhosOnline.php │ │ └── index.php │ │ ├── Integration.php │ │ ├── Lists │ │ ├── CategoryList.php │ │ ├── IconList.php │ │ ├── ListInterface.php │ │ ├── PageList.php │ │ ├── PluginList.php │ │ ├── TagList.php │ │ └── index.php │ │ ├── Models │ │ ├── AbstractFactory.php │ │ ├── AbstractModel.php │ │ ├── BlockFactory.php │ │ ├── BlockModel.php │ │ ├── CategoryFactory.php │ │ ├── CategoryModel.php │ │ ├── FactoryInterface.php │ │ ├── ModelInterface.php │ │ ├── PageFactory.php │ │ ├── PageModel.php │ │ ├── TagFactory.php │ │ ├── TagModel.php │ │ └── index.php │ │ ├── Plugins │ │ ├── AdsBlock │ │ │ ├── AdsBlock.php │ │ │ ├── Hooks │ │ │ │ ├── DisplayButtons.php │ │ │ │ ├── MenuButtons.php │ │ │ │ ├── MessageindexButtons.php │ │ │ │ ├── PrepareDisplayContext.php │ │ │ │ └── index.php │ │ │ ├── Placement.php │ │ │ ├── PlacementSelect.php │ │ │ ├── RepliesComparisonTrait.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ └── template.php │ │ ├── ApexCharts │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── ArticleList │ │ │ ├── ArticleList.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ └── style.css │ │ ├── AssetHandler.php │ │ ├── Block.php │ │ ├── BlogMode │ │ │ ├── BlogArticle.php │ │ │ ├── BlogIndex.php │ │ │ ├── BlogMode.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── BoardList │ │ │ ├── BoardList.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── BoardNews │ │ │ ├── BoardNews.php │ │ │ ├── CustomSelectField.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── BoardStats │ │ │ ├── BoardStats.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ └── style.css │ │ ├── BootstrapIcons │ │ │ ├── BootstrapIcons.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ └── style.css │ │ ├── Calculator │ │ │ ├── Calculator.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ ├── script.js │ │ │ ├── style.css │ │ │ └── template.php │ │ ├── CategoryList │ │ │ ├── CategoryList.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── Chart │ │ │ ├── Chart.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ └── template.php │ │ ├── ChessBoard │ │ │ ├── ChessBoard.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ └── script.js │ │ ├── CodeMirror │ │ │ ├── CodeMirror.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── ConfigHandler.php │ │ ├── CurrentMonth │ │ │ ├── CurrentMonth.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ ├── style.css │ │ │ └── template.php │ │ ├── CustomTranslate │ │ │ ├── CustomTranslate.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ ├── script.js │ │ │ ├── style.css │ │ │ └── template.php │ │ ├── DiceBear │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── Disqus │ │ │ ├── Disqus.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── Dragula │ │ │ ├── Dragula.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ ├── script.js │ │ │ └── style.css │ │ ├── DummyArticleCards │ │ │ ├── DummyArticle.php │ │ │ ├── DummyArticleCards.php │ │ │ ├── Lorem.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── EasyMarkdownEditor │ │ │ ├── EasyMarkdownEditor.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ └── style.css │ │ ├── EhPortalMigration │ │ │ ├── BlockImport.php │ │ │ ├── CategoryImport.php │ │ │ ├── EhPortalMigration.php │ │ │ ├── PageImport.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── Event.php │ │ ├── Events │ │ │ ├── Events.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ ├── style.css │ │ │ └── template.php │ │ ├── ExtendedMetaTags │ │ │ ├── ExtendedMetaTags.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── EzPortalMigration │ │ │ ├── BlockImport.php │ │ │ ├── EzPortalMigration.php │ │ │ ├── PageImport.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── FaBoardIcons │ │ │ ├── FaBoardIcons.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── FacebookComments │ │ │ ├── FacebookComments.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── GalleryBlock │ │ │ ├── CategorySelect.php │ │ │ ├── GalleryBlock.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ └── style.css │ │ ├── Giscus │ │ │ ├── Giscus.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── HelloPortal │ │ │ ├── HelloPortal.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ ├── steps.php │ │ │ ├── style.css │ │ │ └── template.php │ │ ├── HidingBlocks │ │ │ ├── BreakpointSelect.php │ │ │ ├── HidingBlocks.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── ImageUpload │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── IndexNow │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── Jodit │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── LangHandler.php │ │ ├── LanguageAccess │ │ │ ├── LanguageAccess.php │ │ │ ├── LanguageSelect.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── LatteLayouts │ │ │ ├── LatteLayouts.php │ │ │ ├── LatteRenderer.php │ │ │ ├── composer.json │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ └── layouts │ │ │ │ ├── alt.latte │ │ │ │ ├── alt2.latte │ │ │ │ ├── default.latte │ │ │ │ ├── example.latte │ │ │ │ ├── flarum.latte │ │ │ │ ├── index.php │ │ │ │ ├── simple.latte │ │ │ │ ├── simple2.latte │ │ │ │ ├── simple3.latte │ │ │ │ └── spectre.latte │ │ ├── Likely │ │ │ ├── ButtonSelect.php │ │ │ ├── Likely.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ └── style.css │ │ ├── LineAwesomeIcons │ │ │ ├── LineAwesomeIcons.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ └── style.css │ │ ├── MainIcons │ │ │ ├── MainIcons.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── MainMenu │ │ │ ├── MainMenu.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ └── template.php │ │ ├── Markdown │ │ │ ├── Markdown.php │ │ │ ├── SMF │ │ │ │ ├── BlockQuoteRenderer.php │ │ │ │ ├── FencedCodeRenderer.php │ │ │ │ ├── HeadingRenderer.php │ │ │ │ ├── ImageRenderer.php │ │ │ │ ├── LinkRenderer.php │ │ │ │ ├── ListBlockRenderer.php │ │ │ │ ├── ListItemRenderer.php │ │ │ │ ├── TableRenderer.php │ │ │ │ ├── TableRowRenderer.php │ │ │ │ └── index.php │ │ │ ├── composer.json │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ └── style.css │ │ ├── MaterialDesignIcons │ │ │ ├── MaterialDesignIcons.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── MediaBlock │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── News │ │ │ ├── News.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── Optimus │ │ │ ├── Optimus.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── PageList │ │ │ ├── PageList.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── PageScroll │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── Plugin.php │ │ ├── PluginHandler.php │ │ ├── PluginInterface.php │ │ ├── PluginMaker │ │ │ ├── Builder.php │ │ │ ├── Generator.php │ │ │ ├── Handler.php │ │ │ ├── License.php │ │ │ ├── PluginMaker.php │ │ │ ├── Validator.php │ │ │ ├── composer.json │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ └── template.php │ │ ├── Polls │ │ │ ├── Polls.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── PrettyUrls │ │ │ ├── PrettyUrls.php │ │ │ ├── functions.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── RandomPages │ │ │ ├── RandomPages.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ └── style.css │ │ ├── RandomTopics │ │ │ ├── RandomTopics.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ └── style.css │ │ ├── Reactions │ │ │ ├── Reactions.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ ├── style.css │ │ │ └── template.php │ │ ├── RecentAttachments │ │ │ ├── RecentAttachments.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ └── style.css │ │ ├── RecentComments │ │ │ ├── RecentComments.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ └── style.css │ │ ├── RecentPosts │ │ │ ├── RecentPosts.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ ├── style.css │ │ │ └── template.php │ │ ├── RecentTopics │ │ │ ├── RecentTopics.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ ├── style.css │ │ │ └── template.php │ │ ├── Search │ │ │ ├── Search.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ ├── style.css │ │ │ └── template.php │ │ ├── SimpleChat │ │ │ ├── Chat.php │ │ │ ├── SimpleChat.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ ├── script.js │ │ │ ├── style.css │ │ │ └── template.php │ │ ├── SimpleFeeder │ │ │ ├── SimpleFeeder.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── SimpleMenu │ │ │ ├── SimpleMenu.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ └── template.php │ │ ├── SiteList │ │ │ ├── SiteArticle.php │ │ │ ├── SiteList.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ └── template.php │ │ ├── Snowflakes │ │ │ ├── Snowflakes.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── Swiper │ │ │ ├── Swiper.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ ├── style.css │ │ │ └── template.php │ │ ├── TagList │ │ │ ├── DecoratorPluginManager.php │ │ │ ├── TagCloud.php │ │ │ ├── TagList.php │ │ │ ├── composer.json │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ └── style.css │ │ ├── ThemeSwitcher │ │ │ ├── ThemeSwitcher.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ └── style.css │ │ ├── TinyMCE │ │ │ ├── TinyMCE.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── TinyPortalMigration │ │ │ ├── BlockImport.php │ │ │ ├── CategoryImport.php │ │ │ ├── PageImport.php │ │ │ ├── TinyPortalMigration.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── TinySlider │ │ │ ├── TinySlider.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ ├── style.css │ │ │ └── template.php │ │ ├── TopBoards │ │ │ ├── TopBoards.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── TopPages │ │ │ ├── TopPages.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── TopPosters │ │ │ ├── TopPosters.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ └── style.css │ │ ├── TopTopics │ │ │ ├── TopTopics.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── TopicRatingBar │ │ │ ├── TopicRatingBar.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── Translator │ │ │ ├── Translator.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ ├── TrendingTopics │ │ │ ├── TrendingTopics.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ └── style.css │ │ ├── TwentyFortyEight │ │ │ ├── TwentyFortyEight.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ ├── script.js │ │ │ └── style.css │ │ ├── TwigLayouts │ │ │ ├── TwigLayouts.php │ │ │ ├── TwigRenderer.php │ │ │ ├── composer.json │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ └── layouts │ │ │ │ ├── default.twig │ │ │ │ ├── example.twig │ │ │ │ └── index.php │ │ ├── Uicons │ │ │ ├── Uicons.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ └── style.css │ │ ├── UserInfo │ │ │ ├── UserInfo.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ ├── style.css │ │ │ └── template.php │ │ ├── VkComments │ │ │ ├── VkComments.php │ │ │ ├── index.php │ │ │ ├── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ │ └── style.css │ │ ├── WhosOnline │ │ │ ├── WhosOnline.php │ │ │ ├── index.php │ │ │ └── langs │ │ │ │ ├── english.php │ │ │ │ └── index.php │ │ └── index.php │ │ ├── PortalApp.php │ │ ├── Renderers │ │ ├── AbstractRenderer.php │ │ ├── Blade.php │ │ ├── PurePHP.php │ │ ├── RendererInterface.php │ │ └── index.php │ │ ├── Repositories │ │ ├── AbstractRepository.php │ │ ├── BlockRepository.php │ │ ├── CategoryRepository.php │ │ ├── CommentRepository.php │ │ ├── PageRepository.php │ │ ├── PluginRepository.php │ │ ├── TagRepository.php │ │ └── index.php │ │ ├── Routes │ │ ├── Forum.php │ │ ├── Page.php │ │ ├── Portal.php │ │ └── index.php │ │ ├── ServiceProvider.php │ │ ├── Tasks │ │ ├── Maintainer.php │ │ ├── Notifier.php │ │ └── index.php │ │ ├── UI │ │ ├── Fields │ │ │ ├── AbstractField.php │ │ │ ├── CheckboxField.php │ │ │ ├── ColorField.php │ │ │ ├── CustomField.php │ │ │ ├── InputField.php │ │ │ ├── NumberField.php │ │ │ ├── RadioField.php │ │ │ ├── RangeField.php │ │ │ ├── SelectField.php │ │ │ ├── TextField.php │ │ │ ├── TextareaField.php │ │ │ ├── UrlField.php │ │ │ ├── VirtualSelectField.php │ │ │ └── index.php │ │ ├── Partials │ │ │ ├── AbstractPartial.php │ │ │ ├── ActionSelect.php │ │ │ ├── AreaSelect.php │ │ │ ├── BoardSelect.php │ │ │ ├── CategorySelect.php │ │ │ ├── ContentClassSelect.php │ │ │ ├── EntryTypeSelect.php │ │ │ ├── IconSelect.php │ │ │ ├── PageIconSelect.php │ │ │ ├── PageSelect.php │ │ │ ├── PageSlugSelect.php │ │ │ ├── PermissionSelect.php │ │ │ ├── PlacementSelect.php │ │ │ ├── StatusSelect.php │ │ │ ├── TagSelect.php │ │ │ ├── TitleClassSelect.php │ │ │ ├── TopicSelect.php │ │ │ └── index.php │ │ ├── Tables │ │ │ ├── Button.php │ │ │ ├── CheckboxColumn.php │ │ │ ├── ContextMenuColumn.php │ │ │ ├── ExportButtonsRow.php │ │ │ ├── HiddenInput.php │ │ │ ├── IconButton.php │ │ │ ├── IconColumn.php │ │ │ ├── ImportButtonsRow.php │ │ │ ├── Link.php │ │ │ ├── NumViewsColumn.php │ │ │ ├── PageButtonsRow.php │ │ │ ├── PageContextMenuColumn.php │ │ │ ├── PageSearchRow.php │ │ │ ├── PageSlugColumn.php │ │ │ ├── PageStatusColumn.php │ │ │ ├── PageTypeSelectRow.php │ │ │ ├── PortalTableBuilder.php │ │ │ ├── PortalTableBuilderInterface.php │ │ │ ├── StatusColumn.php │ │ │ ├── TableRenderer.php │ │ │ ├── TitleColumn.php │ │ │ └── index.php │ │ └── index.php │ │ ├── Utils │ │ ├── Avatar.php │ │ ├── Breadcrumbs.php │ │ ├── Cache.php │ │ ├── CacheInterface.php │ │ ├── Content.php │ │ ├── DateTime.php │ │ ├── Editor.php │ │ ├── File.php │ │ ├── GlobalArray.php │ │ ├── Icon.php │ │ ├── Language.php │ │ ├── MessageIndex.php │ │ ├── Notify.php │ │ ├── ParamWrapper.php │ │ ├── Post.php │ │ ├── Request.php │ │ ├── Response.php │ │ ├── Session.php │ │ ├── SessionManager.php │ │ ├── Setting.php │ │ ├── Str.php │ │ ├── Traits │ │ │ ├── HasBreadcrumbs.php │ │ │ ├── HasCache.php │ │ │ ├── HasForumHooks.php │ │ │ ├── HasReflection.php │ │ │ ├── HasRequest.php │ │ │ ├── HasResponse.php │ │ │ ├── HasSession.php │ │ │ ├── HasTemplate.php │ │ │ ├── HasThemes.php │ │ │ └── index.php │ │ ├── Weaver.php │ │ └── index.php │ │ ├── Validators │ │ ├── AbstractValidator.php │ │ ├── BlockValidator.php │ │ ├── CategoryValidator.php │ │ ├── PageValidator.php │ │ ├── TagValidator.php │ │ ├── ValidatorInterface.php │ │ └── index.php │ │ ├── app.php │ │ ├── composer.json │ │ ├── create_index.php │ │ ├── index.php │ │ └── update_plugins.php ├── Themes │ └── default │ │ ├── LightPortal │ │ ├── .editorconfig │ │ ├── ManageBlocks.template.php │ │ ├── ManageCategories.template.php │ │ ├── ManageFeedback.template.php │ │ ├── ManageImpex.template.php │ │ ├── ManagePages.template.php │ │ ├── ManagePanels.template.php │ │ ├── ManagePlugins.template.php │ │ ├── ManageSettings.template.php │ │ ├── ManageTags.template.php │ │ ├── ViewBlocks.template.php │ │ ├── ViewCredits.template.php │ │ ├── ViewDebug.template.php │ │ ├── ViewFrontPage.template.php │ │ ├── ViewPage.template.php │ │ ├── index.php │ │ └── layouts │ │ │ ├── alt.blade.php │ │ │ ├── alt2.blade.php │ │ │ ├── alt3.blade.php │ │ │ ├── debug.blade.php │ │ │ ├── default.blade.php │ │ │ ├── featured_grid.blade.php │ │ │ ├── flarum.blade.php │ │ │ ├── index.php │ │ │ ├── partials │ │ │ ├── base.blade.php │ │ │ ├── card-footer.blade.php │ │ │ ├── card-header.blade.php │ │ │ ├── card.blade.php │ │ │ ├── image.blade.php │ │ │ ├── index.php │ │ │ └── pagination.blade.php │ │ │ ├── simple.blade.php │ │ │ ├── simple2.blade.php │ │ │ ├── simple3.blade.php │ │ │ ├── simple_grid.blade.php │ │ │ └── spectre.blade.php │ │ ├── css │ │ └── light_portal │ │ │ ├── flexboxgrid.css │ │ │ └── index.php │ │ ├── languages │ │ └── LightPortal │ │ │ ├── LightPortal.english.php │ │ │ └── index.php │ │ └── scripts │ │ └── light_portal │ │ ├── index.php │ │ └── portal.js ├── database.php ├── package-info.xml ├── portal.php ├── uninstall-optional.php └── uninstall.php └── tsconfig.json /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | indent_style = tab 7 | indent_size = tab 8 | tab_width = 4 9 | trim_trailing_whitespace = true 10 | charset = utf-8 11 | 12 | [*.{js,css,json}] 13 | indent_style = space 14 | indent_size = 2 -------------------------------------------------------------------------------- /src/Sources/LightPortal/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | indent_style = tab 7 | indent_size = tab 8 | tab_width = 4 9 | trim_trailing_whitespace = true 10 | charset = utf-8 11 | 12 | [*.{js,css,json}] 13 | indent_style = space 14 | indent_size = 2 -------------------------------------------------------------------------------- /src/Sources/LightPortal/Actions/ActionInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Actions; 14 | 15 | interface ActionInterface 16 | { 17 | public function show(): void; 18 | } 19 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Actions/BoardIndex.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Actions; 14 | 15 | use Bugo\Compat\Actions\BoardIndex as Index; 16 | 17 | if (! defined('SMF')) 18 | die('No direct access...'); 19 | 20 | final class BoardIndex implements ActionInterface 21 | { 22 | public function show(): void 23 | { 24 | Index::call(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Actions/CardListInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Actions; 14 | 15 | use Bugo\Bricks\Tables\Interfaces\TableBuilderInterface; 16 | 17 | interface CardListInterface 18 | { 19 | public function show(PageListInterface $entity): void; 20 | 21 | public function getOrderBy(): string; 22 | 23 | public function getBuilder(string $id): TableBuilderInterface; 24 | } 25 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Actions/PageListInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Actions; 14 | 15 | interface PageListInterface extends ActionInterface 16 | { 17 | public function showAll(); 18 | 19 | public function getPages(int $start, int $limit, string $sort): array; 20 | 21 | public function getTotalPages(): int; 22 | } 23 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Actions/index.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Areas\Exports; 14 | 15 | interface ExportInterface 16 | { 17 | public function main(); 18 | } 19 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Areas/Exports/index.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Areas\Imports; 14 | 15 | interface CustomImportInterface 16 | { 17 | public function getAll(int $start, int $limit, string $sort): array; 18 | 19 | public function getTotalCount(): int; 20 | } 21 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Areas/Imports/ImportInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Areas\Imports; 14 | 15 | interface ImportInterface 16 | { 17 | public function main(); 18 | } 19 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Areas/Imports/Traits/HasComments.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Areas\Imports\Traits; 14 | 15 | trait HasComments 16 | { 17 | protected function replaceComments(array $comments, array &$results): void 18 | { 19 | if ($comments === [] || $results === []) 20 | return; 21 | 22 | $results = $this->insertData( 23 | 'lp_comments', 24 | 'replace', 25 | $comments, 26 | [ 27 | 'id' => 'int', 28 | 'parent_id' => 'int', 29 | 'page_id' => 'int', 30 | 'author_id' => 'int', 31 | 'message' => 'string', 32 | 'created_at' => 'int', 33 | ], 34 | ['id', 'page_id'], 35 | ); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Areas/Imports/Traits/HasParams.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Areas\Imports\Traits; 14 | 15 | trait HasParams 16 | { 17 | protected function replaceParams(array $params, array &$results): void 18 | { 19 | if ($params === [] || $results === []) 20 | return; 21 | 22 | $results = $this->insertData( 23 | 'lp_params', 24 | 'replace', 25 | $params, 26 | [ 27 | 'item_id' => 'int', 28 | 'type' => 'string', 29 | 'name' => 'string', 30 | 'value' => 'string', 31 | ], 32 | ['item_id', 'type', 'name'], 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Areas/Imports/Traits/index.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Articles; 14 | 15 | use Bugo\LightPortal\Events\HasEvents; 16 | 17 | if (! defined('SMF')) 18 | die('No direct access...'); 19 | 20 | abstract class AbstractArticle implements ArticleInterface 21 | { 22 | use HasEvents; 23 | 24 | protected array $columns = []; 25 | 26 | protected array $tables = []; 27 | 28 | protected array $wheres = []; 29 | 30 | protected array $params = []; 31 | 32 | protected array $orders = []; 33 | 34 | abstract public function init(): void; 35 | 36 | abstract public function getData(int $start, int $limit): array; 37 | 38 | abstract public function getTotalCount(): int; 39 | } 40 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Articles/ArticleInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Articles; 14 | 15 | if (! defined('SMF')) 16 | die('No direct access...'); 17 | 18 | interface ArticleInterface 19 | { 20 | public function init(): void; 21 | 22 | public function getData(int $start, int $limit): array; 23 | 24 | public function getTotalCount(): int; 25 | } 26 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Articles/index.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Enums; 14 | 15 | enum Action: string 16 | { 17 | case FORUM = 'forum'; 18 | case HOME = 'home'; 19 | case PAGES = 'pages'; 20 | } 21 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Enums/AlertAction.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Enums; 14 | 15 | use Bugo\LightPortal\Enums\Traits\HasNames; 16 | 17 | enum AlertAction 18 | { 19 | use HasNames; 20 | 21 | case PAGE_COMMENT; 22 | case PAGE_COMMENT_REPLY; 23 | case PAGE_UNAPPROVED; 24 | } 25 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Enums/EntryType.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Enums; 14 | 15 | use Bugo\Compat\Lang; 16 | use Bugo\LightPortal\Enums\Traits\HasNames; 17 | 18 | use function array_combine; 19 | use function array_filter; 20 | 21 | enum EntryType 22 | { 23 | use HasNames; 24 | 25 | case DEFAULT; 26 | case INTERNAL; 27 | case DRAFT; 28 | 29 | public static function all(): array 30 | { 31 | return array_combine(self::names(), Lang::$txt['lp_page_type_set']); 32 | } 33 | 34 | public static function withoutDrafts(): array 35 | { 36 | return array_filter(self::names(), fn($item) => $item !== self::DRAFT->name()); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Enums/Placement.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Enums; 14 | 15 | use Bugo\Compat\Lang; 16 | use Bugo\LightPortal\Enums\Traits\HasNames; 17 | 18 | use function array_combine; 19 | 20 | enum Placement 21 | { 22 | use HasNames; 23 | 24 | case HEADER; 25 | case TOP; 26 | case LEFT; 27 | case RIGHT; 28 | case BOTTOM; 29 | case FOOTER; 30 | 31 | public static function all(): array 32 | { 33 | return array_combine(self::names(), Lang::$txt['lp_block_placement_set']); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Enums/PluginType.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Enums; 14 | 15 | use Bugo\Compat\Lang; 16 | use Bugo\LightPortal\Enums\Traits\HasNames; 17 | 18 | use function array_combine; 19 | 20 | enum PluginType 21 | { 22 | use HasNames; 23 | 24 | case BLOCK; 25 | case SSI; 26 | case EDITOR; 27 | case COMMENT; 28 | case PARSER; 29 | case ARTICLE; 30 | case FRONTPAGE; 31 | case IMPEX; 32 | case BLOCK_OPTIONS; 33 | case PAGE_OPTIONS; 34 | case ICONS; 35 | case SEO; 36 | case OTHER; 37 | 38 | public static function all(): array 39 | { 40 | return array_combine(self::names(), Lang::$txt['lp_plugins_types']); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Enums/PortalSubAction.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Enums; 14 | 15 | use Bugo\LightPortal\Enums\Traits\HasNames; 16 | 17 | use const LP_BASE_URL; 18 | 19 | enum PortalSubAction 20 | { 21 | use HasNames; 22 | 23 | case CATEGORIES; 24 | case TAGS; 25 | case PROMOTE; 26 | 27 | public function url(): string 28 | { 29 | return LP_BASE_URL . ';sa=' . $this->name(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Enums/Status.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Enums; 14 | 15 | use Bugo\LightPortal\Enums\Traits\HasValues; 16 | 17 | enum Status: int 18 | { 19 | use HasValues; 20 | 21 | case INACTIVE = 0; 22 | case ACTIVE = 1; 23 | case UNAPPROVED = 2; 24 | } 25 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Enums/Tab.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Enums; 14 | 15 | use Bugo\LightPortal\Enums\Traits\HasNames; 16 | 17 | enum Tab 18 | { 19 | use HasNames; 20 | 21 | case CONTENT; 22 | case ACCESS_PLACEMENT; 23 | case APPEARANCE; 24 | case SEO; 25 | case TUNING; 26 | } 27 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Enums/Traits/HasHtml.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Enums\Traits; 14 | 15 | use function array_combine; 16 | use function array_key_first; 17 | use function array_map; 18 | use function sprintf; 19 | 20 | trait HasHtml 21 | { 22 | public static function values(): array 23 | { 24 | return array_combine( 25 | array_map(fn($class) => $class->value, self::cases()), 26 | array_map(fn($class) => $class->getList(), self::cases()) 27 | ); 28 | } 29 | 30 | public static function first(): string 31 | { 32 | return array_key_first(self::values()); 33 | } 34 | 35 | public static function html(string $content, string $class = ''): string 36 | { 37 | return sprintf(self::values()[$class] ?? self::values()[''], $content); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Enums/Traits/HasNames.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Enums\Traits; 14 | 15 | use function array_map; 16 | use function strtolower; 17 | 18 | trait HasNames 19 | { 20 | public function name(): string 21 | { 22 | return strtolower($this->name); 23 | } 24 | 25 | public static function names(): array 26 | { 27 | return array_map(fn($item) => $item->name(), self::cases()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Enums/Traits/HasValues.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Enums\Traits; 14 | 15 | use function array_map; 16 | 17 | trait HasValues 18 | { 19 | public static function values(): array 20 | { 21 | return array_map(fn($item) => $item->value, self::cases()); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Enums/Traits/index.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Events; 14 | 15 | use Bugo\LightPortal\Plugins\PluginHandler; 16 | 17 | final class EventManagerFactory 18 | { 19 | private static array $plugins = []; 20 | 21 | private static PluginHandler $handler; 22 | 23 | private static EventManager $manager; 24 | 25 | public function __invoke(array $plugins = []): EventManager 26 | { 27 | if ($plugins !== self::$plugins) { 28 | self::$plugins = $plugins; 29 | self::$handler = app(PluginHandler::class)($plugins); 30 | } 31 | 32 | self::$handler ??= app(PluginHandler::class)(); 33 | self::$manager = self::$handler->getManager(); 34 | 35 | return self::$manager; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Events/HasEvents.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Hooks; 14 | 15 | use Bugo\Compat\Lang; 16 | use Bugo\LightPortal\Enums\PortalHook; 17 | use Bugo\LightPortal\Events\HasEvents; 18 | 19 | if (! defined('SMF')) 20 | die('No direct access...'); 21 | 22 | class DownloadRequest 23 | { 24 | use HasEvents; 25 | 26 | public function __invoke(mixed &$attachRequest): void 27 | { 28 | Lang::load('LightPortal/LightPortal'); 29 | 30 | $this->events()->dispatch(PortalHook::downloadRequest, ['attachRequest' => &$attachRequest]); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Hooks/LoadIllegalGuestPermissions.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Hooks; 14 | 15 | use Bugo\Compat\Utils; 16 | 17 | use function array_merge; 18 | 19 | if (! defined('SMF')) 20 | die('No direct access...'); 21 | 22 | class LoadIllegalGuestPermissions 23 | { 24 | public function __invoke(): void 25 | { 26 | Utils::$context['non_guest_permissions'] = array_merge( 27 | Utils::$context['non_guest_permissions'], 28 | [ 29 | 'light_portal_manage_pages_own', 30 | 'light_portal_manage_pages_any', 31 | 'light_portal_manage_pages', 32 | 'light_portal_approve_pages', 33 | ] 34 | ); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Hooks/Redirect.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Hooks; 14 | 15 | use Bugo\Compat\Config; 16 | use Bugo\LightPortal\Utils\Setting; 17 | use Bugo\LightPortal\Utils\Traits\HasRequest; 18 | 19 | if (! defined('SMF')) 20 | die('No direct access...'); 21 | 22 | class Redirect 23 | { 24 | use HasRequest; 25 | 26 | public function __invoke(string &$setLocation): void 27 | { 28 | if (empty(Config::$modSettings['lp_frontpage_mode']) || Setting::isStandaloneMode()) 29 | return; 30 | 31 | if ($this->request()->is('markasread')) { 32 | $setLocation = Config::$scripturl . '?action=forum'; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Hooks/RouteParsers.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Hooks; 14 | 15 | use Bugo\Compat\QueryString; 16 | use Bugo\LightPortal\Enums\Action; 17 | use Bugo\LightPortal\Routes\Forum; 18 | use Bugo\LightPortal\Routes\Page; 19 | use Bugo\LightPortal\Routes\Portal; 20 | 21 | use const LP_ACTION; 22 | 23 | class RouteParsers 24 | { 25 | public function __invoke(): void 26 | { 27 | QueryString::$route_parsers[Action::FORUM->value] = Forum::class; 28 | QueryString::$route_parsers[Action::PAGES->value] = Page::class; 29 | QueryString::$route_parsers[LP_ACTION] = Portal::class; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Hooks/index.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Lists; 14 | 15 | interface ListInterface 16 | { 17 | public function __invoke(): array; 18 | } 19 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Lists/PluginList.php: -------------------------------------------------------------------------------- 1 | 9 | * @copyright 2019-2025 Bugo 10 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 11 | * 12 | * @version 2.9 13 | */ 14 | 15 | namespace Bugo\LightPortal\Lists; 16 | 17 | use function array_map; 18 | use function basename; 19 | use function glob; 20 | 21 | use const GLOB_ONLYDIR; 22 | use const LP_ADDON_DIR; 23 | 24 | if (! defined('SMF')) 25 | die('No direct access...'); 26 | 27 | class PluginList implements ListInterface 28 | { 29 | public function __invoke(): array 30 | { 31 | if (empty($dirs = glob(LP_ADDON_DIR . '/*', GLOB_ONLYDIR))) 32 | return []; 33 | 34 | return array_map(static fn($item): string => basename($item), $dirs); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Lists/index.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Models; 14 | 15 | use Bugo\LightPortal\Utils\Str; 16 | 17 | abstract class AbstractFactory implements FactoryInterface 18 | { 19 | protected string $modelClass; 20 | 21 | public function create(array $data): ModelInterface 22 | { 23 | if (! empty($data['titles'])) { 24 | Str::cleanBbcode($data['titles']); 25 | } 26 | 27 | $data = $this->modifyData($data); 28 | 29 | return new $this->modelClass($data); 30 | } 31 | 32 | protected function modifyData(array $data): array 33 | { 34 | return $data; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Models/BlockFactory.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Models; 14 | 15 | use Bugo\LightPortal\Utils\Str; 16 | 17 | class BlockFactory extends AbstractFactory 18 | { 19 | protected string $modelClass = BlockModel::class; 20 | 21 | protected function modifyData(array $data): array 22 | { 23 | if (! empty($data['note'])) { 24 | Str::cleanBbcode($data['note']); 25 | } 26 | 27 | return $data; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Models/CategoryFactory.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Models; 14 | 15 | use Bugo\LightPortal\Utils\Str; 16 | 17 | class CategoryFactory extends AbstractFactory 18 | { 19 | protected string $modelClass = CategoryModel::class; 20 | 21 | protected function modifyData(array $data): array 22 | { 23 | if (! empty($data['description'])) { 24 | Str::cleanBbcode($data['description']); 25 | } 26 | 27 | return $data; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Models/CategoryModel.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Models; 14 | 15 | use Bugo\LightPortal\Enums\Status; 16 | 17 | class CategoryModel extends AbstractModel 18 | { 19 | public int $id; 20 | 21 | public string $icon; 22 | 23 | public string $description; 24 | 25 | public int $priority; 26 | 27 | public int $status; 28 | 29 | public array $titles = []; 30 | 31 | public function __construct(array $data) 32 | { 33 | $this->id = $data['category_id'] ?? $data['id'] ?? 0; 34 | $this->icon = $data['icon'] ?? ''; 35 | $this->description = $data['description'] ?? ''; 36 | $this->priority = $data['priority'] ?? 0; 37 | $this->status = $data['status'] ?? Status::ACTIVE->value; 38 | $this->titles = $data['titles'] ?? []; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Models/FactoryInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Models; 14 | 15 | interface FactoryInterface 16 | { 17 | public function create(array $data): ModelInterface; 18 | } 19 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Models/ModelInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Models; 14 | 15 | interface ModelInterface 16 | { 17 | public function toArray(): array; 18 | } 19 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Models/PageFactory.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Models; 14 | 15 | use Bugo\LightPortal\Utils\Str; 16 | 17 | use function explode; 18 | use function is_array; 19 | 20 | class PageFactory extends AbstractFactory 21 | { 22 | protected string $modelClass = PageModel::class; 23 | 24 | protected function modifyData(array $data): array 25 | { 26 | if (! empty($data['description'])) { 27 | Str::cleanBbcode($data['description']); 28 | } 29 | 30 | $data['tags'] = empty($data['tags']) ? [] : $data['tags']; 31 | $data['tags'] = is_array($data['tags']) ? $data['tags'] : explode(',', (string) $data['tags']); 32 | 33 | return $data; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Models/TagFactory.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Models; 14 | 15 | class TagFactory extends AbstractFactory 16 | { 17 | protected string $modelClass = TagModel::class; 18 | } 19 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Models/TagModel.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Models; 14 | 15 | use Bugo\LightPortal\Enums\Status; 16 | 17 | class TagModel extends AbstractModel 18 | { 19 | public int $id; 20 | 21 | public string $icon; 22 | 23 | public int $status; 24 | 25 | public array $titles = []; 26 | 27 | public function __construct(array $data) 28 | { 29 | $this->id = $data['tag_id'] ?? $data['id'] ?? 0; 30 | $this->icon = $data['icon'] ?? ''; 31 | $this->status = $data['status'] ?? Status::ACTIVE->value; 32 | $this->titles = $data['titles'] ?? []; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Models/index.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2020-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @category plugin 11 | * @version 28.11.24 12 | */ 13 | 14 | namespace Bugo\LightPortal\Plugins\AdsBlock\Hooks; 15 | 16 | use Bugo\Compat\Utils; 17 | use Bugo\LightPortal\Plugins\AdsBlock\RepliesComparisonTrait; 18 | 19 | use function dirname; 20 | 21 | class DisplayButtons 22 | { 23 | use RepliesComparisonTrait; 24 | 25 | public function __invoke(): void 26 | { 27 | if ($this->isRepliesBelowMinimum()) 28 | return; 29 | 30 | require_once dirname(__DIR__) . '/template.php'; 31 | 32 | Utils::$context['template_layers'][] = 'ads_placement_topic'; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/AdsBlock/Hooks/MessageindexButtons.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2020-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @category plugin 11 | * @version 06.11.24 12 | */ 13 | 14 | namespace Bugo\LightPortal\Plugins\AdsBlock\Hooks; 15 | 16 | use Bugo\Compat\Utils; 17 | 18 | use function dirname; 19 | 20 | class MessageindexButtons 21 | { 22 | public function __invoke(): void 23 | { 24 | require_once dirname(__DIR__) . '/template.php'; 25 | 26 | Utils::$context['template_layers'][] = 'ads_placement_board'; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/AdsBlock/Hooks/index.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2020-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @category plugin 11 | * @version 06.11.24 12 | */ 13 | 14 | namespace Bugo\LightPortal\Plugins\AdsBlock; 15 | 16 | use Bugo\Compat\Utils; 17 | 18 | trait RepliesComparisonTrait 19 | { 20 | protected function isRepliesBelowMinimum(): bool 21 | { 22 | return isset(Utils::$context['lp_ads_block_plugin']['min_replies']) 23 | && Utils::$context['topicinfo']['num_replies'] < (int) Utils::$context['lp_ads_block_plugin']['min_replies']; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/AdsBlock/index.php: -------------------------------------------------------------------------------- 1 | 'Article List', 5 | 'description' => 'Displays a list of selected articles of the portal (with images if exist).', 6 | 'body_class' => 'CSS class of article blocks', 7 | 'display_type' => 'What should be displayed', 8 | 'display_type_set' => ['Forum topics', 'Portal pages'], 9 | 'include_topics' => 'Topics', 10 | 'include_topics_select' => 'Select the topics to be displayed inside the block.', 11 | 'include_pages' => 'Pages', 12 | 'include_pages_select' => 'Select the portal pages to display inside the block.', 13 | 'seek_images' => 'Search for images in the text of articles', 14 | 'no_items' => 'There are no available articles.' 15 | ]; 16 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/ArticleList/langs/index.php: -------------------------------------------------------------------------------- 1 | div { 7 | display: flex; 8 | flex-direction: column; 9 | justify-content: space-between; 10 | text-align: center; 11 | margin: 0 !important; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/Block.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Plugins; 14 | 15 | use Bugo\Compat\Utils; 16 | 17 | if (! defined('LP_NAME')) 18 | die('No direct access...'); 19 | 20 | abstract class Block extends Plugin 21 | { 22 | public string $type = 'block'; 23 | 24 | public function isInPlacements(int $id, array $placements): bool 25 | { 26 | $block = Utils::$context['lp_active_blocks'][$id] ?? Utils::$context['lp_block']; 27 | 28 | return in_array($block['placement'], $placements); 29 | } 30 | 31 | public function isInSidebar(int $id): bool 32 | { 33 | return $this->isInPlacements($id, ['left', 'right']); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/BlogMode/BlogArticle.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2024-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @category plugin 11 | * @version 13.11.24 12 | */ 13 | 14 | namespace Bugo\LightPortal\Plugins\BlogMode; 15 | 16 | use Bugo\LightPortal\Articles\PageArticle; 17 | 18 | if (! defined('LP_NAME')) 19 | die('No direct access...'); 20 | 21 | class BlogArticle extends PageArticle 22 | { 23 | public const TYPE = 'blog'; 24 | 25 | public function init(): void 26 | { 27 | parent::init(); 28 | 29 | $this->selectedCategories = []; 30 | 31 | $this->params['entry_type'] = self::TYPE; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/BlogMode/index.php: -------------------------------------------------------------------------------- 1 | 'Adds the ability to create personal blogs for portal users. Do not forget to assign appropriate permissions to member groups.', 5 | 'show_blogs_in_profiles' => 'Display users\' blogs in their profiles', 6 | 'permission' => 'Post blog entries', 7 | 'group_permission' => 'Who can post blog entries — Blogger', 8 | 'menu_item_title' => 'Blog', 9 | 'profile_title' => 'Blog %s', 10 | 'entries' => 'Blog entries', 11 | 'blog_action' => 'Blog action', 12 | 'blogged_status' => 'Blog entry', 13 | 'simple_status' => 'Simple page', 14 | ]; 15 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/BlogMode/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Board List', 5 | 'description' => 'Displays a list of boards that are available to the current user.', 6 | 'category_class' => 'CSS class of category titles', 7 | 'board_class' => 'CSS class of blocks with board lists', 8 | ]; 9 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/BoardList/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Board News', 5 | 'description' => 'Displays the latest posts from selected board.', 6 | 'board_id' => 'Board as source of news', 7 | 'num_posts' => 'Number of posts to display', 8 | 'teaser_length' => 'News teaser length', 9 | 'no_posts' => 'You cannot specify an empty board or board that doesn\'t allow guests', 10 | ]; 11 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/BoardNews/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Forum stats', 5 | 'description' => 'Displays basic forum statistics, as well as the number of online users.', 6 | 'show_latest_member' => 'Display the name of the last member', 7 | 'show_basic_info' => 'Display basic statistics', 8 | 'show_whos_online' => 'Display the "Now online" list', 9 | 'use_fa_icons' => 'Use Font Awesome icons', 10 | 'update_interval' => 'Data refresh interval, in seconds', 11 | 'newbie' => 'Newbie', 12 | 'online_today' => 'Online today', 13 | 'max_online' => 'Most max online', 14 | 'guests' => 'Guests', 15 | 'spiders' => 'Spiders', 16 | ]; 17 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/BoardStats/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Using Bootstrap Icons in the portal blocks\' titles.', 5 | ]; 6 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/BootstrapIcons/langs/index.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2023-2025 Bugo 8 | * @license https://opensource.org/licenses/MIT MIT 9 | * 10 | * @category plugin 11 | * @version 22.12.24 12 | */ 13 | 14 | namespace Bugo\LightPortal\Plugins\Calculator; 15 | 16 | use Bugo\LightPortal\Plugins\Block; 17 | use Bugo\LightPortal\Plugins\Event; 18 | 19 | if (! defined('LP_NAME')) 20 | die('No direct access...'); 21 | 22 | /** 23 | * Generated by PluginMaker 24 | */ 25 | class Calculator extends Block 26 | { 27 | public string $icon = 'fas fa-calculator'; 28 | 29 | public function prepareBlockParams(Event $e): void 30 | { 31 | $e->args->params['no_content_class'] = true; 32 | } 33 | 34 | public function prepareContent(Event $e): void 35 | { 36 | echo $this->getFromTemplate('show_calculator_block', $e->args->id); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/Calculator/index.php: -------------------------------------------------------------------------------- 1 | 'Calculator', 5 | 'description' => 'Adds a widget with a simple calculator in HTML, CSS, and JavaScript.', 6 | ]; 7 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/Calculator/langs/index.php: -------------------------------------------------------------------------------- 1 | * { 22 | position: relative; 23 | text-align: center; 24 | } 25 | 26 | > *:active::before, 27 | > .is-depressed::before { 28 | background-color: rgba(0, 0, 0, 0.2); 29 | bottom: 0; 30 | box-shadow: 0 0 6px 0 rgba(0, 0, 0, 0.5) inset; 31 | content: ""; 32 | left: 0; 33 | opacity: 0.3; 34 | position: absolute; 35 | right: 0; 36 | top: 0; 37 | z-index: 1; 38 | } 39 | } 40 | 41 | .key--equal { 42 | background-image: linear-gradient(to bottom, #fe886a, #ff7033); 43 | grid-column: -2; 44 | grid-row: 2 / span 4; 45 | } 46 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/CategoryList/index.php: -------------------------------------------------------------------------------- 1 | 'Portal categories', 5 | 'description' => 'Displays a category list of the portal.', 6 | 'no_items' => 'No category has been created yet', 7 | ]; 8 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/CategoryList/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Chart', 5 | 'description' => 'Chart.js provides a set of frequently used chart types.', 6 | 'chart_title' => 'Title of chart', 7 | 'chart_title_placeholder' => 'Text to display as a title of chart', 8 | 'datasets' => 'Datasets', 9 | 'datasets_placeholder' => 'Example: 1, 2, 3 (or as objects: {x: 1, y: 2}, {x: 3, y: 4})', 10 | 'set_label' => 'Label', 11 | 'background_color' => 'Background color', 12 | 'border_color' => 'Border color', 13 | 'border_width' => 'Border width', 14 | 'set_add' => 'Add set', 15 | 'labels' => 'Labels', 16 | 'labels_placeholder' => 'Example: Red, Orange, Green', 17 | 'default_palette' => 'Use default color palette', 18 | 'type' => 'Chart type', 19 | 'type_set' => ['Line chart', 'Bar chart', 'Pie chart', 'Doughnut chart', 'Polar area chart', 'Radar chart'], 20 | 'stacked' => 'Enable stacked bar charts', 21 | 'stacked_after' => 'Stacked bar charts can be used to show how one data series is made up of a number of smaller pieces.', 22 | 'horizontal' => 'Enable horizontal bar charts', 23 | ]; 24 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/Chart/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Chessboard', 5 | 'description' => 'Provides an opportunity to play chess with the computer.', 6 | 'search_depth' => 'Search depth', 7 | 'game_over' => 'Game over', 8 | ]; 9 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/ChessBoard/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Provides syntax highlighting when editing pages and blocks with various content.', 5 | 'modes' => 'Syntax Highlighting', 6 | 'small_hint' => 'Disable other editor plugins so that content blocks are not duplicated.', 7 | ]; 8 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/CodeMirror/langs/index.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Plugins; 14 | 15 | use Bugo\Compat\Utils; 16 | use Bugo\LightPortal\Repositories\PluginRepository; 17 | 18 | class ConfigHandler 19 | { 20 | private static array $settings; 21 | 22 | public function handle(string $snakeName): void 23 | { 24 | self::$settings ??= app(PluginRepository::class)->getSettings(); 25 | 26 | // @TODO These variables are still needed in some templates 27 | Utils::$context['lp_' . $snakeName . '_plugin'] = self::$settings[$snakeName] ?? []; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/CurrentMonth/index.php: -------------------------------------------------------------------------------- 1 | 'Current month', 5 | 'description' => 'Displays a widget with the current month.', 6 | ]; 7 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/CurrentMonth/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Widget for quick translation of forum pages', 5 | 'description' => 'Displays a modified version of the standard Yandex.Translate widget to translate forum pages into the selected language.', 6 | 'languages' => 'Supported languages', 7 | 'languages_select' => 'Select desired languages that will be available via this widget', 8 | 'languages_set' => ['Arabic', 'German', 'Greek', 'English', 'Esperanto', 'Spanish', 'French', 'Hindi', 'Italian', 'Dutch', 'Portuguese', 'Russian', 'Swedish', 'Turkish', 'Ukrainian', 'Chinese'], 9 | ]; 10 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/CustomTranslate/langs/index.php: -------------------------------------------------------------------------------- 1 | 12 | 13 | 16 |
'; 17 | 18 | foreach (Utils::$context['ctw_languages'] as $lang) { 19 | echo ' 20 | 21 |
22 |
'; 23 | } 24 | 25 | echo ' 26 |
27 | '; 28 | } 29 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/DiceBear/index.php: -------------------------------------------------------------------------------- 1 | 'With DiceBear you can provide your users with stunning random avatars in no time.', 5 | 'replace_missing_avatars' => 'Replace only missing avatars', 6 | 'source' => 'Data source for generation', 7 | 'source_set' => ['User name', 'User ID', 'User email'], 8 | 'style' => 'Style', 9 | 'size' => 'Default size', 10 | 'flip' => 'Flip right', 11 | ]; 12 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/DiceBear/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Adds the ability to display Disqus comments on portal pages.', 5 | 'shortname' => 'Website shortname', 6 | 'shortname_subtext' => 'This is used to uniquely identify your website on Disqus.
Copy your site shortname from the Disqus settings and paste here.', 7 | ]; 8 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/Disqus/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Allows you to quickly drag and drop blocks between panels without going into the admin area.', 5 | ]; 6 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/Dragula/langs/index.php: -------------------------------------------------------------------------------- 1 | 'The plugin generates fake cards on the frontpage, for testing templates.', 5 | 'use_lorem_ipsum' => 'Use Lorem Ipsum for cards', 6 | 'keywords' => 'Image keywords', 7 | ]; 8 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/DummyArticleCards/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Enables the EasyMDE editor to work with Markdown.', 5 | 'tasks' => 'Task list', 6 | 'lines' => 'lines: ', 7 | 'words' => 'words: ', 8 | 'toggle' => 'Toggle Side by Side', 9 | 'guide' => 'Markdown Guide', 10 | ]; 11 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/EasyMarkdownEditor/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Support for importing EhPortal/SimplePortal pages, categories, and custom blocks (if they exist in the database).', 5 | 'label_name' => 'Import from EhPortal', 6 | 'block_import_desc' => 'Import custom EhPortal/SimplePortal blocks (BBCode, HTML, PHP).', 7 | 'page_import_desc' => 'Import EhPortal/SimplePortal pages (if they exist in the database).', 8 | 'category_import_desc' => 'Import EhPortal/SimplePortal categories (if they exist in the database).', 9 | ]; 10 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/EhPortalMigration/langs/index.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Plugins; 14 | 15 | use Doctrine\Common\EventArgs; 16 | 17 | class Event extends EventArgs 18 | { 19 | public function __construct(public object $args) {} 20 | } 21 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/Events/index.php: -------------------------------------------------------------------------------- 1 | 'Events', 5 | 'description' => 'Displays calendar summary such as birthdays, holidays and events.', 6 | 'days_in_future' => 'Number of days in future to show events', 7 | 'update_interval' => 'Data refresh interval, in seconds', 8 | ]; 9 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/Events/langs/index.php: -------------------------------------------------------------------------------- 1 | div:last-child { 3 | display: grid; 4 | grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); 5 | grid-gap: 0 10px; 6 | 7 | @media screen and (max-width: 768px) { 8 | & { 9 | display: block; 10 | } 11 | } 12 | } 13 | 14 | .fa-calendar { 15 | color: forestgreen; 16 | } 17 | 18 | .fa-cake-candles { 19 | color: salmon; 20 | } 21 | 22 | .fa-calendar-days { 23 | color: rgb(59, 91, 152); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/ExtendedMetaTags/index.php: -------------------------------------------------------------------------------- 1 | 'Adds additional meta tags for portal pages.', 5 | 'meta_robots' => 'Robots (bot behavior management)', 6 | 'meta_robots_set' => ['No', 'index, follow', 'index, nofollow', 'noindex, follow', 'noindex, nofollow'], 7 | 'meta_rating' => 'Age rating', 8 | 'meta_rating_set' => ['No', '14-year-old audience', 'adults (18+)', 'general category', 'mature (17+)', 'restricted', 'safe for kids'], 9 | ]; 10 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/ExtendedMetaTags/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Support for importing ezPortal pages and custom blocks (if they exist in the database).', 5 | 'label_name' => 'Import from ezPortal', 6 | 'block_import_desc' => 'Import custom ezPortal blocks (HTML, PHP).', 7 | 'page_import_desc' => 'Import ezPortal pages (if they exist in the database).', 8 | ]; 9 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/EzPortalMigration/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Displays FA Board Icons for boards in the article mode on the frontpage.', 5 | ]; 6 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/FaBoardIcons/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Adds the ability to display Facebook comments on portal pages.', 5 | 'app_id' => 'Facebook Application ID', 6 | 'app_id_subtext' => 'Get Application ID', 7 | 'comments_per_page' => 'Number of comments per page', 8 | 'comment_order_by' => 'Comments sorting', 9 | 'comment_order_by_set' => ['The newest at the top', 'The oldest at the top'], 10 | 'dark_themes' => 'Select themes for which the color scheme of the widget should be dark', 11 | ]; 12 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/FacebookComments/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Images from SMF Gallery', 5 | 'description' => 'Displays images from selected SMF Gallery categories.', 6 | 'categories' => 'Image categories', 7 | 'categories_select' => 'If you do not need all the images, but only from certain categories', 8 | 'num_images' => 'Number of images to display', 9 | 'num_images_subtext' => 'Set to 0 to disable the limit', 10 | 'no_items' => 'There are no images in the selected categories.', 11 | ]; 12 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/GalleryBlock/langs/index.php: -------------------------------------------------------------------------------- 1 | 'A comments system powered by GitHub Discussions. Let visitors leave comments and reactions on your website via GitHub!', 5 | 'repo' => 'GitHub Repository', 6 | 'repo_subtext' => 'Take from the data-repo field of the proposed config', 7 | 'repo_id' => 'Repository ID', 8 | 'repo_id_subtext' => 'Take from the data-repo-id field of the proposed config', 9 | 'category' => 'Discussion Category', 10 | 'category_subtext' => 'Take from the data-category field of the proposed config', 11 | 'category_id' => 'Category ID', 12 | 'category_id_subtext' => 'Take from the data-category-id field of the proposed config', 13 | 'theme' => 'Theme', 14 | ]; 15 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/Giscus/langs/index.php: -------------------------------------------------------------------------------- 1 | 9 | 12 | '; 13 | } 14 | 15 | function template_tour_info_below() 16 | { 17 | } 18 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/HidingBlocks/index.php: -------------------------------------------------------------------------------- 1 | 'Allows to hide any block depending on the screen width.', 5 | 'hidden_breakpoints' => 'Hide the block on screens with the specified width', 6 | 'hidden_breakpoints_set' => ['less than 576px', 'from 576 to 768px', 'from 768 to 992px', 'from 992 to 1200px', 'more than 1200px'], 7 | 'hidden_breakpoints_subtext' => 'If no element is selected, there are no restrictions' 8 | ]; 9 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/HidingBlocks/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Notify supported search engines about changes of the portal pages.', 5 | 'user_key' => 'User Verification Key', 6 | ]; 7 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/IndexNow/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Enables the Jodit visual editor for working with HTML content.', 5 | 'dark_themes' => 'Select themes for which the editor appearance should be dark', 6 | 'icon_size' => 'Size of icons in the toolbar', 7 | 'icon_size_set' => ['small' => 'Small', 'middle' => 'Middle', 'large' => 'Large'], 8 | 'enter_element' => 'Element that will be created when you press Enter', 9 | 'enter_element_set' => ['p' => 'Paragraph (P)', 'div' => 'Block (DIV)', 'br' => 'Break (BR)'], 10 | 'default_mode' => 'Default mode', 11 | 'default_mode_set' => [1 => 'WYSIWYG', 'Source code', 'Split code'], 12 | 'autofocus' => 'Autofocus on page loading', 13 | 'insert_image_base64' => 'Insert image as Base64 URI', 14 | ]; 15 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/Jodit/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Allows you to display a specific block depending on the user\'s language.', 5 | 'allowed_languages' => 'Display a block if the user\'s current language is', 6 | 'allowed_languages_subtext' => 'If no language is selected, there are no restrictions' 7 | ]; 8 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/LanguageAccess/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Provides the ability to use Latte markup in your own frontpage layouts.', 5 | 'note' => 'To add your template, create a file with the extension %s in the %s directory', 6 | 'example' => 'Example markup', 7 | ]; 8 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/LatteLayouts/langs/index.php: -------------------------------------------------------------------------------- 1 | 8 | {/if} 9 | 10 |
11 | {do show_pagination()} 12 | 13 |
17 |
18 | {php echo parse_bbc('[code]' . print_r($article, true) . '[/code]')} 19 |
20 |
21 | 22 | {do show_pagination(bottom)} 23 |
24 | 25 | {if $no_blocks} 26 | 27 | {/if} -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/LatteLayouts/layouts/index.php: -------------------------------------------------------------------------------- 1 | 8 | {/if} 9 | 10 |
11 | {do show_pagination()} 12 | 13 |
14 |
15 |
16 | {$article[title]} 17 | 18 |
19 | 22 |
23 | 24 | {do show_pagination(bottom)} 25 |
26 | 27 | {if $no_blocks} 28 | 29 | {/if} -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/LatteLayouts/layouts/simple3.latte: -------------------------------------------------------------------------------- 1 | {varType array $context} 2 | 3 | {if empty($context[lp_active_blocks])} 4 |
5 | {/if} 6 | 7 | {do show_pagination()} 8 | 9 |
10 |
11 | {$article[title]} 12 |
13 |
{$article[title]}
14 |

{teaser($article[teaser])}

15 |
16 |
17 | #{$key[name]} 18 |
19 |
20 |
21 | 22 | {do show_pagination(bottom)} 23 | 24 | {if empty($context[lp_active_blocks])} 25 |
26 | {/if} -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/Likely/index.php: -------------------------------------------------------------------------------- 1 | 'Likely', 5 | 'description' => 'Displays selected social sharing buttons.', 6 | 'size' => 'Button size', 7 | 'size_set' => [ 8 | 'small' => 'Small', 9 | 'big' => 'Big' 10 | ], 11 | 'dark_mode' => 'Use buttons for dark mode', 12 | 'buttons' => 'Displayed buttons', 13 | 'select_buttons' => 'Select social buttons to display', 14 | 'buttons_set' => [ 15 | 'facebook' => 'Share', 16 | 'twitter' => 'Tweet', 17 | 'vkontakte' => 'Share', 18 | 'pinterest' => 'Pin', 19 | 'odnoklassniki' => 'Like', 20 | 'telegram' => 'Send', 21 | 'linkedin' => 'Share', 22 | 'whatsapp' => 'Send', 23 | 'viber' => 'Send', 24 | 'reddit' => 'Share', 25 | ], 26 | ]; 27 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/Likely/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Using Line Awesome icons by Icons8 in the portal blocks\' titles.', 5 | ]; 6 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/LineAwesomeIcons/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Using standard SMF icons in the portal blocks\' titles.', 5 | ]; 6 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/MainIcons/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Provides the ability to override the labels of the "Portal" and "Forum" items.', 5 | 'menu_item' => 'Name of item', 6 | ]; 7 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/MainMenu/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Custom Markdown', 5 | 'description' => 'Adds the ability to use Markdown content in articles and portal blocks.', 6 | 'block_desc' => 'Here you can use basic Markdown syntax as content.', 7 | ]; 8 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/Markdown/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Using Material Design Icons in the portal blocks\' titles.', 5 | ]; 6 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/MaterialDesignIcons/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Block with media links', 5 | 'description' => 'Converts links from popular media sites to auto-embed videos.', 6 | 'urls' => 'URLs', 7 | 'title_placeholder' => 'Title (will be displayed below the video)', 8 | 'link_placeholder' => 'Link to video', 9 | 'url_add' => 'Add URL', 10 | ]; 11 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/MediaBlock/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Forum News', 5 | 'description' => 'Displays one of the forum\'s news items.', 6 | 'selected_item' => 'What to display', 7 | 'random_news' => 'The random news', 8 | 'no_items' => 'No news yet.' 9 | ]; 10 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/News/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Displays the descriptions and keywords of the Optimus for topics in the articles mode on the frontpage.', 5 | 'use_topic_descriptions' => 'Use topic descriptions as article teasers on the portal frontpage', 6 | 'show_topic_keywords' => 'Show topic keywords on the portal frontpage', 7 | ]; 8 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/Optimus/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Page List', 5 | 'description' => 'Displays a list of active portal pages.', 6 | 'categories_select' => 'If you do not need all the pages, but only from certain categories', 7 | 'sort' => 'Page sorting', 8 | 'sort_set' => ['By ID', 'By author', 'By title', 'By slug', 'By type', 'By number views', 'By date of creation', 'By date of updating'], 9 | 'num_pages' => 'Number of pages to display', 10 | 'num_pages_subtext' => 'Set 0 to show all pages', 11 | 'no_items' => 'There are no available pages.' 12 | ]; 13 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/PageList/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Adds buttons to move up/down the page.', 5 | 'button_up' => 'The "Up" Button (Unicode)', 6 | 'button_down' => 'The "Down" Button (Unicode)', 7 | 'button_color' => 'Button color', 8 | 'arrow_color' => 'Arrow color', 9 | 'placement' => 'Button layout', 10 | 'placement_set' => ['Lower left corner', 'Lower right corner'], 11 | 'hide_on_mobile' => 'Hide on mobile screens', 12 | ]; 13 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/PageScroll/langs/index.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Plugins; 14 | 15 | interface PluginInterface 16 | { 17 | public function getCamelName(): string; 18 | 19 | public function getSnakeName(): string; 20 | } 21 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/PluginMaker/License.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2021-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @category plugin 11 | * @version 09.01.25 12 | */ 13 | 14 | namespace Bugo\LightPortal\Plugins\PluginMaker; 15 | 16 | enum License: string 17 | { 18 | case MIT = 'mit'; 19 | case BSD = 'bsd'; 20 | case GPL = 'gpl'; 21 | 22 | public function getName(): string 23 | { 24 | return match ($this) { 25 | self::MIT => 'MIT', 26 | self::BSD => 'BSD-3-Clause', 27 | self::GPL => 'GPL-3.0-or-later', 28 | }; 29 | } 30 | 31 | public function getLink(): string 32 | { 33 | return match ($this) { 34 | self::MIT => 'https://opensource.org/licenses/MIT', 35 | self::BSD => 'https://opensource.org/licenses/BSD-3-Clause', 36 | self::GPL => 'https://spdx.org/licenses/GPL-3.0-or-later.html', 37 | }; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/PluginMaker/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "nette/php-generator": "^4.1" 4 | }, 5 | "config": { 6 | "optimize-autoloader": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/PluginMaker/index.php: -------------------------------------------------------------------------------- 1 | 'Forum polls', 5 | 'description' => 'Displays a selected poll.', 6 | 'selected_item' => 'Select a poll', 7 | 'no_items' => 'No polls yet.', 8 | ]; 9 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/Polls/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Provides support for the portal action and pages urls like your_forum/page/slug with the PrettyUrls mod.' 5 | ]; 6 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/PrettyUrls/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Random Pages', 5 | 'description' => 'Displays a list of random pages of the portal.', 6 | 'exclude_categories' => 'Exclude categories', 7 | 'exclude_categories_select' => 'Select the categories from which pages will NOT be displayed.', 8 | 'include_categories' => 'Include categories', 9 | 'include_categories_select' => 'Pages will be displayed ONLY from the selected categories.', 10 | 'num_pages' => 'Number of pages to display', 11 | 'show_num_views' => 'Show number of views', 12 | 'none' => 'There are no random pages', 13 | ]; 14 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/RandomPages/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Random Topics', 5 | 'description' => 'Displays a list of random topics of the forum.', 6 | 'exclude_boards' => 'Exclude boards', 7 | 'exclude_boards_select' => 'Select the boards from which topics will NOT be displayed.', 8 | 'include_boards' => 'Include boards', 9 | 'include_boards_select' => 'Topics will be displayed ONLY from the selected boards.', 10 | 'num_topics' => 'Number of topics to display', 11 | 'show_num_views' => 'Show number of views', 12 | 'none' => 'There are no random topics', 13 | ]; 14 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/RandomTopics/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Adds reactions for pages and comments.', 5 | 'allow_reactions' => 'Allow reactions', 6 | 'titles' => ['Like', 'Dislike', 'Love', 'Laugh', 'Sad', 'Angry'], 7 | 'react' => 'React', 8 | ]; 9 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/Reactions/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Recent Attachments', 5 | 'description' => 'Displays the recent attachments that the user can see.', 6 | 'num_attachments' => 'Number of attachments to display', 7 | 'extensions' => 'The extensions of attachments that you want to display', 8 | 'extensions_subtext' => 'Enter the required extensions, separated by commas. For example: jpg,png', 9 | ]; 10 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/RecentAttachments/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Recent Comments', 5 | 'description' => 'Displays a list of recent comments of the portal pages.', 6 | 'num_comments' => 'Number of comments to display', 7 | 'length' => 'Teaser length', 8 | ]; 9 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/RecentComments/langs/index.php: -------------------------------------------------------------------------------- 1 | div { 26 | display: flex; 27 | flex-direction: column; 28 | justify-content: space-between; 29 | text-align: center; 30 | margin: 0 !important; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/RecentTopics/index.php: -------------------------------------------------------------------------------- 1 | 'Recent Topics', 5 | 'description' => 'Displays a list of recent forum topics.', 6 | 'exclude_boards' => 'Exclude boards', 7 | 'exclude_boards_select' => 'Select the boards from which topics will NOT be displayed.', 8 | 'include_boards' => 'Include boards', 9 | 'include_boards_select' => 'Topics will be displayed ONLY from the selected boards.', 10 | 'use_simple_style' => 'Use a simple design style', 11 | 'use_simple_style_subtext' => 'Disables avatars and icons.', 12 | 'show_avatars' => 'Show user avatars', 13 | 'show_icons' => 'Show topic icons', 14 | 'num_topics' => 'Number of topics to display', 15 | 'type' => 'What to display as a link to a post', 16 | 'type_set' => ['Message subject', 'Message preview'], 17 | 'update_interval' => 'List refresh interval, in seconds', 18 | ]; 19 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/RecentTopics/langs/index.php: -------------------------------------------------------------------------------- 1 | div { 26 | display: flex; 27 | flex-direction: column; 28 | justify-content: space-between; 29 | text-align: center; 30 | margin: 0 !important; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/Search/index.php: -------------------------------------------------------------------------------- 1 | 'Search in pages', 5 | 'description' => 'Displays the search field for the content of portal pages.', 6 | 'min_chars' => 'Minimum number of characters (>= 1) a user must type before a search is performed', 7 | ]; 8 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/Search/langs/index.php: -------------------------------------------------------------------------------- 1 | 10 |

', Lang::$txt['search_results'], '

11 | '; 12 | 13 | if (empty(Utils::$context['search_results'])) { 14 | echo ' 15 |
', Lang::$txt['search_no_results'], '
'; 16 | } 17 | 18 | foreach (Utils::$context['search_results'] as $i => $result) { 19 | echo ' 20 |
21 |
22 | 23 |
', ++$i, '
24 |
25 | ', $result['title'], ' 26 |
27 |  ', Lang::$txt['by'], ' ', $result['author'], '  ', $result['date'], '  28 |
29 |
30 |
', $result['content'], '
31 |
'; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/SimpleChat/index.php: -------------------------------------------------------------------------------- 1 | 'Simple Chat', 5 | 'description' => 'Displays a simple form to communicate with other users in real time.', 6 | 'show_avatars' => 'Show user avatars', 7 | 'form_position' => 'Position of the input form', 8 | 'form_position_set' => ['At the bottom', 'At the top'], 9 | 'window_height' => 'Chat window height (px)', 10 | 'login' => 'Log in to participate in the discussion', 11 | ]; 12 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/SimpleChat/langs/index.php: -------------------------------------------------------------------------------- 1 | 'RSS Feed', 5 | 'description' => 'Displays the RSS feed from the specified URL.', 6 | 'url' => 'RSS feed URL', 7 | 'show_text' => 'Show text', 8 | ]; 9 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/SimpleFeeder/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Simple menu', 5 | 'description' => 'Displays a simple menu of the specified items.', 6 | 'items' => 'Menu items', 7 | 'name_placeholder' => 'Item name', 8 | 'link_placeholder' => 'Item link or forum action', 9 | 'item_add' => 'Add new item', 10 | ]; 11 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/SimpleMenu/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Displays a custom site list on the frontpage.', 5 | 'caution' => 'the added sites will be displayed INSTEAD of portal articles on the frontpage!', 6 | 'image' => 'Link to screenshot', 7 | 'add' => 'Add site', 8 | ]; 9 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/SiteList/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Adds a New Year mood to the site, more specifically snowfall, snowdrifts and a car that clears them regularly!', 5 | 'icon_color' => 'Snowflake color', 6 | 'icon_size' => 'Snowflake size', 7 | 'snowflakes_count' => 'Number of snowflakes', 8 | 'enable_snowdrifts' => 'Enable snowdrifts', 9 | 'snowdrifts_count' => 'Number of snowdrifts', 10 | ]; 11 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/Snowflakes/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Swiper slider', 5 | 'block_desc' => 'Mobile touch slider to display added images.', 6 | 'description' => 'It provides a block with the free and most modern mobile touch slider with hardware accelerated transitions and amazing native behavior.', 7 | 'direction' => 'Direction of slide movement', 8 | 'effect' => 'Transition effect', 9 | 'slides_per_view' => 'Number of slides per view', 10 | 'loop' => 'Move throughout all the slides seamlessly', 11 | 'show_pagination' => 'Show pagination', 12 | 'show_navigation' => 'Show navigation buttons', 13 | 'show_scrollbar' => 'Show scrollbar', 14 | 'images' => 'Image list', 15 | 'title_placeholder' => 'Title (optional)', 16 | 'link_placeholder' => 'Image link', 17 | 'image_add' => 'Add new image', 18 | ]; 19 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/Swiper/langs/index.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2020-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @category plugin 11 | * @version 12.02.25 12 | */ 13 | 14 | namespace Bugo\LightPortal\Plugins\TagList; 15 | 16 | use Laminas\ServiceManager\ServiceManager; 17 | use Laminas\Tag\Cloud; 18 | 19 | class TagCloud extends Cloud 20 | { 21 | public function __construct($options = null) 22 | { 23 | parent::__construct($options); 24 | 25 | $this->decorators = new DecoratorPluginManager(new ServiceManager()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/TagList/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "laminas/laminas-tag": "^2.11", 4 | "laminas/laminas-servicemanager": "^4.4.0" 5 | }, 6 | "config": { 7 | "optimize-autoloader": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/TagList/index.php: -------------------------------------------------------------------------------- 1 | 'Tag List', 5 | 'description' => 'Displays a list of tags of the portal pages (or forum topics, if the Optimus is installed).', 6 | 'source' => 'Tag source', 7 | 'source_set' => ['Portal page tags', 'Topic keywords'], 8 | 'sorting' => 'Tag sorting', 9 | 'sorting_set' => ['By name', 'By frequency'], 10 | 'as_cloud' => 'Display tags as a cloud', 11 | ]; 12 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/TagList/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Theme Switcher', 5 | 'description' => 'Displays a list of themes that are available to quick selecting.', 6 | ]; 7 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/ThemeSwitcher/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Enables a fully-featured, sleek and intuitive rich text editor to work with HTML content.', 5 | 'favorites' => 'Favorites', 6 | 'api_key' => 'API Key', 7 | 'api_key_subtext' => 'Get your API Key', 8 | 'dark_themes' => 'Select themes for which the editor appearance should be dark', 9 | ]; 10 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/TinyMCE/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Support for importing TinyPortal pages, categories, and custom blocks (if they exist in the database).', 5 | 'label_name' => 'Import from TinyPortal', 6 | 'block_import_desc' => 'Import custom TinyPortal blocks (BBCode, HTML, PHP).', 7 | 'page_import_desc' => 'Import TinyPortal pages (if they exist in the database).', 8 | 'category_import_desc' => 'Import TinyPortal categories (if they exist in the database).', 9 | ]; 10 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/TinyPortalMigration/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Top Boards', 5 | 'description' => 'Displays a list of popular boards.', 6 | 'num_boards' => 'Number of boards to display', 7 | 'entity_type' => 'What to display in bars', 8 | 'entity_type_set' => ['A number of topics', 'A number of posts'], 9 | 'show_numbers_only' => 'Only display numbers', 10 | 'topics' => '{topics, plural, one {# topic} other {# topics}}', 11 | 'posts' => '{posts, plural, one {# post} other {# posts}}' 12 | ]; 13 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/TopBoards/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Top Pages', 5 | 'description' => 'Displays a list of popular portal pages.', 6 | 'type' => 'Calculation of the popularity', 7 | 'type_set' => ['By comments', 'By views'], 8 | 'num_pages' => 'Number of pages to display', 9 | 'show_numbers_only' => 'Display numbers only', 10 | 'no_items' => 'There are no popular pages.', 11 | ]; 12 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/TopPages/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Top Posters', 5 | 'description' => 'Displays a list of top posters.', 6 | 'show_avatars' => 'Display user avatars', 7 | 'num_posters' => 'Number of posters to display', 8 | 'show_numbers_only' => 'Display numbers only', 9 | 'posts' => '{posts, plural, one {# post} other {# posts}}', 10 | 'none' => 'No members with posts', 11 | ]; 12 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/TopPosters/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Top Topics', 5 | 'description' => 'Displays a list of popular topics.', 6 | 'type' => 'Calculation of the popularity', 7 | 'type_set' => ['By replies', 'By views'], 8 | 'num_topics' => 'Number of topics to display', 9 | 'show_numbers_only' => 'Display numbers only', 10 | ]; 11 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/TopTopics/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Enables support for Topic Rating Bar mod, displaying the rating for topics in the articles mode on the frontpage.', 5 | ]; 6 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/TopicRatingBar/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Translator widget', 5 | 'description' => 'Displays the button for translating the current page to the selected language.', 6 | 'engine' => 'Used engine', 7 | 'engine_set' => ['Google.Translator', 'Yandex.Translator'], 8 | 'widget_theme' => 'Widget theme', 9 | 'widget_theme_set' => ['Light', 'Dark'], 10 | 'auto_mode' => 'Automatic translation', 11 | ]; 12 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/Translator/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Trending Topics', 5 | 'description' => 'Displays the most trending forum topics for a specified period of time.', 6 | 'show_avatars' => 'Show user avatars', 7 | 'time_period' => 'Time period (to determine the frequency of replies)', 8 | 'time_period_set' => ['Day', 'Week', '2 weeks', 'Month', '2 months', '4 months', '6 months', '8 months', 'Year'], 9 | 'min_replies' => 'Minimum number of replies for the specified period', 10 | 'num_topics' => 'Number of topics to display', 11 | 'none' => 'There are no trending topics', 12 | ]; 13 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/TrendingTopics/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Twenty Forty Eight', 5 | 'description' => 'A simple implementation of the popular game 2048.', 6 | ]; 7 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/TwentyFortyEight/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Provides the ability to use Twig markup in your own frontpage layouts.', 5 | 'note' => 'To add your template, create a file with the extension %s in the %s directory', 6 | 'example' => 'Example markup', 7 | ]; 8 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/TwigLayouts/langs/index.php: -------------------------------------------------------------------------------- 1 | 3 | {% endif %} 4 | {# {{ debug(context.user) }} #} 5 | 6 |
7 | {{ show_pagination() }} 8 | 9 | {% for article in context.lp_frontpage_articles %} 10 |
11 |
{{ debug(article) }}
12 |
13 | {% endfor %} 14 | 15 | {{ show_pagination('bottom') }} 16 |
17 | 18 | {% if not context.lp_active_blocks %} 19 | 20 | {% endif %} -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/TwigLayouts/layouts/index.php: -------------------------------------------------------------------------------- 1 | 'Using Uicons by Flaticon in the portal blocks\' titles.', 5 | 'weight' => 'Icon Style', 6 | 'weight_set' => ['Regular', 'Bold', 'Solid'], 7 | 'corner' => 'Corners', 8 | 'corner_set' => ['Rounded', 'Straight'], 9 | ]; 10 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/Uicons/langs/index.php: -------------------------------------------------------------------------------- 1 | 'User Info', 5 | 'description' => 'Displays a info about the current user.', 6 | ]; 7 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/UserInfo/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Adds the ability to display VK comments on portal pages.', 5 | 'api_id' => 'VK API ID', 6 | 'api_id_subtext' => 'Create application and copy its ID (apiId), to enter here.', 7 | 'comments_per_page' => 'Number of comments per page', 8 | 'allow_attachments' => 'Allow attachments', 9 | 'auto_publish' => 'Post comments on VK user\'s page', 10 | ]; 11 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/VkComments/langs/index.php: -------------------------------------------------------------------------------- 1 | 'Who is online', 5 | 'description' => 'Displays a list of online users.', 6 | 'show_group_key' => 'Show user group titles', 7 | 'show_avatars' => 'Show user avatars', 8 | 'update_interval' => 'List refresh interval, in seconds', 9 | ]; 10 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Plugins/WhosOnline/langs/index.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal; 14 | 15 | use Bugo\LightPortal\Areas\ConfigArea; 16 | use Bugo\LightPortal\Areas\CreditArea; 17 | 18 | if (! defined('SMF')) 19 | die('No direct access...'); 20 | 21 | final class PortalApp 22 | { 23 | public function __construct() 24 | { 25 | if (SMF === 'BACKGROUND') 26 | return; 27 | 28 | app(Integration::class)(); 29 | app(ConfigArea::class)(); 30 | app(CreditArea::class)(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Renderers/RendererInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Renderers; 14 | 15 | interface RendererInterface 16 | { 17 | public function getLayouts(): array; 18 | 19 | public function render(string $layout, array $params = []): string; 20 | } 21 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Renderers/index.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Routes; 14 | 15 | use Bugo\Compat\Routable; 16 | 17 | use function array_shift; 18 | 19 | class Forum implements Routable 20 | { 21 | public static function buildRoute(array $params): array 22 | { 23 | $route[] = $params['action']; 24 | 25 | unset($params['action']); 26 | 27 | return ['route' => $route, 'params' => $params]; 28 | } 29 | 30 | public static function parseRoute(array $route, array $params = []): array 31 | { 32 | $params['action'] = array_shift($route); 33 | 34 | return $params; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Routes/index.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\UI\Fields; 14 | 15 | if (! defined('SMF')) 16 | die('No direct access...'); 17 | 18 | class ColorField extends InputField 19 | { 20 | public function __construct(string $name, string $label) 21 | { 22 | parent::__construct($name, $label); 23 | 24 | $this->setType('color'); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/UI/Fields/InputField.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\UI\Fields; 14 | 15 | if (! defined('SMF')) 16 | die('No direct access...'); 17 | 18 | class InputField extends AbstractField 19 | { 20 | public function __construct(string $name, string $label) 21 | { 22 | parent::__construct($name, $label); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/UI/Fields/NumberField.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\UI\Fields; 14 | 15 | if (! defined('SMF')) 16 | die('No direct access...'); 17 | 18 | class NumberField extends InputField 19 | { 20 | public function __construct(string $name, string $label) 21 | { 22 | parent::__construct($name, $label); 23 | 24 | $this 25 | ->setType('number') 26 | ->setAttribute('id', $name); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/UI/Fields/TextField.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\UI\Fields; 14 | 15 | if (! defined('SMF')) 16 | die('No direct access...'); 17 | 18 | class TextField extends InputField 19 | { 20 | public function __construct(string $name, string $label) 21 | { 22 | parent::__construct($name, $label); 23 | 24 | $this->setType('text'); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/UI/Fields/TextareaField.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\UI\Fields; 14 | 15 | if (! defined('SMF')) 16 | die('No direct access...'); 17 | 18 | class TextareaField extends AbstractField 19 | { 20 | public function __construct(string $name, string $label) 21 | { 22 | parent::__construct($name, $label); 23 | 24 | $this->setType('textarea'); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/UI/Fields/UrlField.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\UI\Fields; 14 | 15 | if (! defined('SMF')) 16 | die('No direct access...'); 17 | 18 | class UrlField extends TextField 19 | { 20 | public function __construct(string $name, string $label) 21 | { 22 | parent::__construct($name, $label); 23 | 24 | $this->setType('url'); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/UI/Fields/VirtualSelectField.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\UI\Fields; 14 | 15 | use Bugo\Compat\Theme; 16 | use Bugo\Compat\Utils; 17 | 18 | if (! defined('SMF')) 19 | die('No direct access...'); 20 | 21 | class VirtualSelectField extends SelectField 22 | { 23 | public function __construct(string $name, string $label) 24 | { 25 | parent::__construct($name, $label); 26 | 27 | Theme::addInlineJavaScript(' 28 | VirtualSelect.init({ 29 | ele: "#' . $name . '", 30 | hideClearButton: true,' . (Utils::$context['right_to_left'] ? ' 31 | textDirection: "rtl",' : '') . ' 32 | dropboxWrapper: "body" 33 | });', true); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/UI/Fields/index.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\UI\Partials; 14 | 15 | use Stringable; 16 | 17 | if (! defined('SMF')) 18 | die('No direct access...'); 19 | 20 | abstract class AbstractPartial implements Stringable 21 | { 22 | abstract public function __invoke(): string; 23 | 24 | public function __toString(): string 25 | { 26 | return static::__invoke(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/UI/Partials/index.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\UI\Tables; 14 | 15 | use Bugo\LightPortal\Utils\Str; 16 | 17 | class Button 18 | { 19 | public function __construct( 20 | private readonly string $name, 21 | private readonly string $value, 22 | private readonly string $class = 'button' 23 | ) {} 24 | 25 | public static function make(string $name, string $value, string $class = 'button'): string 26 | { 27 | $button = new self($name, $value, $class); 28 | 29 | return $button->render(); 30 | } 31 | 32 | public function render(): string 33 | { 34 | return Str::html('input', [ 35 | 'type' => 'submit', 36 | 'name' => $this->name, 37 | 'value' => $this->value, 38 | 'class' => $this->class, 39 | ])->toHtml(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/UI/Tables/CheckboxColumn.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\UI\Tables; 14 | 15 | use Bugo\Bricks\Tables\Column; 16 | use Bugo\LightPortal\Utils\Str; 17 | 18 | class CheckboxColumn extends Column 19 | { 20 | public static function make(string $name = 'actions', string $title = '', ?string $entity = null): static 21 | { 22 | return parent::make($name, $title ?: Str::html('input', [ 23 | 'type' => 'checkbox', 24 | 'onclick' => 'invertAll(this, this.form);', 25 | ])->toHtml()) 26 | ->setStyle('width: 5%') 27 | ->setData(static fn($entry) => Str::html('input', [ 28 | 'type' => 'checkbox', 29 | 'value' => $entry['id'], 30 | 'name' => $entity . '[]', 31 | ]), 'centertext'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/UI/Tables/ExportButtonsRow.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\UI\Tables; 14 | 15 | use Bugo\Bricks\Tables\Row; 16 | use Bugo\Compat\Lang; 17 | 18 | class ExportButtonsRow extends Row 19 | { 20 | public static function make(string $value = '', ?string $class = null): static 21 | { 22 | return parent::make($value ?: implode('', [ 23 | HiddenInput::make(), 24 | Button::make('export_selection', Lang::$txt['lp_export_selection']), 25 | Button::make('export_all', Lang::$txt['lp_export_all']), 26 | ]), $class ?? ''); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/UI/Tables/HiddenInput.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\UI\Tables; 14 | 15 | use Bugo\LightPortal\Utils\Str; 16 | 17 | class HiddenInput 18 | { 19 | public static function make(): string 20 | { 21 | $button = new self(); 22 | 23 | return $button->render(); 24 | } 25 | 26 | public function render(): string 27 | { 28 | return Str::html('input', [ 29 | 'type' => 'hidden', 30 | ])->toHtml(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/UI/Tables/IconColumn.php: -------------------------------------------------------------------------------- 1 | setData('icon', 'centertext'); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/UI/Tables/ImportButtonsRow.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\UI\Tables; 14 | 15 | use Bugo\Bricks\Tables\Row; 16 | use Bugo\Compat\Lang; 17 | 18 | class ImportButtonsRow extends Row 19 | { 20 | public static function make(string $value = '', ?string $class = null): static 21 | { 22 | return parent::make($value ?: implode('', [ 23 | HiddenInput::make(), 24 | Button::make('import_selection', Lang::$txt['lp_import_selection']), 25 | Button::make('import_all', Lang::$txt['lp_import_all']), 26 | ]), $class ?? ''); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/UI/Tables/NumViewsColumn.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\UI\Tables; 14 | 15 | use Bugo\Bricks\Tables\Column; 16 | use Bugo\Compat\Lang; 17 | use Bugo\LightPortal\Utils\Icon; 18 | 19 | class NumViewsColumn extends Column 20 | { 21 | public static function make(string $name = 'num_views', string $title = ''): static 22 | { 23 | return parent::make($name, $title ?: Icon::get('views', Lang::$txt['lp_views'])) 24 | ->setData('num_views', 'centertext') 25 | ->setSort('p.num_views DESC', 'p.num_views'); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/UI/Tables/PageSlugColumn.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\UI\Tables; 14 | 15 | use Bugo\Bricks\Tables\Column; 16 | use Bugo\Compat\Lang; 17 | 18 | class PageSlugColumn extends Column 19 | { 20 | public static function make(string $name = 'slug', string $title = ''): static 21 | { 22 | return parent::make($name, $title ?: Lang::$txt['lp_page_slug']) 23 | ->setData('slug', 'centertext') 24 | ->setSort('p.slug DESC', 'p.slug'); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/UI/Tables/PortalTableBuilderInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\UI\Tables; 14 | 15 | use Bugo\Bricks\Tables\Interfaces\TableBuilderInterface; 16 | 17 | interface PortalTableBuilderInterface extends TableBuilderInterface 18 | { 19 | public function withCreateButton(string $entity, string $title = ''): self; 20 | } 21 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/UI/Tables/TableRenderer.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\UI\Tables; 14 | 15 | use Bugo\Bricks\Renderers\RendererInterface; 16 | use Bugo\Compat\ItemList; 17 | use Bugo\Compat\Utils; 18 | 19 | class TableRenderer implements RendererInterface 20 | { 21 | public function render(array $data): void 22 | { 23 | new ItemList($data); 24 | 25 | Utils::$context['sub_template'] = 'show_list'; 26 | Utils::$context['default_list'] = $data['id']; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/UI/Tables/TitleColumn.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\UI\Tables; 14 | 15 | use Bugo\Bricks\Tables\Column; 16 | use Bugo\Compat\Lang; 17 | use Bugo\LightPortal\Utils\Str; 18 | 19 | class TitleColumn extends Column 20 | { 21 | public static function make(string $name = 'title', string $title = '', ?string $entity = null): static 22 | { 23 | return parent::make($name, $title ?: Lang::$txt['lp_title']) 24 | ->setData(static fn($entry) => $entry['status'] 25 | ? Str::html('a', ['class' => 'bbc_link']) 26 | ->href(LP_BASE_URL . ";sa=$entity;id=" . $entry['id']) 27 | ->setText($entry['title']) 28 | : $entry['title'], 'word_break') 29 | ->setSort('t.value DESC', 't.value'); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/UI/Tables/index.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Utils; 14 | 15 | use const LP_CACHE_TIME; 16 | 17 | interface CacheInterface 18 | { 19 | public function withKey(?string $key): self; 20 | 21 | public function setLifeTime(int $lifeTime): self; 22 | 23 | public function remember(string $key, callable $callback, int $time = LP_CACHE_TIME ?? 0): mixed; 24 | 25 | public function setFallback(callable $callback): mixed; 26 | 27 | public function get(string $key, int $time): mixed; 28 | 29 | public function put(string $key, mixed $value, int $time): void; 30 | 31 | public function forget(string $key): void; 32 | 33 | public function flush(): void; 34 | } 35 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Utils/File.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Utils; 14 | 15 | if (! defined('SMF')) 16 | die('No direct access...'); 17 | 18 | final class File extends GlobalArray 19 | { 20 | public function __construct() 21 | { 22 | $this->storage = &$_FILES; 23 | } 24 | 25 | public function free(string $key): void 26 | { 27 | unset($this->storage[$key]); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Utils/ParamWrapper.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Utils; 14 | 15 | use ArrayAccess; 16 | 17 | class ParamWrapper implements ArrayAccess 18 | { 19 | public function __construct(private array $storage = []) {} 20 | 21 | public function offsetExists(mixed $offset): bool 22 | { 23 | return isset($this->storage[$offset]); 24 | } 25 | 26 | public function offsetGet(mixed $offset): mixed 27 | { 28 | return $this->storage[$offset] ?? null; 29 | } 30 | 31 | public function offsetSet(mixed $offset, mixed $value): void 32 | { 33 | $this->storage[$offset] = $value; 34 | } 35 | 36 | public function offsetUnset(mixed $offset): void 37 | { 38 | unset($this->storage[$offset]); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Utils/Post.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Utils; 14 | 15 | if (! defined('SMF')) 16 | die('No direct access...'); 17 | 18 | final class Post extends GlobalArray 19 | { 20 | public function __construct() 21 | { 22 | $this->storage = &$_POST; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Utils/Response.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Utils; 14 | 15 | use Bugo\Compat\Utils; 16 | 17 | use function header; 18 | use function json_encode; 19 | 20 | class Response 21 | { 22 | public function json(mixed $data, int $flags = 0): false|string 23 | { 24 | header('Content-Type: application/json; charset=utf-8'); 25 | 26 | return json_encode($data, $flags); 27 | } 28 | 29 | public function exit(mixed $data, int $flags = 0): never 30 | { 31 | exit($this->json($data, $flags)); 32 | } 33 | 34 | public function redirect(string $url = ''): void 35 | { 36 | Utils::redirectexit($url); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Utils/Session.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Utils; 14 | 15 | if (! defined('SMF')) 16 | die('No direct access...'); 17 | 18 | final class Session extends GlobalArray 19 | { 20 | public function __construct(?string $key = null) 21 | { 22 | if ($key) { 23 | if (! isset($_SESSION[$key])) { 24 | $_SESSION[$key] = []; 25 | } 26 | 27 | $this->storage = &$_SESSION[$key]; 28 | return; 29 | } 30 | 31 | $this->storage = &$_SESSION; 32 | } 33 | 34 | public function withKey(?string $key): self 35 | { 36 | return new self($key); 37 | } 38 | 39 | public function free(string $key): void 40 | { 41 | unset($this->storage[$key]); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Utils/Traits/HasBreadcrumbs.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Utils\Traits; 14 | 15 | use Bugo\LightPortal\Utils\Breadcrumbs; 16 | 17 | trait HasBreadcrumbs 18 | { 19 | public function breadcrumbs(): Breadcrumbs 20 | { 21 | return app(Breadcrumbs::class); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Utils/Traits/HasForumHooks.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Utils\Traits; 14 | 15 | use Bugo\Compat\IntegrationHook; 16 | use Bugo\LightPortal\Enums\Hook; 17 | 18 | use function method_exists; 19 | 20 | if (! defined('SMF')) 21 | die('No direct access...'); 22 | 23 | trait HasForumHooks 24 | { 25 | protected function applyHook(Hook $hook, ?string $class = null): void 26 | { 27 | $class ??= static::class; 28 | 29 | $method = method_exists($class, $hook->name) ? $hook->name : '__invoke'; 30 | 31 | IntegrationHook::add($hook->name(), "$class::$method#", false); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Utils/Traits/HasReflection.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Utils\Traits; 14 | 15 | use ReflectionClass; 16 | 17 | if (! defined('SMF')) 18 | die('No direct access...'); 19 | 20 | trait HasReflection 21 | { 22 | public function getCalledClass(): ReflectionClass 23 | { 24 | return new ReflectionClass(static::class); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Utils/Traits/HasRequest.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Utils\Traits; 14 | 15 | use Bugo\LightPortal\Utils\File; 16 | use Bugo\LightPortal\Utils\Post; 17 | use Bugo\LightPortal\Utils\Request; 18 | 19 | trait HasRequest 20 | { 21 | public function request(): Request 22 | { 23 | return app(Request::class); 24 | } 25 | 26 | public function post(): Post 27 | { 28 | return app(Post::class); 29 | } 30 | 31 | public function files(): File 32 | { 33 | return app(File::class); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Utils/Traits/HasResponse.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Utils\Traits; 14 | 15 | use Bugo\LightPortal\Utils\Response; 16 | 17 | trait HasResponse 18 | { 19 | public function response(): Response 20 | { 21 | return app(Response::class); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Utils/Traits/HasSession.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Utils\Traits; 14 | 15 | use Bugo\LightPortal\Utils\Session; 16 | 17 | trait HasSession 18 | { 19 | public function session(?string $key = null): Session 20 | { 21 | return $key === null 22 | ? app(Session::class) 23 | : app(Session::class)->withKey($key); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Utils/Traits/index.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Utils; 14 | 15 | use Bugo\Compat\ErrorHandler; 16 | use Fiber; 17 | use Throwable; 18 | 19 | class Weaver 20 | { 21 | public function __invoke(callable $callback): array 22 | { 23 | $fiber = new Fiber(function () use ($callback) { 24 | $data = $callback(); 25 | Fiber::suspend($data); 26 | }); 27 | 28 | try { 29 | return $fiber->start(); 30 | } catch (Throwable $e) { 31 | ErrorHandler::fatal($e->getMessage(), false); 32 | } 33 | 34 | return []; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Utils/index.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Validators; 14 | 15 | class CategoryValidator extends AbstractValidator 16 | { 17 | protected array $filters = [ 18 | 'category_id' => FILTER_VALIDATE_INT, 19 | 'icon' => FILTER_DEFAULT, 20 | 'description' => FILTER_SANITIZE_FULL_SPECIAL_CHARS, 21 | ]; 22 | } 23 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Validators/TagValidator.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Validators; 14 | 15 | class TagValidator extends AbstractValidator 16 | { 17 | protected array $filters = [ 18 | 'tag_id' => FILTER_VALIDATE_INT, 19 | 'icon' => FILTER_DEFAULT, 20 | ]; 21 | } 22 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Validators/ValidatorInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | namespace Bugo\LightPortal\Validators; 14 | 15 | interface ValidatorInterface 16 | { 17 | public function validate(): array; 18 | } 19 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/Validators/index.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | if (! defined('SMF')) 14 | die('We gotta get out of here!'); 15 | 16 | require_once __DIR__ . '/Libs/autoload.php'; 17 | 18 | use Bugo\Compat\ErrorHandler; 19 | use Bugo\LightPortal\Container; 20 | use Bugo\LightPortal\PortalApp; 21 | 22 | /** 23 | * @template RequestedType 24 | * @param class-string|string $service 25 | * @return RequestedType|mixed 26 | */ 27 | function app(string $service = ''): mixed 28 | { 29 | if (empty($service)) { 30 | return Container::getInstance(); 31 | } 32 | 33 | try { 34 | return Container::get($service); 35 | } catch (Throwable $e) { 36 | ErrorHandler::fatal($e->getMessage(), 'critical'); 37 | } 38 | 39 | return false; 40 | } 41 | 42 | // This is the way 43 | app(PortalApp::class); 44 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "php": "~8.1", 4 | "ext-dom": "*", 5 | "ext-intl": "*", 6 | "ext-simplexml": "*", 7 | "ext-zip": "*", 8 | "bugo/fa-php-helper": "^0.5", 9 | "bugo/smf-bricks": "^0.5", 10 | "bugo/smf-compat": "^0.3", 11 | "doctrine/event-manager": "^2.0", 12 | "eftec/bladeone": "^4.13", 13 | "league/container": "^5.0", 14 | "wplake/typed": "^1.1" 15 | }, 16 | "autoload": { 17 | "psr-4": { 18 | "Bugo\\LightPortal\\": "" 19 | }, 20 | "exclude-from-classmap": [ 21 | "Plugins" 22 | ] 23 | }, 24 | "config": { 25 | "vendor-dir": "Libs", 26 | "optimize-autoloader": true, 27 | "preferred-install": "dist", 28 | "sort-packages": true, 29 | "platform": { 30 | "php": "8.1" 31 | } 32 | }, 33 | "scripts": { 34 | "post-update-cmd": [ 35 | "@php update_plugins.php", 36 | "@php create_index.php" 37 | ] 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Sources/LightPortal/create_index.php: -------------------------------------------------------------------------------- 1 | getPathname(), 'Libs')) 12 | continue; 13 | 14 | if (str_contains((string) $directory->getPathname(), 'packages')) 15 | continue; 16 | 17 | if ($directory->isDir() && ! file_exists($directory . '/index.php')) { 18 | file_put_contents($directory . '/index.php', ''; 10 | } 11 | 12 | echo /** @lang text */ ' 13 |
14 | '; 17 | } 18 | -------------------------------------------------------------------------------- /src/Themes/default/LightPortal/ViewDebug.template.php: -------------------------------------------------------------------------------- 1 | 14 | 15 | ' . Lang::$txt['admin_search_type_online'] . ' 16 | 17 | '; 18 | } 19 | 20 | function template_docs_below() 21 | { 22 | } 23 | 24 | function template_debug_above() 25 | { 26 | } 27 | 28 | function template_debug_below(): void 29 | { 30 | echo ' 31 |
32 | ', Utils::$context['lp_load_page_stats'], ' 33 |
'; 34 | } 35 | -------------------------------------------------------------------------------- /src/Themes/default/LightPortal/index.php: -------------------------------------------------------------------------------- 1 | @dump($context['user']) --> 5 | 6 |
7 | @include('partials.pagination') 8 | 9 | @foreach ($context['lp_frontpage_articles'] as $article) 10 |
15 |
16 | {!! parse_bbc('[code]' . print_r($article, true) . '[/code]') !!} 17 |
18 |
19 | @endforeach 20 | 21 | @include('partials.pagination', ['position' => 'bottom']) 22 |
23 | @endsection 24 | -------------------------------------------------------------------------------- /src/Themes/default/LightPortal/layouts/default.blade.php: -------------------------------------------------------------------------------- 1 | @extends('partials.base') 2 | 3 | @section('content') 4 |
5 | @include('partials.pagination') 6 | 7 | @foreach ($context['lp_frontpage_articles'] as $article) 8 |
9 |
10 | @include('partials.image', ['article' => $article]) 11 | 12 | @include('partials.card', ['article' => $article]) 13 |
14 |
15 | @endforeach 16 | 17 | @include('partials.pagination', ['position' => 'bottom']) 18 |
19 | @endsection 20 | -------------------------------------------------------------------------------- /src/Themes/default/LightPortal/layouts/index.php: -------------------------------------------------------------------------------- 1 | 3 | @endempty 4 | 5 | @yield('content') 6 | 7 | @empty ($context['lp_active_blocks']) 8 | 9 | @endempty 10 | -------------------------------------------------------------------------------- /src/Themes/default/LightPortal/layouts/partials/card-header.blade.php: -------------------------------------------------------------------------------- 1 | 2 | @unless (empty($article['section']['name'])) 3 | 4 | @empty ($article['section']['icon']) 5 | @icon('category') 6 | @else 7 | {!! $article['section']['icon'] !!} 8 | @endempty 9 | 10 | {{ $article['section']['name'] }} 11 | 12 | @endunless 13 | 14 | @if ($article['is_new'] && empty($article['image'])) 15 | 16 | {{ $txt['new'] }} 17 | 18 | @endif 19 | 20 | @unless (empty($article['datetime'])) 21 | 24 | @endunless 25 | -------------------------------------------------------------------------------- /src/Themes/default/LightPortal/layouts/partials/card.blade.php: -------------------------------------------------------------------------------- 1 |
2 | @include('partials.card-header', ['article' => $article]) 3 | 4 |

5 | {{ $article['title'] }} 6 |

7 | 8 | @unless (empty($article['teaser'])) 9 |

{{ $article['teaser'] }}

10 | @endunless 11 | 12 | @include('partials.card-footer', ['article' => $article]) 13 |
14 | -------------------------------------------------------------------------------- /src/Themes/default/LightPortal/layouts/partials/image.blade.php: -------------------------------------------------------------------------------- 1 | @unless (empty($article['image'])) 2 | @if ($article['is_new']) 3 |
4 |
5 | {{ $txt['new'] }} 6 |
7 |
8 | @endif 9 | 10 | @if ($article['can_edit']) 11 |
12 | 15 |
16 | @endif 17 | 18 |
19 | 20 |
21 |
22 | @endunless -------------------------------------------------------------------------------- /src/Themes/default/LightPortal/layouts/partials/index.php: -------------------------------------------------------------------------------- 1 | 5 | @include('partials.pagination') 6 | 7 | @foreach ($context['lp_frontpage_articles'] as $article) 8 |
9 | @unless (empty($article['image'])) 10 |
11 | @endunless 12 | 13 |
14 | {{ $article['title'] }} 15 | 16 | @unless (empty($article['teaser'])) 17 | 18 | @endunless 19 |
20 | 21 | 24 |
25 | @endforeach 26 | 27 | @include('partials.pagination', ['position' => 'bottom']) 28 | 29 | @endsection 30 | -------------------------------------------------------------------------------- /src/Themes/default/LightPortal/layouts/simple_grid.blade.php: -------------------------------------------------------------------------------- 1 | @extends('partials.base') 2 | 3 | @section('content') 4 | @include('partials.pagination') 5 | 6 |
7 | @foreach ($context['lp_frontpage_articles'] as $article) 8 |
9 | @unless (empty($article['image'])) 10 | {{ $article['title'] }} 11 | @endunless 12 | 13 |
14 | {{ $article['title'] }} 15 |
16 |
17 | @endforeach 18 |
19 | 20 | @include('partials.pagination', ['position' => 'bottom']) 21 | @endsection 22 | -------------------------------------------------------------------------------- /src/Themes/default/css/light_portal/index.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2019-2025 Bugo 8 | * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later 9 | * 10 | * @version 2.9 11 | */ 12 | 13 | use Bugo\Compat\{Config, Lang, Utils}; 14 | use Bugo\LightPortal\Actions\FrontPage; 15 | 16 | require_once __DIR__ . '/SSI.php'; 17 | 18 | if (empty(Config::$sourcedir)) { 19 | die('' . Lang::$txt['error_occured'] . ' ' . Lang::$txt['lp_standalone_mode_error']); 20 | } 21 | 22 | if (empty(Config::$modSettings['lp_standalone_mode']) || empty(Config::$modSettings['lp_standalone_url'])) { 23 | Utils::redirectexit(); 24 | } 25 | 26 | try { 27 | app(FrontPage::class)->show(); 28 | } catch (Exception $e) { 29 | die($e->getMessage()); 30 | } 31 | 32 | Utils::obExit(); 33 | -------------------------------------------------------------------------------- /src/uninstall.php: -------------------------------------------------------------------------------- 1 | Error: Cannot install - please verify that you put this file in the same place as SMF\'s index.php and SSI.php files.'); 9 | } 10 | 11 | if ((SMF === 'SSI') && ! $user_info['is_admin']) { 12 | die('Admin privileges required.'); 13 | } 14 | 15 | $smcFunc['db_query']('', ' 16 | DELETE FROM {db_prefix}background_tasks 17 | WHERE task_file LIKE {string:task_file}', 18 | [ 19 | 'task_file' => '%$sourcedir/LightPortal%' 20 | ] 21 | ); 22 | 23 | if (SMF === 'SSI') { 24 | echo 'Database changes are complete! Please wait...'; 25 | } 26 | 27 | echo 'I\'ll see you again. I promise ©️'; 28 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2022", 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowJs": true, 7 | "checkJs": true, 8 | "esModuleInterop": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "resolveJsonModule": true, 11 | "skipLibCheck": true, 12 | "noEmit": true, 13 | "allowImportingTsExtensions": true, 14 | "verbatimModuleSyntax": true, 15 | "isolatedModules": true 16 | }, 17 | "include": ["resources"] 18 | } 19 | --------------------------------------------------------------------------------