diff --git a/.php-cs-fixer.cache b/.php-cs-fixer.cache
index e119f96..828a6dd 100644
--- a/.php-cs-fixer.cache
+++ b/.php-cs-fixer.cache
@@ -1 +1 @@
-{"php":"8.3.25","version":"3.64.0:v3.64.0#58dd9c931c785a79739310aef5178928305ffa67","indent":" ","lineEnding":"\n","rules":{"binary_operator_spaces":{"default":"at_least_single_space"},"blank_line_after_opening_tag":true,"blank_line_between_import_groups":true,"blank_lines_before_namespace":true,"braces_position":{"allow_single_line_empty_anonymous_classes":true},"class_definition":{"inline_constructor_arguments":false,"space_before_parenthesis":true},"compact_nullable_type_declaration":true,"declare_equal_normalize":true,"lowercase_cast":true,"lowercase_static_reference":true,"new_with_parentheses":true,"no_blank_lines_after_class_opening":true,"no_extra_blank_lines":{"tokens":["use"]},"no_leading_import_slash":true,"no_whitespace_in_blank_line":true,"ordered_class_elements":{"order":["use_trait"]},"ordered_imports":true,"return_type_declaration":true,"short_scalar_cast":true,"single_import_per_statement":{"group_to_single_imports":false},"single_space_around_construct":{"constructs_followed_by_a_single_space":["abstract","as","case","catch","class","const_import","do","else","elseif","final","finally","for","foreach","function","function_import","if","insteadof","interface","namespace","new","private","protected","public","static","switch","trait","try","use","use_lambda","while"],"constructs_preceded_by_a_single_space":["as","else","elseif","use_lambda"]},"single_trait_insert_per_statement":true,"ternary_operator_spaces":true,"unary_operator_spaces":{"only_dec_inc":true},"visibility_required":true,"blank_line_after_namespace":true,"constant_case":true,"control_structure_braces":true,"control_structure_continuation_position":true,"elseif":true,"function_declaration":true,"indentation_type":true,"line_ending":true,"lowercase_keywords":true,"method_argument_space":{"attribute_placement":"ignore","on_multiline":"ensure_fully_multiline"},"no_break_comment":true,"no_closing_tag":true,"no_multiple_statements_per_line":true,"no_space_around_double_colon":true,"no_spaces_after_function_name":true,"no_trailing_whitespace":true,"no_trailing_whitespace_in_comment":true,"single_blank_line_at_eof":true,"single_class_element_per_statement":{"elements":["property"]},"single_line_after_imports":true,"spaces_inside_parentheses":true,"statement_indentation":true,"switch_case_semicolon_to_colon":true,"switch_case_space":true,"encoding":true,"full_opening_tag":true,"array_syntax":{"syntax":"short"},"no_unused_imports":true,"single_quote":true,"trailing_comma_in_multiline":true},"hashes":{"fragments\/QuickNavigation\/Dropdown.php":"7cc52d767a1b8fa704e4d89c9a3e48a7","fragments\/QuickNavigation\/List.php":"e90ddecd29ce153eec1083841a3088e2","fragments\/QuickNavigation\/NoResult.php":"9b879a1abf902a8aa81cb9e6ce5d921a","fragments\/QuickNavigation\/MinibarList.php":"6c40eb3f991f48d730f45b8d222914b1","pages\/config.php":"cae53f73bf533cc8bb59dadf1cbdebe4","pages\/index.php":"daf2b1a819e7a27391553c599d053802","lib\/LinkMap\/QuickNavigationLinkMap.php":"3060d0975067e724f1dd427eadb02d47","lib\/Utility\/BuildNavigationArray.php":"d2a23cc394de4fd4e83bb34da8b3c0bc","lib\/Minibar\/ArticleHistoryElement.php":"fa606bdfb8e44afdcd46695f36b5d327","lib\/QuickNavigationApi.php":"4eabc25eae94790b9095085102dc278a","lib\/ApiFunction\/MenuRender.php":"fa555351a229780f110eba970ed42a59","lib\/ApiFunction\/MediaSearch.php":"04d4e816aa6766f1f2bf889482187287","lib\/Button\/FavoriteButton.php":"c8163f9adb12699453fe458de325515e","lib\/Button\/ButtonRegistry.php":"0ecf7951feeb0b3524fa1b8c92ac6288","lib\/Button\/YformButton.php":"cb3c1d7608735d18b5732b7425f3c14a","lib\/Button\/ArticleHistoryButton.php":"3851f59535b0647f184a5d706da08aba","lib\/Button\/ButtonInterface.php":"943bf3db82d39b6854401e16fe7e36b6","lib\/Button\/ArticleNavigationButton.php":"a81f2e97e73f235cba29ffcad4db1854","lib\/Button\/WatsonButton.php":"ef0d3641591e83b6e7dfec54008e36a8","lib\/Button\/CategoryButton.php":"3854696ad9b32dffad7d25d881fd2b18","lib\/Media\/MediaSorter.php":"4af98d56992a2e58b4d440ff1545af50","lib\/Media\/QuickNavigationMedia.php":"aa21d3042a12fc77d87e15ccb9c66319","lib\/QuickNavigation.php":"9a208b43632faa9d39923ff64c22f056","update.php":"d6e8377314743b0306a045ec165b99ea","boot.php":"85e4410621c51370487316f2c7de01b4"}}
\ No newline at end of file
+{"php":"8.4.12","version":"3.64.0:v3.64.0#58dd9c931c785a79739310aef5178928305ffa67","indent":" ","lineEnding":"\n","rules":{"binary_operator_spaces":{"default":"at_least_single_space"},"blank_line_after_opening_tag":true,"blank_line_between_import_groups":true,"blank_lines_before_namespace":true,"braces_position":{"allow_single_line_empty_anonymous_classes":true},"class_definition":{"inline_constructor_arguments":false,"space_before_parenthesis":true},"compact_nullable_type_declaration":true,"declare_equal_normalize":true,"lowercase_cast":true,"lowercase_static_reference":true,"new_with_parentheses":true,"no_blank_lines_after_class_opening":true,"no_extra_blank_lines":{"tokens":["use"]},"no_leading_import_slash":true,"no_whitespace_in_blank_line":true,"ordered_class_elements":{"order":["use_trait"]},"ordered_imports":true,"return_type_declaration":true,"short_scalar_cast":true,"single_import_per_statement":{"group_to_single_imports":false},"single_space_around_construct":{"constructs_followed_by_a_single_space":["abstract","as","case","catch","class","const_import","do","else","elseif","final","finally","for","foreach","function","function_import","if","insteadof","interface","namespace","new","private","protected","public","static","switch","trait","try","use","use_lambda","while"],"constructs_preceded_by_a_single_space":["as","else","elseif","use_lambda"]},"single_trait_insert_per_statement":true,"ternary_operator_spaces":true,"unary_operator_spaces":{"only_dec_inc":true},"visibility_required":true,"blank_line_after_namespace":true,"constant_case":true,"control_structure_braces":true,"control_structure_continuation_position":true,"elseif":true,"function_declaration":true,"indentation_type":true,"line_ending":true,"lowercase_keywords":true,"method_argument_space":{"attribute_placement":"ignore","on_multiline":"ensure_fully_multiline"},"no_break_comment":true,"no_closing_tag":true,"no_multiple_statements_per_line":true,"no_space_around_double_colon":true,"no_spaces_after_function_name":true,"no_trailing_whitespace":true,"no_trailing_whitespace_in_comment":true,"single_blank_line_at_eof":true,"single_class_element_per_statement":{"elements":["property"]},"single_line_after_imports":true,"spaces_inside_parentheses":true,"statement_indentation":true,"switch_case_semicolon_to_colon":true,"switch_case_space":true,"encoding":true,"full_opening_tag":true,"array_syntax":{"syntax":"short"},"no_unused_imports":true,"single_quote":true,"trailing_comma_in_multiline":true},"hashes":{"update.php":"599fd370563dc5811b440c0ae86309d7","fragments\/QuickNavigation\/NoResult.php":"9b879a1abf902a8aa81cb9e6ce5d921a","fragments\/QuickNavigation\/MinibarList.php":"6c40eb3f991f48d730f45b8d222914b1","fragments\/QuickNavigation\/List.php":"e90ddecd29ce153eec1083841a3088e2","fragments\/QuickNavigation\/Dropdown.php":"7cc52d767a1b8fa704e4d89c9a3e48a7","lib\/QuickNavigationApi.php":"4eabc25eae94790b9095085102dc278a","lib\/ApiFunction\/MenuRender.php":"fa555351a229780f110eba970ed42a59","lib\/ApiFunction\/MediaSearch.php":"04d4e816aa6766f1f2bf889482187287","lib\/QuickNavigation.php":"9a208b43632faa9d39923ff64c22f056","lib\/Minibar\/ArticleHistoryElement.php":"fa606bdfb8e44afdcd46695f36b5d327","lib\/Button\/ArticleNavigationButton.php":"a81f2e97e73f235cba29ffcad4db1854","lib\/Button\/YformButton.php":"cb3c1d7608735d18b5732b7425f3c14a","lib\/Button\/ButtonInterface.php":"943bf3db82d39b6854401e16fe7e36b6","lib\/Button\/ButtonRegistry.php":"0ecf7951feeb0b3524fa1b8c92ac6288","lib\/Button\/WatsonButton.php":"ef0d3641591e83b6e7dfec54008e36a8","lib\/Button\/ArticleHistoryButton.php":"3851f59535b0647f184a5d706da08aba","lib\/Button\/FavoriteButton.php":"c8163f9adb12699453fe458de325515e","lib\/Button\/CategoryButton.php":"3854696ad9b32dffad7d25d881fd2b18","lib\/LinkMap\/QuickNavigationLinkMap.php":"3060d0975067e724f1dd427eadb02d47","lib\/Utility\/BuildNavigationArray.php":"d2a23cc394de4fd4e83bb34da8b3c0bc","lib\/Media\/QuickNavigationMedia.php":"aa21d3042a12fc77d87e15ccb9c66319","lib\/Media\/MediaSorter.php":"4af98d56992a2e58b4d440ff1545af50","boot.php":"85e4410621c51370487316f2c7de01b4","pages\/index.php":"daf2b1a819e7a27391553c599d053802","pages\/config.php":"cae53f73bf533cc8bb59dadf1cbdebe4"}}
diff --git a/assets/quick-navigation.css b/assets/quick-navigation.css
index 149ce63..402094f 100644
--- a/assets/quick-navigation.css
+++ b/assets/quick-navigation.css
@@ -152,3 +152,65 @@
{
color: var(--quick-navigation-color-offline);
}
+
+/* Favoriten Sections */
+.quick-navigation-section-header {
+ padding: 10px 12px 6px;
+ font-weight: 600;
+ font-size: 11px;
+ text-transform: uppercase;
+ color: #666;
+ background-color: #f5f5f5;
+ border-top: 1px solid #e0e0e0;
+ margin: 0;
+}
+
+.quick-navigation-section-header:first-child {
+ border-top: none;
+}
+
+.quick-navigation-section-divider {
+ display: none;
+}
+
+.quick-navigation-addon-fav {
+ padding: 0;
+}
+
+.quick-navigation-addon-fav a {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 6px 12px;
+ color: inherit;
+ text-decoration: none;
+}
+
+.quick-navigation-addon-fav a:hover {
+ background-color: #f0f0f0;
+}
+
+.quick-navigation-addon-fav a i {
+ width: 16px;
+ text-align: center;
+ flex-shrink: 0;
+}
+
+/* Dark Theme Support */
+.rex-theme-dark .quick-navigation-section-header {
+ color: #aaa;
+ background-color: #2a2d33;
+ border-top-color: #404040;
+}
+
+.rex-theme-dark .quick-navigation-addon-fav a:hover {
+ background-color: #35383e;
+}
+
+.rex-theme-dark .quick-navigation-menu-header {
+ border-bottom-color: #404040;
+}
+
+.rex-theme-dark .quick-navigation-no-results {
+ background-color: rgba(42, 45, 51, 0.59);
+}
diff --git a/boot.php b/boot.php
index ebb0b4d..78cc1c7 100644
--- a/boot.php
+++ b/boot.php
@@ -51,14 +51,44 @@
$userId = rex::getUser()->getId();
if (rex_addon::get('quick_navigation')->getConfig('quick_navigation_artdirections' . $userId) != '1') {
- ButtonRegistry::registerButton(new ArticleNavigationButton(), 10);
+ ButtonRegistry::registerButton(
+ new ArticleNavigationButton(),
+ 10,
+ 'article_navigation',
+ rex_addon::get('quick_navigation')->i18n('quick_navigation_button_article_navigation')
+ );
}
- ButtonRegistry::registerButton(new WatsonButton(), 20);
- ButtonRegistry::registerButton(new CategoryButton(), 30);
- ButtonRegistry::registerButton(new ArticleHistoryButton('structure', 20), 40);
- ButtonRegistry::registerButton(new YformButton(), 50);
- ButtonRegistry::registerButton(new FavoriteButton(), 60);
+ ButtonRegistry::registerButton(
+ new WatsonButton(),
+ 20,
+ 'watson',
+ rex_addon::get('quick_navigation')->i18n('quick_navigation_button_watson')
+ );
+ ButtonRegistry::registerButton(
+ new CategoryButton(),
+ 30,
+ 'category',
+ rex_addon::get('quick_navigation')->i18n('quick_navigation_button_category')
+ );
+ ButtonRegistry::registerButton(
+ new ArticleHistoryButton('structure', 20),
+ 40,
+ 'article_history',
+ rex_addon::get('quick_navigation')->i18n('quick_navigation_button_article_history')
+ );
+ ButtonRegistry::registerButton(
+ new YformButton(),
+ 50,
+ 'yform',
+ rex_addon::get('quick_navigation')->i18n('quick_navigation_button_yform')
+ );
+ ButtonRegistry::registerButton(
+ new FavoriteButton(),
+ 60,
+ 'favorite',
+ rex_addon::get('quick_navigation')->i18n('quick_navigation_button_favorite')
+ );
// Addonrechte (permissions) registieren
rex_perm::register('quick_navigation[]');
diff --git a/fragments/QuickNavigation/List.php b/fragments/QuickNavigation/List.php
index 533cffd..f6c1144 100644
--- a/fragments/QuickNavigation/List.php
+++ b/fragments/QuickNavigation/List.php
@@ -7,10 +7,14 @@
getVar('listItems', []) as $listItem): ?>
+
+ = $listItem ?>
+
-
= $listItem ?>
+
\ No newline at end of file
diff --git a/lang/de_de.lang b/lang/de_de.lang
index 0ac3f5f..d7f913a 100644
--- a/lang/de_de.lang
+++ b/lang/de_de.lang
@@ -21,6 +21,9 @@ quick_navigation_favorite = Favoriten
quick_navigation_manage_favorite = Favoriten anlegen
quick_navigation_favorite_article_add = Artikel hinzufügen in:
quick_navigation_favorite_category_add = Kategorie hinzufügen in:
+quick_navigation_addon_pages = AddOn-Seiten
+quick_navigation_structure_favs = Struktur
+quick_navigation_addon_pages_selection = AddOn-Seiten Favoriten
quick_navigation_yform = YForm
quick_navigation_yform_add = Datensatz hinzufügen in:
@@ -35,3 +38,13 @@ quick_navigation_media_live_search_placeholder = Live-Suche...
# Live Search
quick_navigation_media_live_search_placeholder = Live-Suche...
+
+# Button Management
+quick_navigation_button_management = Buttons ausblenden (Opt-Out)
+quick_navigation_button_management_note = Wähle die Buttons aus, die du NICHT sehen möchtest. Alle anderen Buttons bleiben sichtbar.
+quick_navigation_button_article_navigation = Artikelnavigation (Blättern)
+quick_navigation_button_watson = Watson
+quick_navigation_button_category = Kategorie
+quick_navigation_button_article_history = Artikel-Historie
+quick_navigation_button_yform = YForm
+quick_navigation_button_favorite = Favoriten
diff --git a/lang/en_gb.lang b/lang/en_gb.lang
index 76eac8c..55d91fa 100644
--- a/lang/en_gb.lang
+++ b/lang/en_gb.lang
@@ -21,6 +21,9 @@ quick_navigation_favorite = Favorites
quick_navigation_manage_favorite = Add favorites
quick_navigation_favorite_article_add = Add article to:
quick_navigation_favorite_category_add = Add category to:
+quick_navigation_addon_pages = AddOn Pages
+quick_navigation_structure_favs = Structure
+quick_navigation_addon_pages_selection = AddOn Pages Favorites
quick_navigation_yform = YForm
quick_navigation_yform_add = Add dataset to:
@@ -32,3 +35,13 @@ quick_navigation_media_sort_title = Sort by title (A-Z)
# Media Live-Search
quick_navigation_media_livesearch = Enable media live search?
quick_navigation_media_live_search_placeholder = Live search...
+
+# Button Management
+quick_navigation_button_management = Hide buttons (Opt-Out)
+quick_navigation_button_management_note = Select the buttons you DON'T want to see. All other buttons remain visible.
+quick_navigation_button_article_navigation = Article Navigation (Browse)
+quick_navigation_button_watson = Watson
+quick_navigation_button_category = Category
+quick_navigation_button_article_history = Article History
+quick_navigation_button_yform = YForm
+quick_navigation_button_favorite = Favorites
diff --git a/lib/Button/ButtonRegistry.php b/lib/Button/ButtonRegistry.php
index 72bf3c0..a9ac709 100644
--- a/lib/Button/ButtonRegistry.php
+++ b/lib/Button/ButtonRegistry.php
@@ -2,27 +2,63 @@
namespace FriendsOfRedaxo\QuickNavigation\Button;
+use rex;
+use rex_addon;
+
class ButtonRegistry
{
/**
- * @var array an array that contains button instances and their priorities
+ * @var array an array that contains button instances and their priorities
*/
protected static array $buttons = [];
/**
* Registers a button with an optional priority.
* Lower priority values cause the button to appear earlier in the list.
+ *
+ * @param string $id Unique identifier for the button (e.g. 'article_navigation', 'watson')
+ * @param string $label Human readable label for config (e.g. 'Artikelnavigation', 'Watson')
*/
- public static function registerButton(ButtonInterface $buttonInstance, int $priority = 10): void
+ public static function registerButton(ButtonInterface $buttonInstance, int $priority = 10, string $id = '', string $label = ''): void
{
- self::$buttons[] = ['instance' => $buttonInstance, 'priority' => $priority];
+ // Generate ID from class name if not provided
+ if ($id === '') {
+ $className = get_class($buttonInstance);
+ $id = strtolower(str_replace('Button', '', substr($className, strrpos($className, '\\') + 1)));
+ }
+
+ // Use ID as label if not provided
+ if ($label === '') {
+ $label = ucfirst(str_replace('_', ' ', $id));
+ }
+
+ self::$buttons[] = [
+ 'id' => $id,
+ 'label' => $label,
+ 'instance' => $buttonInstance,
+ 'priority' => $priority
+ ];
}
/**
- * Returns the buttons sorted by their priority.
+ * Returns the buttons sorted by their priority, filtered by user preferences.
*/
public static function getButtonsOutput(): string
{
+ $user = rex::getUser();
+ if (!$user) {
+ return '';
+ }
+
+ $userId = $user->getId();
+ $addon = rex_addon::get('quick_navigation');
+
+ // Get disabled buttons for this user (Opt-Out)
+ $disabledButtons = $addon->getConfig('quick_navigation_disabled_buttons' . $userId, []);
+ if (!is_array($disabledButtons)) {
+ $disabledButtons = [];
+ }
+
// Sorts the buttons based on their priority
usort(self::$buttons, static function (array $a, array $b): int {
return $a['priority'] <=> $b['priority'];
@@ -30,10 +66,39 @@ public static function getButtonsOutput(): string
$resultString = '';
foreach (self::$buttons as $button) {
+ // Skip if button is disabled for this user
+ if (in_array($button['id'], $disabledButtons, true)) {
+ continue;
+ }
+
// Since all instances implement ButtonInterface, it's guaranteed that get() exists.
$resultString .= $button['instance']->get();
}
return $resultString;
}
+
+ /**
+ * Returns all available buttons with their metadata for configuration.
+ * @return array
+ */
+ public static function getAvailableButtons(): array
+ {
+ // Sort by priority
+ $sortedButtons = self::$buttons;
+ usort($sortedButtons, static function (array $a, array $b): int {
+ return $a['priority'] <=> $b['priority'];
+ });
+
+ $result = [];
+ foreach ($sortedButtons as $button) {
+ $result[] = [
+ 'id' => $button['id'],
+ 'label' => $button['label'],
+ 'priority' => $button['priority']
+ ];
+ }
+
+ return $result;
+ }
}
diff --git a/lib/Button/FavoriteButton.php b/lib/Button/FavoriteButton.php
index 3dfa868..8bc22f0 100644
--- a/lib/Button/FavoriteButton.php
+++ b/lib/Button/FavoriteButton.php
@@ -6,6 +6,7 @@
use rex;
use rex_addon;
+use rex_be_controller;
use rex_category;
use rex_clang;
@@ -27,9 +28,14 @@ public function get(): string
}
$categoryIds = rex_addon::get('quick_navigation')->getConfig('quick_navigation_favs' . $user->getId());
+ $addonPages = rex_addon::get('quick_navigation')->getConfig('quick_navigation_addon_favs' . $user->getId(), []);
$listItems = [];
+
+ // Struktur-Favoriten zuerst
if ($categoryIds && count($categoryIds) > 0) {
+ $listItems[] = '';
+
$clangId = rex_request('clang', 'int', rex_clang::getStartId());
foreach ($categoryIds as $categoryId) {
@@ -77,7 +83,53 @@ public function get(): string
$listItems[] = $listItem;
}
- } else {
+ }
+
+ // AddOn-Seiten Favoriten danach
+ if (is_array($addonPages) && count($addonPages) > 0) {
+ if (count($listItems) > 0) {
+ $listItems[] = '';
+ }
+ $listItems[] = '';
+
+ foreach ($addonPages as $pageKey) {
+ $pageInfo = $this->parsePageKey($pageKey);
+ if (!$pageInfo) {
+ continue;
+ }
+
+ // Check permission
+ $page = rex_be_controller::getPageObject($pageInfo['fullKey']);
+ if (!$page || $page->isHidden()) {
+ continue;
+ }
+
+ // Check user permission
+ $requiredPerms = $page->getRequiredPermissions();
+ if (!empty($requiredPerms) && !$user->hasPerm($requiredPerms)) {
+ continue;
+ }
+
+ $attributes = [
+ 'href' => rex_url::backendPage($pageInfo['fullKey']),
+ 'title' => $pageInfo['title'],
+ ];
+
+ $listItem = '
+
+ ';
+
+ $listItems[] = $listItem;
+ }
+ }
+
+ // Keine Favoriten
+ if (count($listItems) === 0) {
$listItems[] = ''.rex_i18n::msg('quick_navigation_manage_favorite').'';
}
@@ -88,4 +140,84 @@ public function get(): string
]);
return $fragment->parse('QuickNavigation/Dropdown.php');
}
+
+ /**
+ * Parse page key and return info
+ * @return array{fullKey: string, title: string, icon: string}|null
+ */
+ private function parsePageKey(string $pageKey): ?array
+ {
+ $page = rex_be_controller::getPageObject($pageKey);
+ if (!$page) {
+ return null;
+ }
+
+ return [
+ 'fullKey' => $pageKey,
+ 'title' => $page->getTitle(),
+ 'icon' => $page->getIcon() ?: 'rex-icon fa-cube',
+ ];
+ }
+
+ /**
+ * Get all available backend pages for favorites
+ * @return array
+ */
+ public static function getAvailablePages(): array
+ {
+ $user = rex::getUser();
+ if (!$user) {
+ return [];
+ }
+
+ $pages = [];
+ $pageContainer = rex_be_controller::getPages();
+
+ foreach ($pageContainer as $pageKey => $page) {
+ // Skip system pages
+ if (in_array($pageKey, ['setup', 'login', 'logout', '2factor_auth', '2factor_auth_verify'], true)) {
+ continue;
+ }
+
+ // Skip if user has no permission
+ if ($page->isHidden()) {
+ continue;
+ }
+
+ $requiredPerms = $page->getRequiredPermissions();
+ if (!empty($requiredPerms) && !$user->hasPerm($requiredPerms)) {
+ continue;
+ }
+
+ $addonName = $pageKey;
+ $pages[] = [
+ 'key' => $pageKey,
+ 'title' => $page->getTitle(),
+ 'icon' => $page->getIcon() ?: 'rex-icon fa-cube',
+ 'addon' => $addonName,
+ ];
+
+ // Add subpages
+ foreach ($page->getSubpages() as $subpageKey => $subpage) {
+ if ($subpage->isHidden()) {
+ continue;
+ }
+
+ $subRequiredPerms = $subpage->getRequiredPermissions();
+ if (!empty($subRequiredPerms) && !$user->hasPerm($subRequiredPerms)) {
+ continue;
+ }
+
+ $fullKey = $pageKey . '/' . $subpageKey;
+ $pages[] = [
+ 'key' => $fullKey,
+ 'title' => ' → ' . $subpage->getTitle(),
+ 'icon' => $subpage->getIcon() ?: 'rex-icon fa-cube',
+ 'addon' => $addonName,
+ ];
+ }
+ }
+
+ return $pages;
+ }
}
diff --git a/pages/config.php b/pages/config.php
index 7bde858..118178b 100644
--- a/pages/config.php
+++ b/pages/config.php
@@ -2,6 +2,8 @@
namespace FriendsOfRedaxo\QuickNavigation;
+use FriendsOfRedaxo\QuickNavigation\Button\ButtonRegistry;
+use FriendsOfRedaxo\QuickNavigation\Button\FavoriteButton;
use rex;
use rex_addon;
use rex_category_select;
@@ -26,6 +28,11 @@
$config['quick_navigation_ignoreoffline' . $user] = isset($config['quick_navigation_ignoreoffline' . $user]) ? 1 : 0;
$config['quick_navigation_artdirections' . $user] = isset($config['quick_navigation_artdirections' . $user]) ? 1 : 0;
$config['quick_navigation_media_livesearch' . $user] = isset($config['quick_navigation_media_livesearch' . $user]) ? 1 : 0;
+
+ // Disabled Buttons speichern (Array bleibt als Array)
+ if (!isset($config['quick_navigation_disabled_buttons' . $user])) {
+ $config['quick_navigation_disabled_buttons' . $user] = [];
+ }
$package->setConfig($config);
echo rex_view::success($package->i18n('quick_navigation_config_saved'));
@@ -56,6 +63,38 @@
$fragment = new rex_fragment();
$fragment->setVar('elements', $formElements, false);
$content .= $fragment->parse('core/form/container.php');
+
+// AddOn-Seiten Favoriten
+$formElements = [];
+$n = [];
+$n['label'] = '';
+
+// Get all available pages
+$availablePages = FavoriteButton::getAvailablePages();
+$selectedPages = $package->getConfig('quick_navigation_addon_favs' . $user, []);
+if (!is_array($selectedPages)) {
+ $selectedPages = [];
+}
+
+$selectHtml = '';
+$n['field'] = $selectHtml;
+$formElements[] = $n;
+$fragment = new rex_fragment();
+$fragment->setVar('elements', $formElements, false);
+$content .= $fragment->parse('core/form/container.php');
+
// Ignore offline cats
$formElements = [];
$n = [];
@@ -89,7 +128,43 @@
$fragment->setVar('elements', $formElements, false);
$content .= $fragment->parse('core/form/checkbox.php');
-// Medienpool-Sortier-Button-Option entfernt
+// Button-Management
+$formElements = [];
+$n = [];
+$n['label'] = '';
+
+// Get all available buttons
+$availableButtons = ButtonRegistry::getAvailableButtons();
+$disabledButtons = $package->getConfig('quick_navigation_disabled_buttons' . $user, []);
+if (!is_array($disabledButtons)) {
+ $disabledButtons = [];
+}
+
+$buttonCheckboxes = '';
+foreach ($availableButtons as $button) {
+ $isDisabled = in_array($button['id'], $disabledButtons, true);
+ $buttonCheckboxes .= sprintf(
+ '
+
+
',
+ $user,
+ rex_escape($button['id']),
+ $isDisabled ? ' checked="checked"' : '',
+ rex_escape($button['label'])
+ );
+}
+
+$n['field'] = '' . $buttonCheckboxes . '
';
+$n['note'] = $package->i18n('quick_navigation_button_management_note');
+$formElements[] = $n;
+$fragment = new rex_fragment();
+$fragment->setVar('elements', $formElements, false);
+$content .= $fragment->parse('core/form/container.php');
+
+$content .= '';
// Save-Button
$formElements = [];