diff --git a/app/Core/Admin/Http/Controllers/Api/DatabasesController.php b/app/Core/Admin/Http/Controllers/Api/DatabasesController.php index 2508acd..4e31e18 100644 --- a/app/Core/Admin/Http/Controllers/Api/DatabasesController.php +++ b/app/Core/Admin/Http/Controllers/Api/DatabasesController.php @@ -21,7 +21,7 @@ public function __construct(DatabasesService $databasesService) public function store(FluteRequest $request): Response { try { - $this->validate($request); + $this->validation($request); $this->databasesService->store( $request->mod, @@ -50,7 +50,7 @@ public function delete(FluteRequest $request, $id): Response public function update(FluteRequest $request, $id): Response { try { - $this->validate($request); + $this->validation($request); $this->databasesService->update( (int) $id, @@ -66,7 +66,7 @@ public function update(FluteRequest $request, $id): Response } } - protected function validate( FluteRequest $request ) + protected function validation( FluteRequest $request ) { if( empty( $request->input('mod') ) || empty( $request->input('dbname') ) ) throw new \Exception(__('admin.databases.params_empty')); diff --git a/app/Core/Admin/Http/Controllers/Api/IconsController.php b/app/Core/Admin/Http/Controllers/Api/IconsController.php new file mode 100644 index 0000000..f02c471 --- /dev/null +++ b/app/Core/Admin/Http/Controllers/Api/IconsController.php @@ -0,0 +1,17 @@ +json([ + 'icons' => app(PhosphorIconsParser::class)->getAll() + ]); + } +} \ No newline at end of file diff --git a/app/Core/Admin/Http/Controllers/Api/NavigationController.php b/app/Core/Admin/Http/Controllers/Api/NavigationController.php index c705264..4036c8f 100644 --- a/app/Core/Admin/Http/Controllers/Api/NavigationController.php +++ b/app/Core/Admin/Http/Controllers/Api/NavigationController.php @@ -31,7 +31,7 @@ public function saveOrder(FluteRequest $request) foreach ($order as $value) { $item = rep(NavbarItem::class)->select()->load('roles')->where(['id' => (int) $value['id']])->fetchOne(); - if ($item && navbar()->hasAccess($item)) { + if ($item && navbar()->hasAccess($item, true)) { $item->position = $value['position']; if ($value['parent_id'] == null) { @@ -39,7 +39,7 @@ public function saveOrder(FluteRequest $request) } else { $parent = rep(NavbarItem::class)->select()->load('roles')->where(['id' => (int) $value['parent_id']])->fetchOne(); - if ($parent && navbar()->hasAccess($parent)) + if ($parent && navbar()->hasAccess($parent, true)) $item->parent = $parent; } @@ -151,7 +151,7 @@ protected function getItem(string $id) if (!$navigation) return $this->error(__('admin.navigation.not_found'), 404); - if (!navbar()->hasAccess($navigation)) + if (!navbar()->hasAccess($navigation, true)) return $this->error(__('def.no_access')); return $navigation; diff --git a/app/Core/Admin/Http/Controllers/Api/ServersController.php b/app/Core/Admin/Http/Controllers/Api/ServersController.php index e2024a9..bb8aea8 100644 --- a/app/Core/Admin/Http/Controllers/Api/ServersController.php +++ b/app/Core/Admin/Http/Controllers/Api/ServersController.php @@ -136,13 +136,15 @@ public function checkRcon(FluteRequest $request) try { $query = new SourceQuery(); - $query->Connect($ip, $port, 5, ((int) $game === 10) ? SourceQuery::GOLDSOURCE : SourceQuery::SOURCE); + $query->Connect($ip, $port, 3, ((int) $game === 10) ? SourceQuery::GOLDSOURCE : SourceQuery::SOURCE); $query->SetRconPassword($rcon); $rcon = $query->Rcon($command); - return $this->success($rcon); + return $this->json([ + 'result' => $rcon + ]); } catch (\Exception $e) { return $this->error($e->getMessage()); } finally { diff --git a/app/Core/Admin/Http/Controllers/Views/NavbarView.php b/app/Core/Admin/Http/Controllers/Views/NavbarView.php index 767fee3..e7634f2 100644 --- a/app/Core/Admin/Http/Controllers/Views/NavbarView.php +++ b/app/Core/Admin/Http/Controllers/Views/NavbarView.php @@ -41,7 +41,7 @@ public function edit(FluteRequest $request, string $id) { $navigation = rep(NavbarItem::class)->select()->load('roles')->where('id', (int) $id)->fetchOne(); - if (!navbar()->hasAccess($navigation)) + if (!navbar()->hasAccess($navigation, true)) return $this->error(__('def.no_access')); if (!$navigation) diff --git a/app/Core/Admin/Http/Controllers/Views/Payments/PaymentsView.php b/app/Core/Admin/Http/Controllers/Views/Payments/PaymentsView.php index e0e43b5..9fdccd9 100644 --- a/app/Core/Admin/Http/Controllers/Views/Payments/PaymentsView.php +++ b/app/Core/Admin/Http/Controllers/Views/Payments/PaymentsView.php @@ -173,11 +173,11 @@ public function edit(FluteRequest $request, string $id): Response return view("Core/Admin/Http/Views/pages/payments/edit", [ 'gateway' => $payment, 'additional' => \Nette\Utils\Json::decode($payment->additional), - 'drivers' => $this->getAllDrivers() + 'drivers' => $this->getAllDrivers($payment->adapter) ]); } - protected function getAllDrivers() + protected function getAllDrivers(?string $currentGateway = null) { $namespaceMap = app()->getLoader()->getPrefixesPsr4(); $result = []; @@ -215,6 +215,15 @@ protected function getAllDrivers() } } + foreach ($result as $key => $val) { + $find = rep(PaymentGateway::class)->findOne([ + "adapter" => $val['name'] + ]); + + if ($find && $currentGateway !== $val['name']) + unset($result[$key]); + } + return $result; } diff --git a/app/Core/Admin/Http/Controllers/Views/SocialsView.php b/app/Core/Admin/Http/Controllers/Views/SocialsView.php index 0444997..2199e79 100644 --- a/app/Core/Admin/Http/Controllers/Views/SocialsView.php +++ b/app/Core/Admin/Http/Controllers/Views/SocialsView.php @@ -138,7 +138,7 @@ public function edit(FluteRequest $request, string $id): Response return view("Core/Admin/Http/Views/pages/socials/edit", [ 'social' => $social, - 'drivers' => $this->getAllDrivers() + 'drivers' => $this->getAllDrivers($social->key) ]); } @@ -147,7 +147,7 @@ protected function getSocialNetwork(int $id): ?SocialNetwork return rep(SocialNetwork::class)->findByPK($id); } - protected function getAllDrivers() + protected function getAllDrivers(?string $currentDriver = null) { $namespaceMap = app()->getLoader()->getPrefixesPsr4(); $result = []; @@ -175,9 +175,16 @@ protected function getAllDrivers() return Strings::startsWith($item, "Hybridauth\\Provider"); }), $result); - foreach( $result as $key => $item ) { + foreach ($result as $key => $item) { $ex = explode('\\', $item); - $result[$key] = $ex[array_key_last($ex)]; + $driver = $ex[array_key_last($ex)]; + + $find = rep(SocialNetwork::class)->findOne([ + "key" => $driver + ]); + + if (!$find || ($driver === $currentDriver)) + $result[$key] = $driver; } return $result; diff --git a/app/Core/Admin/Http/Views/assets/js/components/tabs.js b/app/Core/Admin/Http/Views/assets/js/components/tabs.js index e30c9d8..dfcd6ef 100644 --- a/app/Core/Admin/Http/Views/assets/js/components/tabs.js +++ b/app/Core/Admin/Http/Views/assets/js/components/tabs.js @@ -74,6 +74,7 @@ const contentCache = {}; constructor() { this.draggabillies = []; this.contentContainers = {}; + this.abortControllers = {}; } init(el) { @@ -425,6 +426,12 @@ const contentCache = {}; // Получаем ID вкладки const tabId = tabEl.getAttribute('data-tab-id'); + // Отмена загрузки контента при закрытии вкладки + if (this.abortControllers[tabId]) { + this.abortControllers[tabId].abort(); + delete this.abortControllers[tabId]; + } + // Удаляем контейнер контента, связанный с этой вкладкой const contentContainer = document.getElementById( `content-${tabId}`, @@ -758,27 +765,34 @@ function refreshCurrentPage() { } function fetchContent(url, container, tabEl, reload = false, title = null) { - fetch(appendGet(url, 'loadByTab', '1')) + const tabId = tabEl.getAttribute('data-tab-id'); + const abortController = new AbortController(); + chromeTabs.abortControllers[tabId] = abortController; + + fetch(appendGet(url, 'loadByTab', '1'), { signal: abortController.signal }) .then((response) => { if (!response.ok) { throw new Error('Not 2xx response', { cause: response }); } - return response.text(); }) .then((html) => { - const containerId = container.getAttribute('id'); + if (!container) return; // Check if container is still in DOM + const containerId = container.getAttribute('id'); container.classList.remove('loading'); container.innerHTML = html; loadScriptsFromContainer(containerId); - recoverContainerIDS(containerId); }) .catch((error) => { - console.error('Error loading the page: ', error); - showErrorPage(true); + if (error.name === 'AbortError') { + console.log('Content load aborted:', url); + } else { + console.error('Error loading the page: ', error); + showErrorPage(true); + } }) .finally(() => { setTimeout(() => { @@ -793,6 +807,7 @@ function fetchContent(url, container, tabEl, reload = false, title = null) { }, 700); }); } + function displayLoading(show) { const loadingElement = document.getElementById('loading'); loadingElement.style.setProperty('--animate-duration', '.3s'); @@ -1048,6 +1063,7 @@ function removeScriptsByContainerId(containerId) { function initEditor(container) { container.find('.editor-ace').each(function () { let editor = ace.edit(this); + let mode = $(this).data('editor-lang') || 'json'; let unformattedContent = editor.getSession().getValue(); let formattedContent = js_beautify(unformattedContent, { indent_size: 4, @@ -1055,7 +1071,7 @@ function initEditor(container) { }); editor.getSession().setValue(formattedContent); editor.setTheme('ace/theme/solarized_dark'); - editor.session.setMode('ace/mode/json'); + editor.session.setMode(`ace/mode/${mode}`); }); } diff --git a/app/Core/Admin/Http/Views/assets/js/layout.js b/app/Core/Admin/Http/Views/assets/js/layout.js index b873cb4..ea83d07 100644 --- a/app/Core/Admin/Http/Views/assets/js/layout.js +++ b/app/Core/Admin/Http/Views/assets/js/layout.js @@ -81,7 +81,13 @@ function transformUrl(url) { } } -function sendRequest(data, path = null, method = 'POST', callback) { +function sendRequest( + data, + path = null, + method = 'POST', + callback = null, + needToRefresh = true, +) { toast({ type: 'async', message: translate('admin.is_loading'), @@ -93,27 +99,31 @@ function sendRequest(data, path = null, method = 'POST', callback) { data: data, success: function (response) { callback && callback(response); - Modals.clear(); - if (method === 'DELETE') { - tryAndDeleteTab(transformUrl(path)); - refreshCurrentPage(); - } else { - refreshCurrentPage(); - if (!path.includes('admin/api/settings')) { - if ( - path.includes('edit') || - path.includes('add') || - path.includes('delete') - ) - fetchContentAndAddTab( - replaceURLForTab( - window.location.pathname, - ), - ); + if (needToRefresh) { + Modals.clear(); + + if (method === 'DELETE') { + tryAndDeleteTab(transformUrl(path)); refreshCurrentPage(); + } else { + refreshCurrentPage(); + if (!path.includes('admin/api/settings')) { + if ( + path.includes('edit') || + path.includes('add') || + path.includes('delete') + ) + fetchContentAndAddTab( + replaceURLForTab( + window.location.pathname, + ), + ); + refreshCurrentPage(); + } } } + resolve(response?.success || translate('def.success')); }, error: function (jqXHR, textStatus, errorThrown) { @@ -398,6 +408,76 @@ $(function () { container.addEventListener('mouseleave', function () { container.style.width = '35px'; }); + + let icons = []; + + const $iconMenu = $( + '
', + ).appendTo('body'); + const $iconMenuHeader = $(` +
+ +
+ +
+
+ `).appendTo($iconMenu); + const $iconList = $( + '
', + ).appendTo($iconMenu); + + function fetchIcons() { + $.getJSON(u('admin/api/get-icons'), function (data) { + icons = data.icons; + updateIconList(); + }); + } + + function updateIconList() { + const searchValue = $('#icon-search').val().toLowerCase(); + const style = $('#icon-style').val(); + $iconList.empty(); + icons + .filter((icon) => icon.includes(searchValue)) + .forEach((icon) => { + const iconElement = ``; + $iconList.append(iconElement); + }); + } + + $(document).on('focus', '#icon', function () { + const inputOffset = $(this).offset(); + const inputHeight = $(this).outerHeight() + 10; + $iconMenu + .css({ + top: inputOffset.top + inputHeight, + left: inputOffset.left, + }) + .slideDown(300); + }); + + $(document).on('click', function (event) { + if (!$(event.target).closest('#icon-menu, #icon').length) { + $iconMenu.slideUp(300); + } + }); + + $iconMenuHeader.on('input', '#icon-search', updateIconList); + $iconMenuHeader.on('change', '#icon-style', updateIconList); + + $iconList.on('click', 'i', function () { + const iconClass = $(this).attr('class'); + $('#icon').val(``).trigger('input'); + $iconMenu.slideUp(); + }); + + fetchIcons(); }); window.defaultEditorData = {}; diff --git a/app/Core/Admin/Http/Views/assets/js/pages/navigation/add.js b/app/Core/Admin/Http/Views/assets/js/pages/navigation/add.js index 2a8d911..3a41ab1 100644 --- a/app/Core/Admin/Http/Views/assets/js/pages/navigation/add.js +++ b/app/Core/Admin/Http/Views/assets/js/pages/navigation/add.js @@ -15,7 +15,16 @@ $(function () { $(document).on('input', '#icon', function () { let val = $(this).val().trim(); - $('#icon-output').html(``); + let className = val; + + if (val.includes('`); }); // Обработчик события изменения текста в поле URL diff --git a/app/Core/Admin/Http/Views/assets/js/pages/servers/edit.js b/app/Core/Admin/Http/Views/assets/js/pages/servers/edit.js index 4009aed..ac6a90d 100644 --- a/app/Core/Admin/Http/Views/assets/js/pages/servers/edit.js +++ b/app/Core/Admin/Http/Views/assets/js/pages/servers/edit.js @@ -52,3 +52,84 @@ $(document).on('click', '#check_ip', (ev) => { }), }); }); + +$(document).on('submit', '#commandInputForm', (e) => sendCommand(e)); + +$(document).on('click', '#openModal', () => { + Modals.open({ + title: translate('admin.servers.rcon_command_placeholder'), + content: { + form: createCommandInput(), + }, + buttons: [ + { + text: translate('def.close'), + class: 'cancel', + id: 'closeRconBtn', + callback: (modal) => modal.clear(), + }, + { + text: translate('def.submit'), + class: 'primary', + id: 'sendBtn', + callback: () => sendCommand(null), + }, + ], + }); +}); + +function createCommandInput() { + return { + id: 'commandInputForm', + fields: [ + { + type: 'text', + id: 'commandInput', + label: translate('admin.servers.rcon_command'), + placeholder: translate( + 'admin.servers.rcon_command_placeholder', + ), + helpText: translate('admin.servers.rcon_command_desc'), + }, + ], + }; +} + +async function sendCommand(e) { + if (e) { + e.preventDefault(); + } + + sendRequest( + { + command: $('#commandInput').val(), + ip: $('#serverIp').val(), + port: Number($('#serverPort').val()), + rcon: $('#serverRcon').val(), + game: $('#gameSelect').val(), + }, + u('admin/api/servers/check-rcon'), + 'POST', + function (res) { + if (res?.result) { + $('#commandInputForm') + .parent() + .html(`
${res.result}
`); + $('#sendBtn').remove(); + $('#closeRconBtn').removeClass('cancel').addClass('primary'); + } else { + if ($('#commandInputForm > div > .error-message').length > 0) { + $('#commandInputForm > div > .error-message').html( + res.responseJSON?.error, + ); + $('#commandInputForm > div > .error-message').remove(); + } else { + $('#commandInputForm > div').append( + `${res.responseJSON?.error}`, + ); + } + } + }, + false, + ); +} diff --git a/app/Core/Admin/Http/Views/assets/js/pages/socials/add.js b/app/Core/Admin/Http/Views/assets/js/pages/socials/add.js index 63ac105..d7f7e3e 100644 --- a/app/Core/Admin/Http/Views/assets/js/pages/socials/add.js +++ b/app/Core/Admin/Http/Views/assets/js/pages/socials/add.js @@ -1,12 +1,32 @@ $(function () { + hideSteam(); + $(document).on('change', '#key', function () { let socialPlatform = $(this).val(); let redirectUri1 = u(`social/${socialPlatform}`); let redirectUri2 = u(`profile/social/bind/${socialPlatform}`); $('#redirectUri1').val(redirectUri1).attr('data-copy', redirectUri1); $('#redirectUri2').val(redirectUri2).attr('data-copy', redirectUri2); + + hideSteam(); }); - + + function hideSteam() { + let socialPlatform = $('#key').val(); + + if (socialPlatform === 'Steam' || socialPlatform === 'HttpsSteam') { + $('#driverSettings').hide(); + } else { + $('#driverSettings').show(); + } + } + + document + .querySelector('.chrome-tabs') + .addEventListener('contentRender', ({ detail }) => { + hideSteam(); + }); + $(document).on('submit', '#socialAdd, #socialEdit', (ev) => { let $form = $(ev.currentTarget); @@ -28,7 +48,9 @@ $(function () { { ...form, ...{ - settings: ace.edit($form.find('.editor-ace')[0]).getValue(), + settings: ace + .edit($form.find('.editor-ace')[0]) + .getValue(), }, }, url, diff --git a/app/Core/Admin/Http/Views/assets/styles/components/_inputs.scss b/app/Core/Admin/Http/Views/assets/styles/components/_inputs.scss index dd34e4c..ff27a5d 100644 --- a/app/Core/Admin/Http/Views/assets/styles/components/_inputs.scss +++ b/app/Core/Admin/Http/Views/assets/styles/components/_inputs.scss @@ -621,4 +621,61 @@ $input-placeholder-color: $color-inactive; &:hover { color: $color-primary; } +} + +.icon-menu { + display: none; + position: absolute; + background: $color-disabled; + border: 1px solid $color-white-5; + border-radius: 6px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + z-index: 1000; + width: 305px; + max-height: 400px; + overflow-y: auto; + z-index: 10; +} + +.icon-menu-header { + display: flex; + padding: 10px; + border-bottom: 1px solid $color-white-5; + position: sticky; + top: 0; + background-color: $color-disabled; + + .form-group { + width: 100%; + margin: 0; + padding: 0; + } +} + +#icon-search { + padding: 5px; + color: $color-text; + width: 160px; +} + +#icon-style {} + +.icon-list { + padding: 10px; + display: flex; + flex-wrap: wrap; + gap: 5px; +} + +.icon-list i { + cursor: pointer; + font-size: 22px; + color: $color-text; + padding: 10px; + border-radius: 5px; + transition: $transition; + + &:hover { + background-color: $color-white-5; + } } \ No newline at end of file diff --git a/app/Core/Admin/Http/Views/assets/styles/pages/servers.scss b/app/Core/Admin/Http/Views/assets/styles/pages/servers.scss index 3ff98b1..5253647 100644 --- a/app/Core/Admin/Http/Views/assets/styles/pages/servers.scss +++ b/app/Core/Admin/Http/Views/assets/styles/pages/servers.scss @@ -9,6 +9,18 @@ text-shadow: none; } +.error-message { + color: $color-error; + font-size: 14px; + margin-top: 20px; +} + +.success-message { + color: $color-success; + font-size: 14px; + white-space: break-spaces; +} + .servers-action-buttons { display: flex; gap: 5px; diff --git a/app/Core/Admin/Http/Views/assets/styles/pages/users.scss b/app/Core/Admin/Http/Views/assets/styles/pages/users.scss index e3e949f..240cce4 100644 --- a/app/Core/Admin/Http/Views/assets/styles/pages/users.scss +++ b/app/Core/Admin/Http/Views/assets/styles/pages/users.scss @@ -344,6 +344,8 @@ svg, i { width: 30px; height: 30px; - font-size: 25px; + font-size: 24px; + fill: $color-primary; + color: $color-primary; } } \ No newline at end of file diff --git a/app/Core/Admin/Http/Views/pages/footer/list.blade.php b/app/Core/Admin/Http/Views/pages/footer/list.blade.php index 80f7f96..9c0d2e7 100644 --- a/app/Core/Admin/Http/Views/pages/footer/list.blade.php +++ b/app/Core/Admin/Http/Views/pages/footer/list.blade.php @@ -84,6 +84,6 @@ @endpush @push('footer') - + @at('https://SortableJS.github.io/Sortable/Sortable.js') @at('Core/Admin/Http/Views/assets/js/pages/footer/list.js') @endpush diff --git a/app/Core/Admin/Http/Views/pages/footer/social/add.blade.php b/app/Core/Admin/Http/Views/pages/footer/social/add.blade.php deleted file mode 100644 index 946b5ca..0000000 --- a/app/Core/Admin/Http/Views/pages/footer/social/add.blade.php +++ /dev/null @@ -1,71 +0,0 @@ -@extends('Core.Admin.Http.Views.layout', [ - 'title' => __('admin.title', ['name' => __('admin.footer.social_add')]), -]) - -@push('header') - @at('Core/Admin/Http/Views/assets/styles/pages/footer.scss') -@endpush - -@push('content') -
-
- - - @t('def.back') - -

@t('admin.footer.social_add_title')

-

@t('admin.footer.social_add_description')

-
-
- -
- @csrf -
-
- -
-
- -
-
-
-
- -
-
- -
-
-
-
- -
-
- -
-
- - -
-
- -
-
-
-@endpush - -@push('footer') - @at('Core/Admin/Http/Views/assets/js/pages/footer/social/add.js') -@endpush diff --git a/app/Core/Admin/Http/Views/pages/footer/social/edit.blade.php b/app/Core/Admin/Http/Views/pages/footer/social/edit.blade.php deleted file mode 100644 index a6046bd..0000000 --- a/app/Core/Admin/Http/Views/pages/footer/social/edit.blade.php +++ /dev/null @@ -1,83 +0,0 @@ -@extends('Core.Admin.Http.Views.layout', [ - 'title' => __('admin.title', [ - 'name' => __('admin.footer.social_edit_title', [ - 'name' => $item->name, - ]), - ]), -]) - -@push('header') - @at('Core/Admin/Http/Views/assets/styles/pages/footer.scss') -@endpush - -@push('content') -
-
- - - @t('def.back') - -

@t('admin.footer.social_edit_title', [ - 'name' => $item->name, - ])

-

@t('admin.footer.social_edit_description')

-
-
- -
-
- -
- @csrf - -
-
- -
-
- -
-
-
-
- -
-
- -
-
-
-
- -
-
- -
-
- - -
-
- -
-
-
-@endpush - -@push('footer') - @at('Core/Admin/Http/Views/assets/js/pages/footer/social/add.js') -@endpush diff --git a/app/Core/Admin/Http/Views/pages/footer/social/list.blade.php b/app/Core/Admin/Http/Views/pages/footer/social/list.blade.php deleted file mode 100644 index b2d647d..0000000 --- a/app/Core/Admin/Http/Views/pages/footer/social/list.blade.php +++ /dev/null @@ -1,27 +0,0 @@ -@extends('Core.Admin.Http.Views.layout', [ - 'title' => __('admin.title', ['name' => __('admin.footer.social')]), -]) - -@push('header') - @at('Core/Admin/Http/Views/assets/styles/pages/footer.scss') -@endpush - -@push('content') -
-
-

@t('admin.footer.social_header')

-

@t('admin.footer.social_description')

-
-
- - @t('admin.footer.social_add') - -
-
- - {!! $socials !!} -@endpush - -@push('footer') - @at('Core/Admin/Http/Views/assets/js/pages/footer/social/list.js') -@endpush diff --git a/app/Core/Admin/Http/Views/pages/footer/socials/add.blade.php b/app/Core/Admin/Http/Views/pages/footer/socials/add.blade.php index 946b5ca..dd00cb6 100644 --- a/app/Core/Admin/Http/Views/pages/footer/socials/add.blade.php +++ b/app/Core/Admin/Http/Views/pages/footer/socials/add.blade.php @@ -36,10 +36,14 @@ + @t('admin.notifications.icon_desc')
- +
+
+ +
diff --git a/app/Core/Admin/Http/Views/pages/footer/socials/edit.blade.php b/app/Core/Admin/Http/Views/pages/footer/socials/edit.blade.php index a6046bd..a9066b0 100644 --- a/app/Core/Admin/Http/Views/pages/footer/socials/edit.blade.php +++ b/app/Core/Admin/Http/Views/pages/footer/socials/edit.blade.php @@ -48,10 +48,14 @@ + @t('admin.notifications.icon_desc')
- +
+
+ +
diff --git a/app/Core/Admin/Http/Views/pages/main/items/additional.blade.php b/app/Core/Admin/Http/Views/pages/main/items/additional.blade.php index d969b6b..bba4a8d 100644 --- a/app/Core/Admin/Http/Views/pages/main/items/additional.blade.php +++ b/app/Core/Admin/Http/Views/pages/main/items/additional.blade.php @@ -91,7 +91,7 @@ class="form-check-input" {{ config('app.discord_link_roles') == true ? 'checked'
-
+
@@ -104,6 +104,8 @@ class="form-check-input" {{ config('app.widget_placeholders') ? 'checked' : '' }
+
@t('admin.app.notifications_label')
+
@@ -124,6 +126,23 @@ class="form-check-input" {{ config('app.widget_placeholders') ? 'checked' : '' }
+
+
+ + @t('admin.app.notifications_new_view_description') +
+
+ + +
+
+
diff --git a/app/Core/Admin/Http/Views/pages/main/items/app.blade.php b/app/Core/Admin/Http/Views/pages/main/items/app.blade.php index 6737dad..71a8f53 100644 --- a/app/Core/Admin/Http/Views/pages/main/items/app.blade.php +++ b/app/Core/Admin/Http/Views/pages/main/items/app.blade.php @@ -24,8 +24,21 @@ @t('admin.app.footer_name_description')
- + +
+
+ + +
+
+ + @t('admin.app.footer_html_description') +
+
+
{!! config('app.footer_html') !!}
@@ -43,6 +56,22 @@
+ +
+
+ + @t('admin.app.timezone_description') +
+
+ +
+
+ +
@t('admin.app.debug_mode_label')
+
@@ -58,7 +87,7 @@
-
+
+
@t('admin.app.maintenance_mode')
+
- -
-
-
- -
+
-
- - + +
+
E-Mail
+
@@ -64,6 +62,41 @@
+ + +
+
+ + @t('admin.auth_form.confirm_email_description') +
+
+ + +
+
+ +
@t('def.security')
+ + +
+
+ + @t('admin.auth_form.csrf_protection_description') +
+
+ + +
+
+
@@ -80,7 +113,7 @@
-
+
- - -
-
- - @t('admin.auth_form.confirm_email_description') -
-
- - -
-
- -
-
- - @t('admin.auth_form.only_social_label') -
-
- - -
-
- {{--
@@ -135,6 +140,8 @@
--}} +
@t('def.validation')
+
diff --git a/app/Core/Admin/Http/Views/pages/navigation/list.blade.php b/app/Core/Admin/Http/Views/pages/navigation/list.blade.php index 715112c..add0c4b 100644 --- a/app/Core/Admin/Http/Views/pages/navigation/list.blade.php +++ b/app/Core/Admin/Http/Views/pages/navigation/list.blade.php @@ -19,9 +19,9 @@
- @if (sizeof(navbar()->all()) > 0) + @if (sizeof(navbar()->all(true)) > 0)
-
+
-
+
+ value="{{ url('social/' . $social->key) }}" data-copy="{{ url('social/' . $social->key) }}">
@@ -104,7 +103,7 @@ class="form-control" value="{{ $social->cooldownTime }}" required>
-
diff --git a/app/Core/Admin/Services/Config/AppConfigService.php b/app/Core/Admin/Services/Config/AppConfigService.php index 5337eec..6fcffaa 100644 --- a/app/Core/Admin/Services/Config/AppConfigService.php +++ b/app/Core/Admin/Services/Config/AppConfigService.php @@ -16,16 +16,19 @@ public function updateConfig(array $params): Response $config = array_merge(config('app'), [ "name" => $params['name'] ?? config('app.name'), "footer_name" => $params['footer_name'] ?? config('app.footer_name', ''), + "footer_html" => $params['editorContent'] ?? config('app.footer_html', ''), "url" => $params['url'] ?? config('app.url'), "steam_api" => $params['steam_api'] ?? config('app.steam_api'), "debug" => $this->b($params['debug'] ?? config('app.debug')), "debug_ips" => $this->parseDebugIps($params['debugIps'] ?? implode(', ', config('app.debug_ips', []))), // "key" => $params['key'] ?? config('app.key'), "tips" => $this->b($params['tips'] ?? config('app.tips')), - "maintenance_mode" => $this->b($params['maintenance_mode'] ?? config('app.maintenance_mode')), + "maintenance_mode" => $params['maintenance_mode'] && $this->b($params['maintenance_mode']), + "maintenance_message" => $params['maintenance_message'] ?? config('app.maintenance_message'), "discord_link_roles" => $this->b($params['discord_link_roles'] ?? config('app.discord_link_roles')), "timezone" => $params['timezone'] ?? config('app.timezone'), "notifications" => $params['notifications'] ?? config('app.notifications'), + "notifications_new_view" => $this->b($params['notifications_new_view'] ?? config('app.notifications_new_view')), "mode" => $this->b($params['performanceMode'] ?? (config('app.mode') === 'performance')) ? 'performance' : 'default', "share" => $this->b($params['share'] ?? config('app.share')), "flute_copyright" => $this->b($params['flute_copyright'] ?? config('app.flute_copyright')), diff --git a/app/Core/Admin/routes.php b/app/Core/Admin/routes.php index 767385a..3073848 100644 --- a/app/Core/Admin/routes.php +++ b/app/Core/Admin/routes.php @@ -9,6 +9,7 @@ use Flute\Core\Admin\Http\Controllers\Api\EventsTestingController; use Flute\Core\Admin\Http\Controllers\Api\Footer\FooterController; use Flute\Core\Admin\Http\Controllers\Api\Footer\FooterSocialsController; +use Flute\Core\Admin\Http\Controllers\Api\IconsController; use Flute\Core\Admin\Http\Controllers\Api\IndexApi; use Flute\Core\Admin\Http\Controllers\Api\HelperAdminController; use Flute\Core\Admin\Http\Controllers\Api\MainSettingsController; @@ -183,6 +184,8 @@ // $admin->get('/', [IndexApi::class, 'index']); $admin->get('/createlog', [MainSettingsController::class, 'createLog']); + $admin->get('/get-icons', [IconsController::class, 'getAll']); + $admin->get('/getip', [HelperAdminController::class, 'getIP']); $admin->post('/check-steam', [HelperAdminController::class, 'checkSteam']); @@ -225,6 +228,7 @@ $adminModule->delete('/{id}', [ServersController::class, 'delete']); $adminModule->post('/add', [ServersController::class, 'add']); $adminModule->post('/check-ip', [ServersController::class, 'checkIp']); + $adminModule->post('/check-rcon', [ServersController::class, 'checkRcon']); $adminModule->put('/{id}', [ServersController::class, 'edit']); }, '/servers'); diff --git a/app/Core/App.php b/app/Core/App.php index 34f0ea3..4aa375d 100644 --- a/app/Core/App.php +++ b/app/Core/App.php @@ -47,7 +47,7 @@ final class App * * @var string */ - public const VERSION = '0.2.1.7-dev'; + public const VERSION = '0.2.2-alpha'; /** * Set the base path of the application diff --git a/app/Core/Helpers/App.php b/app/Core/Helpers/App.php index 6c67164..8bb1d06 100644 --- a/app/Core/Helpers/App.php +++ b/app/Core/Helpers/App.php @@ -8,9 +8,10 @@ /** * Get the instance of the Application class or resolve a class/interface from the container. * - * @param string|null $name Entry name or a class name. + * @template T + * @param class-string|null $name Entry name or a class name. * - * @return mixed Returns an instance of the type specified by $name, or the Application instance if $name is null. + * @return ($name is null ? App : T) Returns an instance of the type specified by $name, or the Application instance if $name is null. * @throws DependencyException * @throws NotFoundException */ diff --git a/app/Core/Helpers/Utils.php b/app/Core/Helpers/Utils.php index 96c28b1..d060ce7 100644 --- a/app/Core/Helpers/Utils.php +++ b/app/Core/Helpers/Utils.php @@ -261,6 +261,10 @@ function getPluralForm($number, $forms) function secondsToReadable(int $seconds): string { + if( $seconds === 0 ) { + return __('def.forever'); + } + $days = floor($seconds / 86400); $hours = floor(($seconds % 86400) / 3600); $minutes = floor(($seconds % 3600) / 60); @@ -269,22 +273,22 @@ function secondsToReadable(int $seconds): string $result = []; if ($days > 0) { - $daysForms = explode('|', __('def.days', [], 'messages')); + $daysForms = explode('|', __('def.days')); $result[] = $days . ' ' . getPluralForm($days, $daysForms); } if ($hours > 0) { - $hoursForms = explode('|', __('def.hours', [], 'messages')); + $hoursForms = explode('|', __('def.hours')); $result[] = $hours . ' ' . getPluralForm($hours, $hoursForms); } if ($minutes > 0) { - $minutesForms = explode('|', __('def.minutes', [], 'messages')); + $minutesForms = explode('|', __('def.minutes')); $result[] = $minutes . ' ' . getPluralForm($minutes, $minutesForms); } if ($remainingSeconds > 0 || empty($result)) { - $secondsForms = explode('|', __('def.seconds', [], 'messages')); + $secondsForms = explode('|', __('def.seconds')); $result[] = $remainingSeconds . ' ' . getPluralForm($remainingSeconds, $secondsForms); } diff --git a/app/Core/Http/Middlewares/MaintenanceMiddleware.php b/app/Core/Http/Middlewares/MaintenanceMiddleware.php index 08b94af..588b1f3 100644 --- a/app/Core/Http/Middlewares/MaintenanceMiddleware.php +++ b/app/Core/Http/Middlewares/MaintenanceMiddleware.php @@ -19,7 +19,9 @@ public function __invoke(FluteRequest $request, \Closure $next) return $next($request); } - abort_if((bool) config('app.maintenance_mode') === false || is_debug(), 503, __('def.maintenance_mode')); + if( config('app.maintenance_mode') && !is_debug() ) { + return $this->error(config('app.maintenance_message') ? __(config('app.maintenance_message')) : __('def.maintenance_mode'), 503); + } return $next($request); } diff --git a/app/Core/Http/Middlewares/RedirectsMiddleware.php b/app/Core/Listeners/RedirectsListener.php similarity index 59% rename from app/Core/Http/Middlewares/RedirectsMiddleware.php rename to app/Core/Listeners/RedirectsListener.php index 7bc12ad..f5f2100 100644 --- a/app/Core/Http/Middlewares/RedirectsMiddleware.php +++ b/app/Core/Listeners/RedirectsListener.php @@ -1,56 +1,59 @@ select()->where('fromUrl', $request->getRequestUri())->load('conditionGroups')->load('conditionGroups.conditions')->fetchAll(); if ($redirects) { foreach ($redirects as $redirect) { - if ($this->checkConditions($redirect, $request)) { - return new Response('', Response::HTTP_FOUND, ['Location' => $redirect->getToUrl()]); + if (self::checkConditions($redirect, $request)) { + $newResponse = redirect($redirect->getToUrl())->send(); + $event->setResponse($newResponse); + return; } } } - - return $next($request); } - private function checkConditions(Redirect $redirect, FluteRequest $request) + private static function checkConditions(Redirect $redirect, FluteRequest $request) { foreach ($redirect->getConditions() as $group) { - if ($this->checkConditionGroup($group, $request)) { + if (self::checkConditionGroup($group, $request)) { return true; } } return false; } - private function checkConditionGroup($group, FluteRequest $request) + private static function checkConditionGroup($group, FluteRequest $request) { foreach ($group->getConditions() as $condition) { - if (!$this->checkCondition($condition, $request)) { + if (!self::checkCondition($condition, $request)) { return false; } } return true; } - private function checkCondition(RedirectCondition $condition, FluteRequest $request) + private static function checkCondition(RedirectCondition $condition, FluteRequest $request) { - $value = $this->getRequestValue($condition->getType(), $condition->getValue(), $request); + $value = self::getRequestValue($condition->getType(), $condition->getValue(), $request); if (empty($condition->getValue())) { return true; @@ -74,15 +77,13 @@ private function checkCondition(RedirectCondition $condition, FluteRequest $requ } } - private function getRequestValue($field, $conditionValue, FluteRequest $request) + private static function getRequestValue($field, $conditionValue, FluteRequest $request) { switch ($field) { case 'ip': return $request->getClientIp(); case 'cookie': return $request->cookies->all(); - // case 'country': - // return $this->getCountryFromIp($request->getClientIp()); case 'referer': return $request->headers->get('referer'); case 'request_method': @@ -97,14 +98,4 @@ private function getRequestValue($field, $conditionValue, FluteRequest $request) return null; } } - - // private function getCountryFromIp($ip) - // { - // try { - // $record = $this->geoIpReader->country($ip); - // return $record->country->isoCode; - // } catch (\Exception $e) { - // return null; - // } - // } -} \ No newline at end of file +} diff --git a/app/Core/PhosphorIcons/PhosphorIconsParser.php b/app/Core/PhosphorIcons/PhosphorIconsParser.php new file mode 100644 index 0000000..f238f6f --- /dev/null +++ b/app/Core/PhosphorIcons/PhosphorIconsParser.php @@ -0,0 +1,32 @@ +icons)) + $this->parseIcons(); + + return $this->icons; + } + + protected function parseIcons() + { + if (cache()->has(self::CACHE_KEY)) + $this->icons = cache()->get(self::CACHE_KEY); + + $file = path(self::FILE_PATH); + + if (file_exists($file) && is_readable($file)) { + $this->icons = json_decode(file_get_contents($file), true); + + cache()->set(self::CACHE_KEY, $this->icons); + } + } +} \ No newline at end of file diff --git a/app/Core/PhosphorIcons/icons.json b/app/Core/PhosphorIcons/icons.json new file mode 100644 index 0000000..d731801 --- /dev/null +++ b/app/Core/PhosphorIcons/icons.json @@ -0,0 +1,1532 @@ +[ + "acorn", + "address-book", + "address-book-tabs", + "air-traffic-control", + "airplane", + "airplane-in-flight", + "airplane-landing", + "airplane-takeoff", + "airplane-taxiing", + "airplane-tilt", + "airplay", + "alarm", + "alien", + "align-bottom", + "align-bottom-simple", + "align-center-horizontal", + "align-center-horizontal-simple", + "align-center-vertical", + "align-center-vertical-simple", + "align-left", + "align-left-simple", + "align-right", + "align-right-simple", + "align-top", + "align-top-simple", + "amazon-logo", + "ambulance", + "anchor", + "anchor-simple", + "android-logo", + "angle", + "angular-logo", + "aperture", + "app-store-logo", + "app-window", + "apple-logo", + "apple-podcasts-logo", + "approximate-equals", + "archive", + "armchair", + "arrow-arc-left", + "arrow-arc-right", + "arrow-bend-double-up-left", + "arrow-bend-double-up-right", + "arrow-bend-down-left", + "arrow-bend-down-right", + "arrow-bend-left-down", + "arrow-bend-left-up", + "arrow-bend-right-down", + "arrow-bend-right-up", + "arrow-bend-up-left", + "arrow-bend-up-right", + "arrow-circle-down", + "arrow-circle-down-left", + "arrow-circle-down-right", + "arrow-circle-left", + "arrow-circle-right", + "arrow-circle-up", + "arrow-circle-up-left", + "arrow-circle-up-right", + "arrow-clockwise", + "arrow-counter-clockwise", + "arrow-down", + "arrow-down-left", + "arrow-down-right", + "arrow-elbow-down-left", + "arrow-elbow-down-right", + "arrow-elbow-left", + "arrow-elbow-left-down", + "arrow-elbow-left-up", + "arrow-elbow-right", + "arrow-elbow-right-down", + "arrow-elbow-right-up", + "arrow-elbow-up-left", + "arrow-elbow-up-right", + "arrow-fat-down", + "arrow-fat-left", + "arrow-fat-line-down", + "arrow-fat-line-left", + "arrow-fat-line-right", + "arrow-fat-line-up", + "arrow-fat-lines-down", + "arrow-fat-lines-left", + "arrow-fat-lines-right", + "arrow-fat-lines-up", + "arrow-fat-right", + "arrow-fat-up", + "arrow-left", + "arrow-line-down", + "arrow-line-down-left", + "arrow-line-down-right", + "arrow-line-left", + "arrow-line-right", + "arrow-line-up", + "arrow-line-up-left", + "arrow-line-up-right", + "arrow-right", + "arrow-square-down", + "arrow-square-down-left", + "arrow-square-down-right", + "arrow-square-in", + "arrow-square-left", + "arrow-square-out", + "arrow-square-right", + "arrow-square-up", + "arrow-square-up-left", + "arrow-square-up-right", + "arrow-u-down-left", + "arrow-u-down-right", + "arrow-u-left-down", + "arrow-u-left-up", + "arrow-u-right-down", + "arrow-u-right-up", + "arrow-u-up-left", + "arrow-u-up-right", + "arrow-up", + "arrow-up-left", + "arrow-up-right", + "arrows-clockwise", + "arrows-counter-clockwise", + "arrows-down-up", + "arrows-horizontal", + "arrows-in", + "arrows-in-cardinal", + "arrows-in-line-horizontal", + "arrows-in-line-vertical", + "arrows-in-simple", + "arrows-left-right", + "arrows-merge", + "arrows-out", + "arrows-out-cardinal", + "arrows-out-line-horizontal", + "arrows-out-line-vertical", + "arrows-out-simple", + "arrows-split", + "arrows-vertical", + "article", + "article-medium", + "article-ny-times", + "asclepius", + "caduceus", + "asterisk", + "asterisk-simple", + "at", + "atom", + "avocado", + "axe", + "baby", + "baby-carriage", + "backpack", + "backspace", + "bag", + "bag-simple", + "balloon", + "bandaids", + "bank", + "barbell", + "barcode", + "barn", + "barricade", + "baseball", + "baseball-cap", + "baseball-helmet", + "basket", + "basketball", + "bathtub", + "battery-charging", + "battery-charging-vertical", + "battery-empty", + "battery-full", + "battery-high", + "battery-low", + "battery-medium", + "battery-plus", + "battery-plus-vertical", + "battery-vertical-empty", + "battery-vertical-full", + "battery-vertical-high", + "battery-vertical-low", + "battery-vertical-medium", + "battery-warning", + "battery-warning-vertical", + "beach-ball", + "beanie", + "bed", + "beer-bottle", + "beer-stein", + "behance-logo", + "bell", + "bell-ringing", + "bell-simple", + "bell-simple-ringing", + "bell-simple-slash", + "bell-simple-z", + "bell-slash", + "bell-z", + "belt", + "bezier-curve", + "bicycle", + "binary", + "binoculars", + "biohazard", + "bird", + "blueprint", + "bluetooth", + "bluetooth-connected", + "bluetooth-slash", + "bluetooth-x", + "boat", + "bomb", + "bone", + "book", + "book-bookmark", + "book-open", + "book-open-text", + "book-open-user", + "bookmark", + "bookmark-simple", + "bookmarks", + "bookmarks-simple", + "books", + "boot", + "boules", + "bounding-box", + "bowl-food", + "bowl-steam", + "bowling-ball", + "box-arrow-down", + "archive-box", + "box-arrow-up", + "boxing-glove", + "brackets-angle", + "brackets-curly", + "brackets-round", + "brackets-square", + "brain", + "brandy", + "bread", + "bridge", + "briefcase", + "briefcase-metal", + "broadcast", + "broom", + "browser", + "browsers", + "bug", + "bug-beetle", + "bug-droid", + "building", + "building-apartment", + "building-office", + "buildings", + "bulldozer", + "bus", + "butterfly", + "cable-car", + "cactus", + "cake", + "calculator", + "calendar", + "calendar-blank", + "calendar-check", + "calendar-dot", + "calendar-dots", + "calendar-heart", + "calendar-minus", + "calendar-plus", + "calendar-slash", + "calendar-star", + "calendar-x", + "call-bell", + "camera", + "camera-plus", + "camera-rotate", + "camera-slash", + "campfire", + "car", + "car-battery", + "car-profile", + "car-simple", + "cardholder", + "cards", + "cards-three", + "caret-circle-double-down", + "caret-circle-double-left", + "caret-circle-double-right", + "caret-circle-double-up", + "caret-circle-down", + "caret-circle-left", + "caret-circle-right", + "caret-circle-up", + "caret-circle-up-down", + "caret-double-down", + "caret-double-left", + "caret-double-right", + "caret-double-up", + "caret-down", + "caret-left", + "caret-line-down", + "caret-line-left", + "caret-line-right", + "caret-line-up", + "caret-right", + "caret-up", + "caret-up-down", + "carrot", + "cash-register", + "cassette-tape", + "castle-turret", + "cat", + "cell-signal-full", + "cell-signal-high", + "cell-signal-low", + "cell-signal-medium", + "cell-signal-none", + "cell-signal-slash", + "cell-signal-x", + "cell-tower", + "certificate", + "chair", + "chalkboard", + "chalkboard-simple", + "chalkboard-teacher", + "champagne", + "charging-station", + "chart-bar", + "chart-bar-horizontal", + "chart-donut", + "chart-line", + "chart-line-down", + "chart-line-up", + "chart-pie", + "chart-pie-slice", + "chart-polar", + "chart-scatter", + "chat", + "chat-centered", + "chat-centered-dots", + "chat-centered-slash", + "chat-centered-text", + "chat-circle", + "chat-circle-dots", + "chat-circle-slash", + "chat-circle-text", + "chat-dots", + "chat-slash", + "chat-teardrop", + "chat-teardrop-dots", + "chat-teardrop-slash", + "chat-teardrop-text", + "chat-text", + "chats", + "chats-circle", + "chats-teardrop", + "check", + "check-circle", + "check-fat", + "check-square", + "check-square-offset", + "checkerboard", + "checks", + "cheers", + "cheese", + "chef-hat", + "cherries", + "church", + "cigarette", + "cigarette-slash", + "circle", + "circle-dashed", + "circle-half", + "circle-half-tilt", + "circle-notch", + "circles-four", + "circles-three", + "circles-three-plus", + "circuitry", + "city", + "clipboard", + "clipboard-text", + "clock", + "clock-afternoon", + "clock-clockwise", + "clock-countdown", + "clock-counter-clockwise", + "clock-user", + "closed-captioning", + "cloud", + "cloud-arrow-down", + "cloud-arrow-up", + "cloud-check", + "cloud-fog", + "cloud-lightning", + "cloud-moon", + "cloud-rain", + "cloud-slash", + "cloud-snow", + "cloud-sun", + "cloud-warning", + "cloud-x", + "clover", + "club", + "coat-hanger", + "coda-logo", + "code", + "code-block", + "code-simple", + "codepen-logo", + "codesandbox-logo", + "coffee", + "coffee-bean", + "coin", + "coin-vertical", + "coins", + "columns", + "columns-plus-left", + "columns-plus-right", + "command", + "compass", + "compass-rose", + "compass-tool", + "computer-tower", + "confetti", + "contactless-payment", + "control", + "cookie", + "cooking-pot", + "copy", + "copy-simple", + "copyleft", + "copyright", + "corners-in", + "corners-out", + "couch", + "court-basketball", + "cow", + "cowboy-hat", + "cpu", + "crane", + "crane-tower", + "credit-card", + "cricket", + "crop", + "cross", + "crosshair", + "crosshair-simple", + "crown", + "crown-cross", + "crown-simple", + "cube", + "cube-focus", + "cube-transparent", + "currency-btc", + "currency-circle-dollar", + "currency-cny", + "currency-dollar", + "currency-dollar-simple", + "currency-eth", + "currency-eur", + "currency-gbp", + "currency-inr", + "currency-jpy", + "currency-krw", + "currency-kzt", + "currency-ngn", + "currency-rub", + "cursor", + "cursor-click", + "cursor-text", + "cylinder", + "database", + "desk", + "desktop", + "desktop-tower", + "detective", + "dev-to-logo", + "device-mobile", + "device-mobile-camera", + "device-mobile-slash", + "device-mobile-speaker", + "device-rotate", + "device-tablet", + "device-tablet-camera", + "device-tablet-speaker", + "devices", + "diamond", + "diamonds-four", + "dice-five", + "dice-four", + "dice-one", + "dice-six", + "dice-three", + "dice-two", + "disc", + "disco-ball", + "discord-logo", + "divide", + "dna", + "dog", + "door", + "door-open", + "dot", + "dot-outline", + "dots-nine", + "dots-six", + "dots-six-vertical", + "dots-three", + "dots-three-circle", + "dots-three-circle-vertical", + "dots-three-outline", + "dots-three-outline-vertical", + "dots-three-vertical", + "download", + "download-simple", + "dress", + "dresser", + "dribbble-logo", + "drone", + "drop", + "drop-half", + "drop-half-bottom", + "drop-simple", + "drop-slash", + "dropbox-logo", + "ear", + "ear-slash", + "egg", + "egg-crack", + "eject", + "eject-simple", + "elevator", + "empty", + "engine", + "envelope", + "envelope-open", + "envelope-simple", + "envelope-simple-open", + "equalizer", + "equals", + "eraser", + "escalator-down", + "escalator-up", + "exam", + "exclamation-mark", + "exclude", + "exclude-square", + "export", + "eye", + "eye-closed", + "eye-slash", + "eyedropper", + "eyedropper-sample", + "eyeglasses", + "eyes", + "face-mask", + "facebook-logo", + "factory", + "faders", + "faders-horizontal", + "fallout-shelter", + "fan", + "farm", + "fast-forward", + "fast-forward-circle", + "feather", + "fediverse-logo", + "figma-logo", + "file", + "file-archive", + "file-arrow-down", + "file-arrow-up", + "file-audio", + "file-c", + "file-c-sharp", + "file-cloud", + "file-code", + "file-cpp", + "file-css", + "file-csv", + "file-dashed", + "file-dotted", + "file-doc", + "file-html", + "file-image", + "file-ini", + "file-jpg", + "file-js", + "file-jsx", + "file-lock", + "file-magnifying-glass", + "file-search", + "file-md", + "file-minus", + "file-pdf", + "file-plus", + "file-png", + "file-ppt", + "file-py", + "file-rs", + "file-sql", + "file-svg", + "file-text", + "file-ts", + "file-tsx", + "file-txt", + "file-video", + "file-vue", + "file-x", + "file-xls", + "file-zip", + "files", + "film-reel", + "film-script", + "film-slate", + "film-strip", + "fingerprint", + "fingerprint-simple", + "finn-the-human", + "fire", + "fire-extinguisher", + "fire-simple", + "fire-truck", + "first-aid", + "first-aid-kit", + "fish", + "fish-simple", + "flag", + "flag-banner", + "flag-banner-fold", + "flag-checkered", + "flag-pennant", + "flame", + "flashlight", + "flask", + "flip-horizontal", + "flip-vertical", + "floppy-disk", + "floppy-disk-back", + "flow-arrow", + "flower", + "flower-lotus", + "flower-tulip", + "flying-saucer", + "folder", + "folder-notch", + "folder-dashed", + "folder-dotted", + "folder-lock", + "folder-minus", + "folder-notch-minus", + "folder-open", + "folder-notch-open", + "folder-plus", + "folder-notch-plus", + "folder-simple", + "folder-simple-dashed", + "folder-simple-dotted", + "folder-simple-lock", + "folder-simple-minus", + "folder-simple-plus", + "folder-simple-star", + "folder-simple-user", + "folder-star", + "folder-user", + "folders", + "football", + "football-helmet", + "footprints", + "fork-knife", + "four-k", + "frame-corners", + "framer-logo", + "function", + "funnel", + "funnel-simple", + "funnel-simple-x", + "funnel-x", + "game-controller", + "garage", + "gas-can", + "gas-pump", + "gauge", + "gavel", + "gear", + "gear-fine", + "gear-six", + "gender-female", + "gender-intersex", + "gender-male", + "gender-neuter", + "gender-nonbinary", + "gender-transgender", + "ghost", + "gif", + "gift", + "git-branch", + "git-commit", + "git-diff", + "git-fork", + "git-merge", + "git-pull-request", + "github-logo", + "gitlab-logo", + "gitlab-logo-simple", + "globe", + "globe-hemisphere-east", + "globe-hemisphere-west", + "globe-simple", + "globe-simple-x", + "globe-stand", + "globe-x", + "goggles", + "golf", + "goodreads-logo", + "google-cardboard-logo", + "google-chrome-logo", + "google-drive-logo", + "google-logo", + "google-photos-logo", + "google-play-logo", + "google-podcasts-logo", + "gps", + "gps-fix", + "gps-slash", + "gradient", + "graduation-cap", + "grains", + "grains-slash", + "graph", + "graphics-card", + "greater-than", + "greater-than-or-equal", + "grid-four", + "grid-nine", + "guitar", + "hair-dryer", + "hamburger", + "hammer", + "hand", + "hand-arrow-down", + "hand-arrow-up", + "hand-coins", + "hand-deposit", + "hand-eye", + "hand-fist", + "hand-grabbing", + "hand-heart", + "hand-palm", + "hand-peace", + "hand-pointing", + "hand-soap", + "hand-swipe-left", + "hand-swipe-right", + "hand-tap", + "hand-waving", + "hand-withdraw", + "handbag", + "handbag-simple", + "hands-clapping", + "hands-praying", + "handshake", + "hard-drive", + "hard-drives", + "hard-hat", + "hash", + "hash-straight", + "head-circuit", + "headlights", + "headphones", + "headset", + "heart", + "heart-break", + "heart-half", + "heart-straight", + "heart-straight-break", + "heartbeat", + "hexagon", + "high-definition", + "high-heel", + "highlighter", + "highlighter-circle", + "hockey", + "hoodie", + "horse", + "hospital", + "hourglass", + "hourglass-high", + "hourglass-low", + "hourglass-medium", + "hourglass-simple", + "hourglass-simple-high", + "hourglass-simple-low", + "hourglass-simple-medium", + "house", + "house-line", + "house-simple", + "hurricane", + "ice-cream", + "identification-badge", + "identification-card", + "image", + "image-broken", + "image-square", + "images", + "images-square", + "infinity", + "lemniscate", + "info", + "instagram-logo", + "intersect", + "intersect-square", + "intersect-three", + "intersection", + "invoice", + "island", + "jar", + "jar-label", + "jeep", + "joystick", + "kanban", + "key", + "key-return", + "keyboard", + "keyhole", + "knife", + "ladder", + "ladder-simple", + "lamp", + "lamp-pendant", + "laptop", + "lasso", + "lastfm-logo", + "layout", + "leaf", + "lectern", + "lego", + "lego-smiley", + "less-than", + "less-than-or-equal", + "letter-circle-h", + "letter-circle-p", + "letter-circle-v", + "lifebuoy", + "lightbulb", + "lightbulb-filament", + "lighthouse", + "lightning", + "lightning-a", + "lightning-slash", + "line-segment", + "line-segments", + "line-vertical", + "link", + "link-break", + "link-simple", + "link-simple-break", + "link-simple-horizontal", + "link-simple-horizontal-break", + "linkedin-logo", + "linktree-logo", + "linux-logo", + "list", + "list-bullets", + "list-checks", + "list-dashes", + "list-heart", + "list-magnifying-glass", + "list-numbers", + "list-plus", + "list-star", + "lock", + "lock-key", + "lock-key-open", + "lock-laminated", + "lock-laminated-open", + "lock-open", + "lock-simple", + "lock-simple-open", + "lockers", + "log", + "magic-wand", + "magnet", + "magnet-straight", + "magnifying-glass", + "magnifying-glass-minus", + "magnifying-glass-plus", + "mailbox", + "map-pin", + "map-pin-area", + "map-pin-line", + "map-pin-plus", + "map-pin-simple", + "map-pin-simple-area", + "map-pin-simple-line", + "map-trifold", + "markdown-logo", + "marker-circle", + "martini", + "mask-happy", + "mask-sad", + "mastodon-logo", + "math-operations", + "matrix-logo", + "medal", + "medal-military", + "medium-logo", + "megaphone", + "megaphone-simple", + "member-of", + "memory", + "messenger-logo", + "meta-logo", + "meteor", + "metronome", + "microphone", + "microphone-slash", + "microphone-stage", + "microscope", + "microsoft-excel-logo", + "microsoft-outlook-logo", + "microsoft-powerpoint-logo", + "microsoft-teams-logo", + "microsoft-word-logo", + "minus", + "minus-circle", + "minus-square", + "money", + "money-wavy", + "monitor", + "monitor-arrow-up", + "monitor-play", + "moon", + "moon-stars", + "moped", + "moped-front", + "mosque", + "motorcycle", + "mountains", + "mouse", + "mouse-left-click", + "mouse-middle-click", + "mouse-right-click", + "mouse-scroll", + "mouse-simple", + "music-note", + "music-note-simple", + "music-notes", + "music-notes-minus", + "music-notes-plus", + "music-notes-simple", + "navigation-arrow", + "needle", + "network", + "network-slash", + "network-x", + "newspaper", + "newspaper-clipping", + "not-equals", + "not-member-of", + "not-subset-of", + "not-superset-of", + "notches", + "note", + "note-blank", + "note-pencil", + "notebook", + "notepad", + "notification", + "notion-logo", + "nuclear-plant", + "number-circle-eight", + "number-circle-five", + "number-circle-four", + "number-circle-nine", + "number-circle-one", + "number-circle-seven", + "number-circle-six", + "number-circle-three", + "number-circle-two", + "number-circle-zero", + "number-eight", + "number-five", + "number-four", + "number-nine", + "number-one", + "number-seven", + "number-six", + "number-square-eight", + "number-square-five", + "number-square-four", + "number-square-nine", + "number-square-one", + "number-square-seven", + "number-square-six", + "number-square-three", + "number-square-two", + "number-square-zero", + "number-three", + "number-two", + "number-zero", + "numpad", + "nut", + "ny-times-logo", + "octagon", + "office-chair", + "onigiri", + "open-ai-logo", + "option", + "orange", + "orange-slice", + "oven", + "package", + "paint-brush", + "paint-brush-broad", + "paint-brush-household", + "paint-bucket", + "paint-roller", + "palette", + "panorama", + "pants", + "paper-plane", + "paper-plane-right", + "paper-plane-tilt", + "paperclip", + "paperclip-horizontal", + "parachute", + "paragraph", + "parallelogram", + "park", + "password", + "path", + "patreon-logo", + "pause", + "pause-circle", + "paw-print", + "paypal-logo", + "peace", + "pen", + "pen-nib", + "pen-nib-straight", + "pencil", + "pencil-circle", + "pencil-line", + "pencil-ruler", + "pencil-simple", + "pencil-simple-line", + "pencil-simple-slash", + "pencil-slash", + "pentagon", + "pentagram", + "pepper", + "percent", + "person", + "person-arms-spread", + "person-simple", + "person-simple-bike", + "person-simple-circle", + "person-simple-hike", + "person-simple-run", + "person-simple-ski", + "person-simple-snowboard", + "person-simple-swim", + "person-simple-tai-chi", + "person-simple-throw", + "person-simple-walk", + "perspective", + "phone", + "phone-call", + "phone-disconnect", + "phone-incoming", + "phone-list", + "phone-outgoing", + "phone-pause", + "phone-plus", + "phone-slash", + "phone-transfer", + "phone-x", + "phosphor-logo", + "pi", + "piano-keys", + "picnic-table", + "picture-in-picture", + "piggy-bank", + "pill", + "ping-pong", + "pint-glass", + "pinterest-logo", + "pinwheel", + "pipe", + "pipe-wrench", + "pix-logo", + "pizza", + "placeholder", + "planet", + "plant", + "play", + "play-circle", + "play-pause", + "playlist", + "plug", + "plug-charging", + "plugs", + "plugs-connected", + "plus", + "plus-circle", + "plus-minus", + "plus-square", + "poker-chip", + "police-car", + "polygon", + "popcorn", + "popsicle", + "potted-plant", + "power", + "prescription", + "presentation", + "presentation-chart", + "printer", + "prohibit", + "prohibit-inset", + "projector-screen", + "projector-screen-chart", + "pulse", + "activity", + "push-pin", + "push-pin-simple", + "push-pin-simple-slash", + "push-pin-slash", + "puzzle-piece", + "qr-code", + "question", + "question-mark", + "queue", + "quotes", + "rabbit", + "racquet", + "radical", + "radio", + "radio-button", + "radioactive", + "rainbow", + "rainbow-cloud", + "ranking", + "read-cv-logo", + "receipt", + "receipt-x", + "record", + "rectangle", + "rectangle-dashed", + "recycle", + "reddit-logo", + "repeat", + "repeat-once", + "replit-logo", + "resize", + "rewind", + "rewind-circle", + "road-horizon", + "robot", + "rocket", + "rocket-launch", + "rows", + "rows-plus-bottom", + "rows-plus-top", + "rss", + "rss-simple", + "rug", + "ruler", + "sailboat", + "scales", + "scan", + "scan-smiley", + "scissors", + "scooter", + "screencast", + "screwdriver", + "scribble", + "scribble-loop", + "scroll", + "seal", + "circle-wavy", + "seal-check", + "circle-wavy-check", + "seal-percent", + "seal-question", + "circle-wavy-question", + "seal-warning", + "circle-wavy-warning", + "seat", + "seatbelt", + "security-camera", + "selection", + "selection-all", + "selection-background", + "selection-foreground", + "selection-inverse", + "selection-plus", + "selection-slash", + "shapes", + "share", + "share-fat", + "share-network", + "shield", + "shield-check", + "shield-checkered", + "shield-chevron", + "shield-plus", + "shield-slash", + "shield-star", + "shield-warning", + "shipping-container", + "shirt-folded", + "shooting-star", + "shopping-bag", + "shopping-bag-open", + "shopping-cart", + "shopping-cart-simple", + "shovel", + "shower", + "shrimp", + "shuffle", + "shuffle-angular", + "shuffle-simple", + "sidebar", + "sidebar-simple", + "sigma", + "sign-in", + "sign-out", + "signature", + "signpost", + "sim-card", + "siren", + "sketch-logo", + "skip-back", + "skip-back-circle", + "skip-forward", + "skip-forward-circle", + "skull", + "skype-logo", + "slack-logo", + "sliders", + "sliders-horizontal", + "slideshow", + "smiley", + "smiley-angry", + "smiley-blank", + "smiley-meh", + "smiley-melting", + "smiley-nervous", + "smiley-sad", + "smiley-sticker", + "smiley-wink", + "smiley-x-eyes", + "snapchat-logo", + "sneaker", + "sneaker-move", + "snowflake", + "soccer-ball", + "sock", + "solar-panel", + "solar-roof", + "sort-ascending", + "sort-descending", + "soundcloud-logo", + "spade", + "sparkle", + "speaker-hifi", + "speaker-high", + "speaker-low", + "speaker-none", + "speaker-simple-high", + "speaker-simple-low", + "speaker-simple-none", + "speaker-simple-slash", + "speaker-simple-x", + "speaker-slash", + "speaker-x", + "speedometer", + "sphere", + "spinner", + "spinner-ball", + "spinner-gap", + "spiral", + "split-horizontal", + "split-vertical", + "spotify-logo", + "spray-bottle", + "square", + "square-half", + "square-half-bottom", + "square-logo", + "square-split-horizontal", + "square-split-vertical", + "squares-four", + "stack", + "stack-minus", + "stack-overflow-logo", + "stack-plus", + "stack-simple", + "stairs", + "stamp", + "standard-definition", + "star", + "star-and-crescent", + "star-four", + "star-half", + "star-of-david", + "steam-logo", + "steering-wheel", + "steps", + "stethoscope", + "sticker", + "stool", + "stop", + "stop-circle", + "storefront", + "strategy", + "stripe-logo", + "student", + "subset-of", + "subset-proper-of", + "subtitles", + "subtitles-slash", + "subtract", + "subtract-square", + "subway", + "suitcase", + "suitcase-rolling", + "suitcase-simple", + "sun", + "sun-dim", + "sun-horizon", + "sunglasses", + "superset-of", + "superset-proper-of", + "swap", + "swatches", + "swimming-pool", + "sword", + "synagogue", + "syringe", + "t-shirt", + "table", + "tabs", + "tag", + "tag-chevron", + "tag-simple", + "target", + "taxi", + "tea-bag", + "telegram-logo", + "television", + "television-simple", + "tennis-ball", + "tent", + "terminal", + "terminal-window", + "test-tube", + "text-a-underline", + "text-aa", + "text-align-center", + "text-align-justify", + "text-align-left", + "text-align-right", + "text-b", + "text-bolder", + "text-columns", + "text-h", + "text-h-five", + "text-h-four", + "text-h-one", + "text-h-six", + "text-h-three", + "text-h-two", + "text-indent", + "text-italic", + "text-outdent", + "text-strikethrough", + "text-subscript", + "text-superscript", + "text-t", + "text-t-slash", + "text-underline", + "textbox", + "thermometer", + "thermometer-cold", + "thermometer-hot", + "thermometer-simple", + "threads-logo", + "three-d", + "thumbs-down", + "thumbs-up", + "ticket", + "tidal-logo", + "tiktok-logo", + "tilde", + "timer", + "tip-jar", + "tipi", + "tire", + "toggle-left", + "toggle-right", + "toilet", + "toilet-paper", + "toolbox", + "tooth", + "tornado", + "tote", + "tote-simple", + "towel", + "tractor", + "trademark", + "trademark-registered", + "traffic-cone", + "traffic-sign", + "traffic-signal", + "train", + "train-regional", + "train-simple", + "tram", + "translate", + "trash", + "trash-simple", + "tray", + "tray-arrow-down", + "archive-tray", + "tray-arrow-up", + "treasure-chest", + "tree", + "tree-evergreen", + "tree-palm", + "tree-structure", + "tree-view", + "trend-down", + "trend-up", + "triangle", + "triangle-dashed", + "trolley", + "trolley-suitcase", + "trophy", + "truck", + "truck-trailer", + "tumblr-logo", + "twitch-logo", + "twitter-logo", + "umbrella", + "umbrella-simple", + "union", + "unite", + "unite-square", + "upload", + "upload-simple", + "usb", + "user", + "user-check", + "user-circle", + "user-circle-check", + "user-circle-dashed", + "user-circle-gear", + "user-circle-minus", + "user-circle-plus", + "user-focus", + "user-gear", + "user-list", + "user-minus", + "user-plus", + "user-rectangle", + "user-sound", + "user-square", + "user-switch", + "users", + "users-four", + "users-three", + "van", + "vault", + "vector-three", + "vector-two", + "vibrate", + "video", + "video-camera", + "video-camera-slash", + "video-conference", + "vignette", + "vinyl-record", + "virtual-reality", + "virus", + "visor", + "voicemail", + "volleyball", + "wall", + "wallet", + "warehouse", + "warning", + "warning-circle", + "warning-diamond", + "warning-octagon", + "washing-machine", + "watch", + "wave-sawtooth", + "wave-sine", + "wave-square", + "wave-triangle", + "waveform", + "waveform-slash", + "waves", + "webcam", + "webcam-slash", + "webhooks-logo", + "wechat-logo", + "whatsapp-logo", + "wheelchair", + "wheelchair-motion", + "wifi-high", + "wifi-low", + "wifi-medium", + "wifi-none", + "wifi-slash", + "wifi-x", + "wind", + "windmill", + "windows-logo", + "wine", + "wrench", + "x", + "x-circle", + "x-logo", + "x-square", + "yarn", + "yin-yang", + "youtube-logo" +] \ No newline at end of file diff --git a/app/Core/Router/RouteDispatcher.php b/app/Core/Router/RouteDispatcher.php index 700279a..2340f35 100644 --- a/app/Core/Router/RouteDispatcher.php +++ b/app/Core/Router/RouteDispatcher.php @@ -9,7 +9,6 @@ use Flute\Core\Exceptions\ForcedRedirectException; use Flute\Core\Http\Middlewares\BanCheckMiddleware; use Flute\Core\Http\Middlewares\MaintenanceMiddleware; -use Flute\Core\Http\Middlewares\RedirectsMiddleware; use Flute\Core\Router\RouteGroup; use Flute\Core\Support\FluteRequest; use Flute\Core\Template\Template; @@ -37,7 +36,6 @@ class RouteDispatcher protected array $defaultMiddlewares = [ MaintenanceMiddleware::class, BanCheckMiddleware::class, - RedirectsMiddleware::class ]; @@ -119,30 +117,11 @@ public function handle(FluteRequest $request): Response } catch (HttpException $exception) { return response()->error($exception->getStatusCode(), $exception->getMessage()); } catch (\Exception $exception) { - if (!is_debug()) + if (!is_debug()) { return response()->error(500, __('def.internal_server_error')); - else - throw $exception; - } - - try { - // Ensure middleware is run even on error - $middlewares = $this->handleMiddlewares($this->defaultMiddlewares); - $middlewareRunner = new MiddlewareRunner($middlewares, $request, function () use ($response) { - return $response; - }); - $response = $middlewareRunner->run(); - } catch (ResourceNotFoundException $exception) { - $response = response()->error(404, __('def.page_not_found')); - } catch (MethodNotAllowedException $exception) { - $response = response()->error(405, __('def.method_not_allowed')); - } catch (ForcedRedirectException $exception) { - $response = response()->redirect($exception->getUrl(), $exception->getStatusCode()); - } catch (\Exception $exception) { - if (!is_debug()) - return response()->error(500, __('def.internal_server_error')); - else + } else { throw $exception; + } } // Dispatches a routing finished event. diff --git a/app/Core/ServiceProviders/EventsServiceProvider.php b/app/Core/ServiceProviders/EventsServiceProvider.php index 167b98e..e7424f4 100644 --- a/app/Core/ServiceProviders/EventsServiceProvider.php +++ b/app/Core/ServiceProviders/EventsServiceProvider.php @@ -2,6 +2,8 @@ namespace Flute\Core\ServiceProviders; +use Flute\Core\Events\RoutingFinishedEvent; +use Flute\Core\Listeners\RedirectsListener; use Flute\Core\Support\AbstractServiceProvider; use Psr\EventDispatcher\EventDispatcherInterface; use Flute\Core\Support\FluteEventDispatcher; @@ -32,6 +34,8 @@ public function register(ContainerBuilder $containerBuilder): void * * @return void */ - public function boot( \DI\Container $container ): void - {} + public function boot(\DI\Container $container): void + { + $container->get('events')->addListener(RoutingFinishedEvent::NAME, [RedirectsListener::class, 'onRoutingFinished']); + } } diff --git a/app/Core/ServiceProviders/RequestServiceProvider.php b/app/Core/ServiceProviders/RequestServiceProvider.php index d651a09..9627c39 100644 --- a/app/Core/ServiceProviders/RequestServiceProvider.php +++ b/app/Core/ServiceProviders/RequestServiceProvider.php @@ -34,7 +34,7 @@ public function boot(Container $container) : void // Cloudflare bypass FluteRequest::setTrustedProxies( ['REMOTE_ADDR'], - FluteRequest::HEADER_X_FORWARDED_FOR + Request::HEADER_X_FORWARDED_FOR ); } } diff --git a/app/Core/Services/ConfigurationService.php b/app/Core/Services/ConfigurationService.php index 0a34620..337267d 100644 --- a/app/Core/Services/ConfigurationService.php +++ b/app/Core/Services/ConfigurationService.php @@ -150,11 +150,13 @@ public function getExpectedConfig(): array "app" => Expect::structure([ "name" => Expect::string("Flute")->required(), "footer_name" => Expect::string(""), + "footer_html" => Expect::string(""), "url" => Expect::string()->required(), "steam_api" => Expect::string()->required(), "debug_ips" => Expect::array()->required(), "debug" => Expect::bool(true)->required(), "maintenance_mode" => Expect::bool(false), + "maintenance_message" => Expect::string(""), "discord_link_roles" => Expect::bool(false), "mode" => Expect::string("performance")->required(), "key" => Expect::string()->required(), @@ -165,6 +167,7 @@ public function getExpectedConfig(): array "flute_copyright" => Expect::bool(true)->required(), "timezone" => Expect::string()->required(), "notifications" => Expect::string('all')->required(), + "notifications_new_view" => Expect::bool(false), "widget_placeholders" => Expect::bool(true), ]), "lk" => Expect::structure([ diff --git a/app/Core/Services/NavbarService.php b/app/Core/Services/NavbarService.php index 283ef24..10fe638 100644 --- a/app/Core/Services/NavbarService.php +++ b/app/Core/Services/NavbarService.php @@ -25,7 +25,7 @@ public function __construct(NavbarItemFormat $format) if (!is_installed()) return; - $this->performance = (bool) (app('app.mode') == App::PERFORMANCE_MODE); + $this->performance = is_performance(); $this->format = $format; @@ -55,15 +55,15 @@ public function add(NavbarItem $item): self * * @return array */ - public function all(): array + public function all(bool $ignoreAuthRules = false): array { - return $this->cachedNavbarItems; + return $ignoreAuthRules ? $this->getDefaultNavbarItems(true) : $this->cachedNavbarItems; } /** * Sets the default navbar items by fetching them from the database */ - protected function getDefaultNavbarItems(): array + protected function getDefaultNavbarItems(bool $ignoreAuth = false): array { $navbarItems = $this->getNavbarItemRepository()->select()->load('roles')->orderBy('position', 'asc')->where([ 'parent_id' => null, @@ -72,7 +72,7 @@ protected function getDefaultNavbarItems(): array $formattedItems = []; foreach ($navbarItems as $item) { - if ($this->hasAccess($item)) { + if ($this->hasAccess($item, $ignoreAuth)) { $formattedItem = $this->format->format($item); $formattedItem['children'] = $this->getChildren($item->id); $formattedItems[] = $formattedItem; @@ -116,17 +116,19 @@ protected function getChildren(int $parentId): array * * @return bool */ - public function hasAccess(NavbarItem $item): bool + public function hasAccess(NavbarItem $item, bool $ignoreAuth = false): bool { $isLoggedIn = user()->isLoggedIn(); - // Item visibility constraints - if ($item->visibleOnlyForGuests && $isLoggedIn) { - return false; - } + if (!$ignoreAuth) { + // Item visibility constraints + if ($item->visibleOnlyForGuests && $isLoggedIn) { + return false; + } - if ($item->visibleOnlyForLoggedIn && !$isLoggedIn) { - return false; + if ($item->visibleOnlyForLoggedIn && !$isLoggedIn) { + return false; + } } // If no roles are specified, the item is accessible for logged in user diff --git a/app/Core/Support/ContentParser.php b/app/Core/Support/ContentParser.php index 1b87b40..d76b1f8 100644 --- a/app/Core/Support/ContentParser.php +++ b/app/Core/Support/ContentParser.php @@ -9,31 +9,13 @@ class ContentParser public static function replaceContent(string $content, $eventInstance, User $user): string { $content = self::replaceUserContent($content, $user); - $content = self::handleConditionalStatements($content, $eventInstance); - return preg_replace_callback('/\{(.*?)\}/', function ($matches) use ($eventInstance) { + return template()->getBlade()->runString(preg_replace_callback('/\{(.*?)\}/', function ($matches) use ($eventInstance) { return self::evaluateExpression($matches[1], $eventInstance); - }, $content); - } - - private static function handleConditionalStatements(string $content, $eventInstance): string - { - $pattern = '/@if\s*\(([^()]*(?:\((?:[^()]*(?:\([^()]*\))*[^()]*)*\))*[^()]*)\)(.*?)@endif/s'; - return preg_replace_callback($pattern, function ($matches) use ($eventInstance) { - $condition = trim($matches[1]); - $ifContent = $matches[2]; - - if (strpos($ifContent, '@else') !== false) { - list($ifContent, $elseContent) = explode('@else', $ifContent); - } else { - $elseContent = ''; - } - - // Evaluate the condition - $result = self::evaluateExpression($condition, $eventInstance); - - return $result ? $ifContent : $elseContent; - }, $content); + }, $content), [ + "event" => $eventInstance, + "user" => user()->getCurrentUser() + ]); } private static function evaluateExpression($expression, $eventInstance = null) @@ -68,7 +50,7 @@ private static function getNestedProperty($object, $expression) $current = call_user_func_array($func, $args); } elseif (is_object($current) && method_exists($current, $func)) { $current = call_user_func_array([$current, $func], $args); - } elseif(function_exists($func)) { + } elseif (function_exists($func)) { $current = call_user_func_array($func, $args); } else { return null; diff --git a/app/Core/Template/TemplateAssets.php b/app/Core/Template/TemplateAssets.php index 08b1be9..a250bc2 100644 --- a/app/Core/Template/TemplateAssets.php +++ b/app/Core/Template/TemplateAssets.php @@ -199,8 +199,8 @@ protected function processCdnAsset(string $url, string $type = "js"): string if ($content !== false) { file_put_contents($fullLocalPath, $content); } else { - if( Validators::isUrl($content) ) { - return $content; + if( Validators::isUrl($url) ) { + return $url; } } } diff --git a/app/Themes/standard/assets/styles/layouts/_footer.scss b/app/Themes/standard/assets/styles/layouts/_footer.scss index 94c1d90..5642b88 100644 --- a/app/Themes/standard/assets/styles/layouts/_footer.scss +++ b/app/Themes/standard/assets/styles/layouts/_footer.scss @@ -3,13 +3,16 @@ border-radius: $border-radius; background-color: $color-disabled; box-shadow: inset 0px 0px 0px 1px $color-white-5; - display: flex; - align-items: center; - justify-content: space-between; margin: 20px 0; - @media (max-width: 768px) { - flex-direction: column; + &-flex { + display: flex; + align-items: center; + justify-content: space-between; + + @media (max-width: 768px) { + flex-direction: column; + } } .project-name { @@ -132,7 +135,7 @@ opacity: 1; } - > div { + >div { display: flex; flex-direction: column; text-align: right; diff --git a/app/Themes/standard/components/footer.blade.php b/app/Themes/standard/components/footer.blade.php index 3d9212d..70f5a3f 100644 --- a/app/Themes/standard/components/footer.blade.php +++ b/app/Themes/standard/components/footer.blade.php @@ -3,67 +3,71 @@
+ {!! config('app.footer_html') !!}
diff --git a/app/Themes/standard/pages/lk/index.blade.php b/app/Themes/standard/pages/lk/index.blade.php index c9877f7..01a6f7f 100644 --- a/app/Themes/standard/pages/lk/index.blade.php +++ b/app/Themes/standard/pages/lk/index.blade.php @@ -18,7 +18,7 @@ @stack('container')
- @if (sizeof($payments) > 1) + @if (sizeof($payments) > 1 || (sizeof($payments) === 1 && sizeof($currencies) > 1))

@t('lk.page.choose_gateway')

@@ -41,19 +41,17 @@
@endif - @if (sizeof($payments) > 1) -
- @foreach ($payments as $key => $val) - - @endforeach -
- @endif +
+ @foreach ($payments as $key => $val) + + @endforeach +
@endif -
+

@t('lk.page.put_amount_and_promo')

@flash @@ -119,7 +117,7 @@ @push('footer')