Commit cb045371 authored by Sergey Shadrin's avatar Sergey Shadrin

[#124455] Patches

-Added package to apply patches
-Removed obsolete patches
-Patched core to replace icons
-Patched `admin_toolbar` to replace icons
parent 5c90473f
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
"license": "GPL-2.0-or-later", "license": "GPL-2.0-or-later",
"require": { "require": {
"composer/installers": "^1.7", "composer/installers": "^1.7",
"drupal/admin_toolbar": "^1.25", "drupal/admin_toolbar": "^3.2",
"drupal/blazy": "^1.0", "drupal/blazy": "^1.0",
"drupal/bootstrap": "^3.16", "drupal/bootstrap": "^3.16",
"drupal/ckeditor_font": "^1.0", "drupal/ckeditor_font": "^1.0",
...@@ -40,7 +40,8 @@ ...@@ -40,7 +40,8 @@
"drupal/video_embed_field": "^2.0", "drupal/video_embed_field": "^2.0",
"drupal/webform": "^5.0", "drupal/webform": "^5.0",
"drush/drush": "^9.5", "drush/drush": "^9.5",
"oomphinc/composer-installers-extender": "^2.0" "oomphinc/composer-installers-extender": "^2.0",
"cweagans/composer-patches": "^1.7"
}, },
"minimum-stability": "dev", "minimum-stability": "dev",
"prefer-stable": true, "prefer-stable": true,
...@@ -51,7 +52,8 @@ ...@@ -51,7 +52,8 @@
"drupal/core-composer-scaffold": true, "drupal/core-composer-scaffold": true,
"drupal/core-project-message": true, "drupal/core-project-message": true,
"composer/installers": true, "composer/installers": true,
"oomphinc/composer-installers-extender": true "oomphinc/composer-installers-extender": true,
"cweagans/composer-patches": true
} }
}, },
"extra": { "extra": {
...@@ -81,22 +83,10 @@ ...@@ -81,22 +83,10 @@
}, },
"patches": { "patches": {
"drupal/core": { "drupal/core": {
"2698057 Add support for <nolink>, <none> and empty values to the UI": "https://www.drupal.org/files/issues/2018-04-17/add_nolink_support-2698057-23.patch" "Replace icons": "./patches/core/core-icons.patch"
}, },
"drupal/linkit": { "drupal/admin_toolbar": {
"2903176 Views as a dependency": "https://www.drupal.org/files/issues/linkit_views_dependency-2903176-2.patch" "Replace icons": "./patches/admin_toolbar/replace-icons.patch"
},
"drupal/paragraphs_browser": {
"2917656 Extend from ParagraphsWidget instead of InlineParagraphsWidget": "https://www.drupal.org/files/issues/2018-03-22/paragraphs_browser-extend-from-ParagraphsWidget-2917656-10.patch"
},
"drupal/colorbutton": {
"2881822 Module can't find library in profile directory": "https://www.drupal.org/files/issues/colorbutton-module_can_t_find-2881822-15.patch"
},
"drupal/panelbutton": {
"2881820 Module can't find library in profile directory": "https://www.drupal.org/files/issues/panelbutton-module_can_t_find-2881820-11.patch"
},
"drupal/entity_browser": {
"2932081 fixing bug with file upload validation": "https://www.drupal.org/files/issues/2018-04-13/2932081-7.patch"
} }
} }
}, },
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "cc20c098c61dee52473958c40b7f0583", "content-hash": "12e108028ee19eae86ddc59b250272da",
"packages": [ "packages": [
{ {
"name": "asm89/stack-cors", "name": "asm89/stack-cors",
...@@ -1147,6 +1147,54 @@ ...@@ -1147,6 +1147,54 @@
"abandoned": "psr/container", "abandoned": "psr/container",
"time": "2017-02-14T19:40:03+00:00" "time": "2017-02-14T19:40:03+00:00"
}, },
{
"name": "cweagans/composer-patches",
"version": "1.7.3",
"source": {
"type": "git",
"url": "https://github.com/cweagans/composer-patches.git",
"reference": "e190d4466fe2b103a55467dfa83fc2fecfcaf2db"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/cweagans/composer-patches/zipball/e190d4466fe2b103a55467dfa83fc2fecfcaf2db",
"reference": "e190d4466fe2b103a55467dfa83fc2fecfcaf2db",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0 || ^2.0",
"php": ">=5.3.0"
},
"require-dev": {
"composer/composer": "~1.0 || ~2.0",
"phpunit/phpunit": "~4.6"
},
"type": "composer-plugin",
"extra": {
"class": "cweagans\\Composer\\Patches"
},
"autoload": {
"psr-4": {
"cweagans\\Composer\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Cameron Eagans",
"email": "me@cweagans.net"
}
],
"description": "Provides a way to patch Composer packages.",
"support": {
"issues": "https://github.com/cweagans/composer-patches/issues",
"source": "https://github.com/cweagans/composer-patches/tree/1.7.3"
},
"time": "2022-12-20T22:53:13+00:00"
},
{ {
"name": "dflydev/dot-access-data", "name": "dflydev/dot-access-data",
"version": "v1.1.0", "version": "v1.1.0",
...@@ -1674,26 +1722,29 @@ ...@@ -1674,26 +1722,29 @@
}, },
{ {
"name": "drupal/admin_toolbar", "name": "drupal/admin_toolbar",
"version": "1.27.0", "version": "3.2.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://git.drupalcode.org/project/admin_toolbar.git", "url": "https://git.drupalcode.org/project/admin_toolbar.git",
"reference": "8.x-1.27" "reference": "3.2.1"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://ftp.drupal.org/files/projects/admin_toolbar-8.x-1.27.zip", "url": "https://ftp.drupal.org/files/projects/admin_toolbar-3.2.1.zip",
"reference": "8.x-1.27", "reference": "3.2.1",
"shasum": "fed1fbbdf8f805b1da63d73e7e2c54750f354d61" "shasum": "7a4bfb716e269be4ca03b7f04e29e4439ec6cf93"
}, },
"require": { "require": {
"drupal/core": "^8" "drupal/core": "^8.8.0 || ^9.0"
},
"require-dev": {
"drupal/admin_toolbar_tools": "*"
}, },
"type": "drupal-module", "type": "drupal-module",
"extra": { "extra": {
"drupal": { "drupal": {
"version": "8.x-1.27", "version": "3.2.1",
"datestamp": "1558553350", "datestamp": "1665044276",
"security-coverage": { "security-coverage": {
"status": "covered", "status": "covered",
"message": "Covered by Drupal's security advisory policy" "message": "Covered by Drupal's security advisory policy"
...@@ -1702,7 +1753,7 @@ ...@@ -1702,7 +1753,7 @@
}, },
"notification-url": "https://packages.drupal.org/8/downloads", "notification-url": "https://packages.drupal.org/8/downloads",
"license": [ "license": [
"GPL-2.0+" "GPL-2.0-or-later"
], ],
"authors": [ "authors": [
{ {
...@@ -1746,7 +1797,7 @@ ...@@ -1746,7 +1797,7 @@
"Toolbar" "Toolbar"
], ],
"support": { "support": {
"source": "http://cgit.drupalcode.org/admin_toolbar", "source": "https://git.drupalcode.org/project/admin_toolbar",
"issues": "https://www.drupal.org/project/issues/admin_toolbar" "issues": "https://www.drupal.org/project/issues/admin_toolbar"
} }
}, },
......
This file was automatically generated by Composer Patches (https://github.com/cweagans/composer-patches)
Patches applied to this directory:
Replace icons
Source: ./patches/core/core-icons.patch
core/misc/druplicon.png

3.81 KB | W: | H:

core/misc/druplicon.png

13 KB | W: | H:

core/misc/druplicon.png
core/misc/druplicon.png
core/misc/druplicon.png
core/misc/druplicon.png
  • 2-up
  • Swipe
  • Onion skin
core/misc/favicon.ico

5.3 KB | W: | H:

core/misc/favicon.ico

9.44 KB | W: | H:

core/misc/favicon.ico
core/misc/favicon.ico
core/misc/favicon.ico
core/misc/favicon.ico
  • 2-up
  • Swipe
  • Onion skin
<svg xmlns="http://www.w3.org/2000/svg" width="57" height="66" viewBox="471.5 467 57 66" enable-background="new 471.5 467 57 66"><path opacity=".2" fill="#303030" d="M528.5 504.965c0 16.634-13.123 27.615-28.24 27.615-10.29 0-19.894-5.523-24.978-14.167l.605-.027c1.313 1.192 3.39 2.58 7.404 2.515 4.77-.064 5.645-.875 9.855-2.756 22.716-10.17 26.925-19.457 27.736-21.59s2.013-5.587.756-9.415c-.242-.737-.42-1.333-.54-1.808-3.018-3.372-6.017-5.225-6.92-5.784-.14-.093-.29-.177-.43-.26l.44.26c2.01 1.247 14.314 8.782 14.314 25.417z"/><path fill="#fff" d="M509.09 518.507c1.006 0 2.077.065 2.83.568.756.503 1.193 1.63 1.445 2.263.25.634 0 1.006-.503 1.258-.438.25-.503.12-.94-.69-.44-.81-.82-1.63-3.01-1.63s-2.887.755-3.948 1.63c-1.062.876-1.443 1.193-1.825.69s-.253-1.006.437-1.63 1.825-1.63 2.888-2.077c1.06-.45 1.62-.383 2.625-.383zm-10.413 7.152c1.257 1.005 3.14 1.825 7.153 1.825 4.015 0 6.836-1.137 8.094-2.077.568-.438.82-.065.875.187.056.25.186.624-.252 1.07-.316.317-3.194 2.33-6.594 2.636-3.4.31-7.964.504-10.73-2.01-.438-.44-.316-1.07 0-1.323.317-.25.568-.438.94-.438.374.008.317.008.513.13z"/><path opacity=".2" fill="#aaa" d="M520.89 496.545c-.81 2.133-5.02 11.42-27.735 21.59-4.21 1.88-5.085 2.69-9.854 2.756-4.013.066-6.09-1.32-7.403-2.514l-.605.028h-.01c-2.393-4.042-3.78-8.783-3.78-13.952 0-7.852 2.97-13.654 6.287-17.687.11-.13.213-.26.325-.382 2.683-3.148 5.55-5.17 7.218-6.203.038-.028.075-.047.112-.065.42-.25.754-.447.987-.568 2.757-1.51 4.77-2.263 7.963-4.77.12-.092.242-.186.354-.288l.008-.01c.875-.754 1.64-1.76 2.18-3.4v-.008c.325-.97.567-2.16.716-3.65l.02.018c2.253 2.69 4.954 5.886 6.89 7.144.69.447 1.38.848 2.068 1.202l.3.15c2.243 1.126 4.507 1.945 6.807 3.333l.428.26c.903.56 3.902 2.412 6.92 5.784.12.475.298 1.07.54 1.807 1.274 3.837.073 7.292-.737 9.425z"/><path opacity=".5" fill="#333" d="M514.176 479.538c-3.26-2.077-6.464-2.887-9.603-4.955-1.938-1.267-4.64-4.47-6.893-7.162-.438 4.332-1.686 6.148-3.26 7.35-3.195 2.515-5.207 3.26-7.963 4.77-2.338 1.256-14.958 8.726-14.958 24.913 0 5.17 1.387 9.91 3.77 13.96 5.077 8.635 14.68 14.158 24.97 14.158 15.126 0 28.24-10.98 28.24-27.614 0-9.127-3.707-15.526-7.386-19.633-3.016-3.382-6.015-5.217-6.918-5.785zm7.627 7.34c4.117 5.15 6.213 11.23 6.213 18.077 0 3.968-.755 7.712-2.245 11.148-1.414 3.25-3.444 6.13-6.053 8.56-5.15 4.806-12.062 7.45-19.475 7.45-3.67 0-7.265-.698-10.692-2.086-3.372-1.36-6.398-3.297-9.016-5.774-5.532-5.225-8.57-12.257-8.57-19.8 0-6.716 2.18-12.695 6.483-17.753 3.288-3.865 6.836-6.007 8.196-6.743.67-.363 1.285-.69 1.89-.997 1.892-.97 3.68-1.89 6.14-3.818 1.312-.997 2.71-2.58 3.305-6.585 2.077 2.468 4.48 5.234 6.314 6.426 1.63 1.08 3.307 1.835 4.918 2.562 1.527.69 3.11 1.406 4.676 2.403l.056.037c4.62 2.84 7.06 5.896 7.86 6.892z"/><path opacity=".5" fill="#fff" d="M497.98 468.678c.874 2.58.753 3.893.753 4.452 0 .56-.307 2.077-1.313 2.832-.438.317-.568.568-.568.624 0 .25.568.438.568 1.006 0 .69-.317 2.077-3.642 5.393-3.325 3.316-8.103 6.278-11.8 8.103-3.698 1.826-5.468 1.686-5.97.81s.185-2.83 2.514-5.392l9.667-6.278 9.164-6.398.503-2.44"/><path fill="#fff" d="M497.98 468.613c-.57 4.145-1.826 5.393-3.512 6.715-2.83 2.133-5.588 3.446-6.212 3.763-1.63.82-7.535 4.08-10.608 8.784-.94 1.444 0 2.012.186 2.133.187.12 2.33.372 6.9-2.385 4.574-2.757 6.595-4.387 9.175-7.078 1.377-1.444 1.573-2.263 1.573-2.636 0-.438-.316-.624-.82-.754-.25-.065-.316-.187 0-.373.317-.186 1.622-.82 1.938-1.07.318-.25 1.827-1.257 1.882-2.887.065-1.63-.056-2.766-.503-4.21zm-14.112 45.628c.065-4.898 4.648-9.472 10.422-9.536 7.348-.065 12.424 7.283 16.13 7.208 3.14-.064 9.166-6.212 12.118-6.212 3.14 0 4.014 3.26 4.014 5.206 0 1.938-.623 5.458-2.133 7.656-1.51 2.198-2.44 3.008-4.2 2.888-2.264-.187-6.78-7.21-9.67-7.35-3.64-.12-11.547 7.6-17.75 7.6-3.763 0-4.9-.567-6.147-1.378-1.92-1.312-2.85-3.315-2.785-6.08z"/></svg> <svg width="214" height="214" viewBox="0 0 214 214" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M172 59C154.963 36 135 19 105 0C110.5 30.5 58.5 50 41 68.5C23.5 87 17 106.188 17 125.902C17 174.204 57.6985 213.5 106 213.5C154.302 213.5 196.5 174.204 196.5 125.902C196.5 106.188 189.037 82 172 59Z" fill="#008CF2"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M105.318 83.5C92.4745 83.5 81.0102 88.6894 73.0589 96.8593C70.2775 99.7171 68.2075 104.354 67.3793 109.481C66.5258 114.766 67.2414 118.928 68.2111 120.763C58 122 51.5 113 52.5 104.5C53.2059 98.5 55.8754 91.5746 61.5929 85.7C72.5277 74.4646 88.115 67.5 105.318 67.5C137.872 67.5 165 92.6234 165 124.5C165 156.377 137.872 181.5 105.318 181.5C100.829 181.5 93.7529 180.358 90 180C85.3088 179.654 71.5 179 64 182L83.5 108.5C85.5 102 91.7553 98.2637 102.602 99.6635L84.5586 164.168C86.3276 164.183 88.0427 164.274 89.7083 164.397C91.628 164.538 93.3802 164.707 95.0667 164.87C98.4724 165.198 101.61 165.5 105.318 165.5C129.85 165.5 149 146.747 149 124.5C149 102.253 129.85 83.5 105.318 83.5Z" fill="white"/>
</svg>
This diff is collapsed.
This file was automatically generated by Composer Patches (https://github.com/cweagans/composer-patches)
Patches applied to this directory:
Replace icons
Source: ./patches/admin_toolbar/replace-icons.patch
...@@ -50,7 +50,7 @@ INSTALLATION ...@@ -50,7 +50,7 @@ INSTALLATION
CONFIGURATION CONFIGURATION
------------- -------------
No configuration is needed. * Configure the admin toolbar tools at (/admin/config/user-interface/settings).
MAINTAINERS MAINTAINERS
...@@ -65,5 +65,7 @@ Current maintainers: ...@@ -65,5 +65,7 @@ Current maintainers:
This project has been sponsored by: This project has been sponsored by:
* emerya * emerya
Founded in 2009, emerya is a human-sized company, dedicated to the design and Founded in 2009, emerya is a human-sized company, dedicated to the design and
implementation of web interfaces. Visit: http://http://emerya.fr/ for more implementation of web interfaces. Visit: http://emerya.fr/ for more
information. information.
* trained people
Trained People is a training company focused on Drupal.
name: Admin Toolbar name: Admin Toolbar
description: Provides an improved drop-down menu interface to the site Toolbar. description: Provides an improved drop-down menu interface to the site Toolbar.
package: Administration package: Administration
type: module type: module
# core: 8.x core_version_requirement: ^8.8.0 || ^9
dependencies: dependencies:
- drupal:toolbar - drupal:toolbar
# Information added by Drupal.org packaging script on 2019-05-22 # Information added by Drupal.org packaging script on 2022-10-06
version: '8.x-1.27' version: '3.2.1'
core: '8.x'
project: 'admin_toolbar' project: 'admin_toolbar'
datestamp: 1558552277 datestamp: 1665044278
...@@ -14,3 +14,17 @@ function admin_toolbar_update_8001() { ...@@ -14,3 +14,17 @@ function admin_toolbar_update_8001() {
// Rebuilding the route cache. // Rebuilding the route cache.
\Drupal::service("router.builder")->rebuild(); \Drupal::service("router.builder")->rebuild();
} }
/**
* Add menu_depth param into the config.
*
* @see https://www.drupal.org/project/admin_toolbar/issues/3200542
*/
function admin_toolbar_update_8002() {
$config_factory = \Drupal::configFactory();
$config = $config_factory->getEditable('admin_toolbar.settings');
if (empty($config->get('menu_depth'))) {
$config->set('menu_depth', 4);
$config->save(TRUE);
}
}
...@@ -3,19 +3,19 @@ toolbar.tree: ...@@ -3,19 +3,19 @@ toolbar.tree:
theme: theme:
css/admin.toolbar.css: {} css/admin.toolbar.css: {}
js: js:
js/jquery.hoverIntent.js: {}
js/admin_toolbar.js: {} js/admin_toolbar.js: {}
dependencies: dependencies:
- core/jquery - core/jquery
- core/drupal - core/drupal
search: toolbar.tree.hoverintent:
css: js:
theme: js/jquery.hoverIntent.js: {}
css/admin.toolbar_search.css: {} js/admin_toolbar.hoverintent.js: {}
dependencies:
- core/jquery
toolbar.tree.hover:
js: js:
js/admin_toolbar_search.js: {} js/admin_toolbar.hover.js: {}
dependencies: dependencies:
- core/jquery - core/jquery
- core/drupal
- core/jquery.once
- core/jquery.ui.autocomplete
admin_toolbar.settings:
title: 'Admin Toolbar'
description: 'Configure the Admin Toolbar module.'
route_name: admin_toolbar.settings
parent: system.admin_config_ui
...@@ -5,50 +5,28 @@ ...@@ -5,50 +5,28 @@
* This is the module to create a drop-down menu for the core toolbar. * This is the module to create a drop-down menu for the core toolbar.
*/ */
use Drupal\Core\Menu\MenuTreeParameters; use Drupal\admin_toolbar\Render\Element\AdminToolbar;
use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url; use Drupal\Core\Url;
use Drupal\Component\Utility\Html; use Drupal\Component\Utility\Html;
use Drupal\Core\StringTranslation\TranslatableMarkup;
/** /**
* Implements hook_toolbar_alter(). * Implements hook_toolbar_alter().
*/ */
function admin_toolbar_toolbar_alter(&$items) { function admin_toolbar_toolbar_alter(&$items) {
$items['administration']['tray']['toolbar_administration']['#pre_render'] = ['admin_toolbar_prerender_toolbar_administration_tray']; $items['administration']['tray']['toolbar_administration']['#pre_render'] = [
$items['administration']['#attached']['library'][] = 'admin_toolbar/toolbar.tree'; [AdminToolbar::class, 'preRenderTray'],
$items['administration_search'] = [
"#type" => "toolbar_item",
'tab' => [
'#type' => 'link',
'#title' => new TranslatableMarkup('Search'),
'#url' => URL::fromRoute('system.admin'),
'#attributes' => [
'class' => [
'toolbar-icon',
],
],
],
'tray' => [
'search' => [
'#title' => 'Search',
'#type' => 'textfield',
'#size' => 60,
'#attributes' => [
'id' => 'admin-toolbar-search-input',
],
],
],
'#attached' => [
'library' => [
'admin_toolbar/search',
],
],
'#wrapper_attributes' => [
"id" => "admin-toolbar-search-tab",
],
]; ];
$items['administration']['#attached']['library'][] = 'admin_toolbar/toolbar.tree';
$hoverintent_functionality = \Drupal::config('admin_toolbar_tools.settings')->get('hoverintent_functionality');
if ($hoverintent_functionality === TRUE) {
// Use jQuery hover() effect.
$items['administration']['#attached']['library'][] = 'admin_toolbar/toolbar.tree.hoverintent';
}
else {
// User hoverIntent plugin.
$items['administration']['#attached']['library'][] = 'admin_toolbar/toolbar.tree.hover';
}
} }
/** /**
...@@ -61,47 +39,15 @@ function admin_toolbar_help($route_name, RouteMatchInterface $route_match) { ...@@ -61,47 +39,15 @@ function admin_toolbar_help($route_name, RouteMatchInterface $route_match) {
':toolbar' => Url::fromRoute('help.page', ['name' => 'toolbar'])->toString(), ':toolbar' => Url::fromRoute('help.page', ['name' => 'toolbar'])->toString(),
':automated_cron' => (\Drupal::moduleHandler()->moduleExists('automated_cron')) ? Url::fromRoute('help.page', ['name' => 'automated_cron'])->toString() : '#', ':automated_cron' => (\Drupal::moduleHandler()->moduleExists('automated_cron')) ? Url::fromRoute('help.page', ['name' => 'automated_cron'])->toString() : '#',
]; ];
$output = ''; $output = '';
$output .= '<h3>' . t('About') . '</h3>'; $output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('The Admin Toolbar module enhances the <a href=":toolbar">Toolbar</a> module by providing fast access to all the administrative links at the top of your site. Admin Toolbar remains a very "lightweight" module by closely integrating with all Toolbar functionality. It can be used in conjunction with all the sub modules included on Admin Toolbar, for quick access to system commands such as Flush all caches, <a href=":automated_cron">Run cron</a>, Run Updates, etc.', $variables) . '</p>'; $output .= '<p>' . t('The Admin Toolbar module enhances the <a href=":toolbar">Toolbar</a> module by providing fast access to all the administrative links at the top of your site. Admin Toolbar remains a very "lightweight" module by closely integrating with all Toolbar functionality. It can be used in conjunction with all the sub modules included on Admin Toolbar, for quick access to system commands such as Flush all caches, <a href=":automated_cron">Run cron</a>, Run Updates, etc.', $variables) . '</p>';
$output .= '<h3>' . t('Uses') . '</h3>'; $output .= '<h3>' . t('Uses') . '</h3>';
$output .= '<p>' . t('The Admin Toolbar greatly improves the user experience for those who regularly interact with the site Toolbar by providing fast, full access to all links in the site Toolbar without having to click to get there.') . '</p>'; $output .= '<p>' . t('The Admin Toolbar greatly improves the user experience for those who regularly interact with the site Toolbar by providing fast, full access to all links in the site Toolbar without having to click to get there.') . '</p>';
return $output; return $output;
} }
} }
/**
* Renders the toolbar's administration tray.
*
* This is a clone of core's toolbar_prerender_toolbar_administration_tray()
* function, which uses setMaxDepth(4) instead of setTopLevelOnly().
*
* @param array $element
* A renderable array.
*
* @return array
* The updated renderable array.
*
* @see toolbar_prerender_toolbar_administration_tray()
*/
function admin_toolbar_prerender_toolbar_administration_tray(array $element) {
$menu_tree = \Drupal::service('toolbar.menu_tree');
$parameters = new MenuTreeParameters();
$parameters->setRoot('system.admin')->excludeRoot()->setMaxDepth(4)->onlyEnabledLinks();
$tree = $menu_tree->load(NULL, $parameters);
$manipulators = [
['callable' => 'menu.default_tree_manipulators:checkAccess'],
['callable' => 'menu.default_tree_manipulators:generateIndexAndSort'],
['callable' => 'toolbar_tools_menu_navigation_links'],
];
$tree = $menu_tree->transform($tree, $manipulators);
$element['administration_menu'] = $menu_tree->build($tree);
return $element;
}
/** /**
* Adds toolbar-specific attributes to the menu link tree. * Adds toolbar-specific attributes to the menu link tree.
* *
...@@ -117,10 +63,8 @@ function toolbar_tools_menu_navigation_links(array $tree) { ...@@ -117,10 +63,8 @@ function toolbar_tools_menu_navigation_links(array $tree) {
toolbar_tools_menu_navigation_links($element->subtree); toolbar_tools_menu_navigation_links($element->subtree);
} }
$link = $element->link; $link = $element->link;
// Get the non-localized title to make the icon class. // Get the non-localized title to make the icon class.
$definition = $link->getPluginDefinition(); $definition = $link->getPluginDefinition();
$element->options['attributes']['class'][] = 'toolbar-icon'; $element->options['attributes']['class'][] = 'toolbar-icon';
$string = strtolower(str_replace(['.', ' ', '_'], ['-', '-', '-'], $definition['id'])); $string = strtolower(str_replace(['.', ' ', '_'], ['-', '-', '-'], $definition['id']));
$element->options['attributes']['class'][] = Html::cleanCssIdentifier('toolbar-icon-' . $string); $element->options['attributes']['class'][] = Html::cleanCssIdentifier('toolbar-icon-' . $string);
......
admin_toolbar.settings:
path: '/admin/config/user-interface/admin-toolbar'
defaults:
_form: '\Drupal\admin_toolbar\Form\AdminToolbarSettingsForm'
_title: 'Admin Toolbar settings'
requirements:
_permission: 'administer site configuration'
...@@ -3,13 +3,12 @@ description: Provides a workaround for the common problem that users with 'Use t ...@@ -3,13 +3,12 @@ description: Provides a workaround for the common problem that users with 'Use t
package: Administration package: Administration
type: module type: module
# core: 8.x core_version_requirement: ^8.8.0 || ^9.0
dependencies: dependencies:
- admin_toolbar:admin_toolbar - admin_toolbar:admin_toolbar
# Information added by Drupal.org packaging script on 2019-05-22 # Information added by Drupal.org packaging script on 2022-10-06
version: '8.x-1.27' version: '3.2.1'
core: '8.x'
project: 'admin_toolbar' project: 'admin_toolbar'
datestamp: 1558552277 datestamp: 1665044278
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
*/ */
use Drupal\Core\Session\AccountInterface; use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use Drupal\user\Entity\Role; use Drupal\user\Entity\Role;
use Symfony\Component\Routing\Exception\RouteNotFoundException; use Symfony\Component\Routing\Exception\RouteNotFoundException;
use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Routing\RouteMatchInterface;
...@@ -59,8 +58,14 @@ function admin_toolbar_links_access_filter_preprocess_menu(&$variables) { ...@@ -59,8 +58,14 @@ function admin_toolbar_links_access_filter_preprocess_menu(&$variables) {
* Hides links from admin menu, if user doesn't have access rights. * Hides links from admin menu, if user doesn't have access rights.
*/ */
function admin_toolbar_links_access_filter_filter_non_accessible_links(array &$items) { function admin_toolbar_links_access_filter_filter_non_accessible_links(array &$items) {
foreach ($items as $route => &$item) { if (Drupal::currentUser()->id() == 1) {
$route_name = $route; // Admin can access everything.
return;
}
$access_manager = \Drupal::accessManager();
foreach ($items as $menu_id => &$item) {
$route_name = NULL;
$route_params = []; $route_params = [];
if (!empty($item['original_link'])) { if (!empty($item['original_link'])) {
/** @var \Drupal\Core\Menu\MenuLinkBase $original_link */ /** @var \Drupal\Core\Menu\MenuLinkBase $original_link */
...@@ -72,17 +77,27 @@ function admin_toolbar_links_access_filter_filter_non_accessible_links(array &$i ...@@ -72,17 +77,27 @@ function admin_toolbar_links_access_filter_filter_non_accessible_links(array &$i
$route_name = $original_link->getRouteName(); $route_name = $original_link->getRouteName();
$route_params = $original_link->getRouteParameters(); $route_params = $original_link->getRouteParameters();
} }
elseif (!empty($item['url'])) {
/** @var \Drupal\Core\Url $url */
$url = $item['url'];
if ($url->isExternal()) {
// Do not filter external URL at all.
continue;
}
$route_name = $url->getRouteName();
$route_params = $url->getRouteParameters();
}
// Check, if user has access rights to the route. // Check, if user has access rights to the route.
if (!\Drupal::accessManager()->checkNamedRoute($route_name, $route_params)) { if (!$access_manager->checkNamedRoute($route_name, $route_params)) {
unset($items[$route]); unset($items[$menu_id]);
} }
else { else {
if (!empty($items[$route]['below'])) { if (!empty($items[$menu_id]['below'])) {
// Recursively call this function for the child items. // Recursively call this function for the child items.
admin_toolbar_links_access_filter_filter_non_accessible_links($items[$route]['below']); admin_toolbar_links_access_filter_filter_non_accessible_links($items[$menu_id]['below']);
} }
if (empty($items[$route]['below']) && \Drupal::moduleHandler()->moduleExists('admin_toolbar')) { if (empty($items[$menu_id]['below'])) {
// Every child item has been cleared out. // Every child item has been cleared out.
// Now check, if the given route represents an overview page only, // Now check, if the given route represents an overview page only,
...@@ -90,50 +105,18 @@ function admin_toolbar_links_access_filter_filter_non_accessible_links(array &$i ...@@ -90,50 +105,18 @@ function admin_toolbar_links_access_filter_filter_non_accessible_links(array &$i
// unset this item, as there aren't any children left. // unset this item, as there aren't any children left.
// This assumption is only valid, when the admin_toolbar module is // This assumption is only valid, when the admin_toolbar module is
// installed because otherwise we won't have child items at all. // installed because otherwise we won't have child items at all.
if (admin_toolbar_links_access_filter_is_overview_page($route)) { if (admin_toolbar_links_access_filter_is_overview_page($route_name)) {
unset($items[$route]); unset($items[$menu_id]);
}
// If there are no sub-items and the parent does not have a link, then
// it is safe to remove it.
elseif ($route_name === '<nolink>') {
unset($items[$menu_id]);
} }
else { else {
// Let's remove the expanded flag. // Let's remove the expanded flag.
$items[$route]['is_expanded'] = FALSE; $items[$menu_id]['is_expanded'] = FALSE;
}
}
}
}
}
/**
* Implements template_preprocess_admin_block_content().
*/
function admin_toolbar_links_access_filter_admin_block_content(&$variables) {
if (!admin_toolbar_links_access_filter_user_has_admin_role($variables['user'])) {
foreach ($variables['content'] as $key => &$item) {
if (isset($item['url']) && $item['url'] instanceof Url) {
/* @var \Drupal\Core\Url $url */
$url = $item['url'];
if ($url->access()) {
continue;
} }
unset($variables['content'][$key]);
}
// The key is structured in the form: "ID title route",
// concatenated with spaces.
$key_parts = explode(' ', $key);
$route = end($key_parts);
// Special handling for Views pages, as they are not defined
// system routes.
// @TODO check the permission for Views + find a generic way for similar
// cases. Best way would be to get the link entity somehow to properly
// check permissions.
if (strpos($route, 'views_view:') === 0) {
continue;
}
// Check, if user has access rights to the route.
if (!\Drupal::accessManager()->checkNamedRoute($route)) {
unset($variables['content'][$key]);
} }
} }
} }
...@@ -155,7 +138,7 @@ function admin_toolbar_links_access_filter_admin_block_content(&$variables) { ...@@ -155,7 +138,7 @@ function admin_toolbar_links_access_filter_admin_block_content(&$variables) {
* FALSE otherwise. * FALSE otherwise.
*/ */
function admin_toolbar_links_access_filter_is_overview_page($route_name) { function admin_toolbar_links_access_filter_is_overview_page($route_name) {
// @var \Drupal\Core\Routing\RouteProviderInterface $route_provider. /** @var \Drupal\Core\Routing\RouteProviderInterface $route_provider. */
$route_provider = \Drupal::service('router.route_provider'); $route_provider = \Drupal::service('router.route_provider');
$overview_page_controllers = [ $overview_page_controllers = [
'\Drupal\system\Controller\AdminController::index', '\Drupal\system\Controller\AdminController::index',
......
{
"name": "drupal/admin_toolbar_links_access_filter",
"description": "Provides a workaround for the common problem that users with 'Use the administration pages and help' permission see menu links they don't have access permission for. Once the issue https://www.drupal.org/node/296693 be solved, this module will be deprecated.",
"type": "drupal-module",
"keywords": ["Drupal", "Toolbar"],
"homepage": "http://drupal.org/project/admin_toolbar",
"license": "GPL-2.0+",
"authors": [
{
"name": "Wilfrid Roze (eme)",
"homepage": "https://www.drupal.org/u/eme",
"role": "Maintainer"
},
{
"name": "Romain Jarraud (romainj)",
"homepage": "https://www.drupal.org/u/romainj",
"role": "Maintainer"
},
{
"name": "Adrian Cid Almaguer (adriancid)",
"email": "adriancid@gmail.com",
"homepage": "https://www.drupal.org/u/adriancid",
"role": "Maintainer"
},
{
"name": "Mohamed Anis Taktak (matio89)",
"homepage": "https://www.drupal.org/u/matio89",
"role": "Maintainer"
}
],
"support": {
"issues": "https://www.drupal.org/project/issues/admin_toolbar",
"source": "http://cgit.drupalcode.org/admin_toolbar"
},
"require": {
"drupal/admin_toolbar": "^1"
}
}
name: Admin Toolbar Search
description: Provides search of Admin Toolbar items.
package: Administration
type: module
core_version_requirement: ^8.8.0 || ^9.0
configure: admin_toolbar_search.settings
dependencies:
- admin_toolbar:admin_toolbar_tools
# Information added by Drupal.org packaging script on 2022-10-06
version: '3.2.1'
project: 'admin_toolbar'
datestamp: 1665044278
search:
css:
theme:
css/admin.toolbar_search.css: {}
js:
js/admin_toolbar_search.js: {}
dependencies:
- core/jquery
- core/drupal
- core/jquery.once
- core/drupal.autocomplete
admin_toolbar_search.settings:
title: 'Admin Toolbar Search'
description: 'Configure the Admin Toolbar Search module.'
route_name: admin_toolbar_search.settings
parent: system.admin_config_ui
<?php
/**
* @file
* Functionality for search of Admin Toolbar.
*/
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;
/**
* Implements hook_help().
*/
function admin_toolbar_search_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
// Main module help.
case 'help.page.admin_toolbar_search':
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('The Admin Toolbar Search module add a search option to the toolbar for site administrative tasks.') . '</p>';
return $output;
}
}
/**
* Implements hook_toolbar_alter().
*/
function admin_toolbar_search_toolbar_alter(&$items) {
if (!\Drupal::currentUser()->hasPermission('use admin toolbar search')) {
return;
}
$admin_toolbar_tools_enabled = \Drupal::service('module_handler')
->moduleExists('admin_toolbar_tools');
$config = \Drupal::config('admin_toolbar_search.settings');
$display_menu_item = $config->get('display_menu_item');
if (!$display_menu_item) {
$items['administration_mobile_search'] = [
'#type' => 'toolbar_item',
'#weight' => 100,
'tab' => [
'#type' => 'link',
'#title' => new TranslatableMarkup('Search'),
'#url' => Url::fromRoute('system.admin'),
'#attributes' => [
'class' => [
'toolbar-icon',
],
],
],
'#wrapper_attributes' => [
'id' => 'admin-toolbar-mobile-search-tab',
],
];
$items['administration_search'] = [
"#type" => "toolbar_item",
'#weight' => 101,
'tab' => [
'search' => [
'#title' => t('Search'),
'#title_display' => 'invisible',
'#type' => 'search',
'#size' => 30,
'#attributes' => [
'placeholder' => new TranslatableMarkup('Admin Toolbar quick search'),
],
'#id' => 'admin-toolbar-search-input',
],
],
'#attached' => [
'library' => [
'admin_toolbar_search/search',
],
'drupalSettings' => [
'adminToolbarSearch' => [
'loadExtraLinks' => $admin_toolbar_tools_enabled,
],
],
],
'#wrapper_attributes' => [
'id' => 'admin-toolbar-search-tab',
],
'#cache' => [
'contexts' => [
'user.permissions',
],
'tags' => [
'config:admin_toolbar_search.settings',
],
],
];
}
else {
$items['administration_search'] = [
"#type" => "toolbar_item",
'tab' => [
'#type' => 'link',
'#title' => new TranslatableMarkup('Search'),
'#url' => URL::fromRoute('system.admin'),
'#attributes' => [
'class' => [
'toolbar-icon',
],
],
],
'tray' => [
'search' => [
'#title' => t('Search'),
'#type' => 'search',
'#size' => 60,
'#id' => 'admin-toolbar-search-input',
],
],
'#attached' => [
'library' => [
'admin_toolbar_search/search',
],
'drupalSettings' => [
'adminToolbarSearch' => [
'loadExtraLinks' => $admin_toolbar_tools_enabled,
],
],
],
'#wrapper_attributes' => [
"id" => "admin-toolbar-search-tab",
],
'#cache' => [
'contexts' => [
'user.permissions',
],
'tags' => [
'config:admin_toolbar_search.settings',
],
],
];
}
}
admin_toolbar.search:
path: '/admin/admin-toolbar-search'
defaults:
_controller: '\Drupal\admin_toolbar_search\Controller\AdminToolbarSearchController::search'
requirements:
_permission: 'use admin toolbar search'
admin_toolbar_search.settings:
path: '/admin/config/user-interface/admin-toolbar-search-settings'
defaults:
_title: 'Admin toolbar search settings'
_form: 'Drupal\admin_toolbar_search\Form\AdminToolbarSearchSettingsForm'
requirements:
_permission: 'administer site configuration'
services:
admin_toolbar_search.search_links:
class: Drupal\admin_toolbar_search\SearchLinks
arguments:
- '@entity_type.manager'
- '@module_handler'
- '@router.route_provider'
- '@cache_contexts_manager'
- '@cache.toolbar'
- '@config.factory'
admin_toolbar_search.settings:
type: config_object
label: 'Admin Toolbar Search settings'
mapping:
display_menu_item:
type: integer
label: 'How the search input will be displayed'
#admin-toolbar-mobile-search-tab ~ #admin-toolbar-search-tab {
display: none;
}
#admin-toolbar-mobile-search-tab ~ #admin-toolbar-search-tab.visible {
display: block;
width: 100%;
}
#admin-toolbar-mobile-search-tab ~ #admin-toolbar-search-tab .js-form-item.form-item {
margin: 0.75rem 0;
padding-left: 1rem;
padding-right: 1rem;
}
#admin-toolbar-mobile-search-tab .toolbar-item::before {
background-image: url('../../misc/icons/bebebe/loupe.svg');
}
#admin-toolbar-mobile-search-tab ~ #admin-toolbar-search-tab #admin-toolbar-search-input {
width: 100%;
}
@media only screen and (min-width: 769px) {
#admin-toolbar-mobile-search-tab {
display: none;
}
#admin-toolbar-mobile-search-tab ~ #admin-toolbar-search-tab {
display: block;
}
#admin-toolbar-mobile-search-tab ~ #admin-toolbar-search-tab.visible {
width: auto;
}
#admin-toolbar-mobile-search-tab ~ #admin-toolbar-search-tab .js-form-item.form-item {
margin-top: 0.3rem;
margin-bottom: 0;
}
}
#admin-toolbar-search-input {
min-height: 30px;
height: 100%;
padding: 0 0.4rem;
line-height: 1.75rem;
margin: 0;
color: #3b3b3b;
background: #fcfcfa;
border: 1px solid #ccc;
border-radius: unset;
font-size: 1em;
}
.ui-autocomplete .ui-menu-item span.admin-toolbar-search-url {
display: none;
}
.admin-toolbar-search-autocomplete-list {
max-height: 300px;
overflow-y: scroll;
}
.admin-toolbar-search-autocomplete-list .ui-menu-item .ui-state-active {
margin: 0;
}
#toolbar-item-administration-search-tray label {
display: inline-block;
color: #000000;
margin-right: .5em;
font-weight: bold;
}
#toolbar-item-administration-search-tray div.form-item {
margin: 0.75em 0;
}
#toolbar-item-administration-search-tray input {
display: inline-block;
padding: 0.3em 0.4em 0.3em 0.5em;
font-size: 1em;
}
#admin-toolbar-search-tab .toolbar-item:before {
background-image: url('../../misc/icons/bebebe/loupe.svg');
}
#admin-toolbar-search-tab .toolbar-item:active:before,
#admin-toolbar-search-tab .toolbar-item.is-active:before {
background-image: url('../../misc/icons/ffffff/loupe.svg');
}
#toolbar-item-administration-search-tray div.form-item.js-form-type-textfield {
margin: 0.75em 0;
}
/**
* @file
* Behaviors for the search widget in the admin toolbar.
*/
(function ($, Drupal) {
'use strict';
Drupal.behaviors.adminToolbarSearch = {
// If extra links have been fetched.
extraFetched: false,
attach: function (context) {
if (context != document) {
return;
}
var $self = this;
$('#toolbar-bar', context).once('admin-toolbar-search').each(function () {
$self.links = [];
var $searchTab = $(this).find('#admin-toolbar-search-tab')
var $searchInput = $searchTab.find('#admin-toolbar-search-input');
if ($searchInput.length === 0) {
return;
}
$searchInput.autocomplete({
minLength: 2,
position: { collision : 'fit' },
source: function (request, response) {
var data = $self.handleAutocomplete(request.term);
if (!$self.extraFetched && drupalSettings.adminToolbarSearch.loadExtraLinks) {
$.getJSON( Drupal.url('admin/admin-toolbar-search'), function ( data ) {
$(data).each(function () {
var item = this;
item.label = this.labelRaw + ' ' + this.value;
$self.links.push(item);
});
$self.extraFetched = true;
var results = $self.handleAutocomplete(request.term);
response(results);
});
}
else {
response(data);
}
},
open: function () {
var zIndex = $('#toolbar-item-administration-tray')
.css('z-index') + 1;
$(this).autocomplete('widget').css('z-index', zIndex);
return false;
},
select: function (event, ui) {
if (ui.item.value) {
location.href = ui.item.value;
return false;
}
}
}).data('ui-autocomplete')._renderItem = (function (ul, item) {
ul.addClass('admin-toolbar-search-autocomplete-list');
return $('<li>')
.append('<div>' + item.labelRaw + ' <span class="admin-toolbar-search-url">' + item.value + '</span></div>')
.appendTo(ul);
});
// Populate the links for search results when the input is pressed.
$searchInput.focus(function () {
Drupal.behaviors.adminToolbarSearch.populateLinks($self);
});
// Show/hide search input field when mobile tab item is pressed.
$('#admin-toolbar-mobile-search-tab .toolbar-item', context).click(function (e) {
e.preventDefault();
$(this).toggleClass('is-active');
$searchTab.toggleClass('visible');
$searchInput.focus();
});
});
},
getItemLabel: function (item) {
var breadcrumbs = [];
$(item).parents().each(function () {
if ($(this).hasClass('menu-item')) {
var $link = $(this).find('a:first');
if ($link.length && !$link.hasClass('admin-toolbar-search-ignore')) {
breadcrumbs.unshift($link.text());
}
}
});
return breadcrumbs.join(' > ');
},
handleAutocomplete: function (term) {
var $self = this;
var keywords = term.split(" "); // Split search terms into list.
var suggestions = [];
$self.links.forEach(function (element) {
var label = element.label.toLowerCase();
// Add exact matches.
if (label.indexOf(term.toLowerCase()) >= 0) {
suggestions.push(element);
}
else {
// Add suggestions where it matches all search terms.
var matchCount = 0;
keywords.forEach(function (keyword) {
if (label.indexOf(keyword.toLowerCase()) >= 0) {
matchCount++;
}
});
if (matchCount == keywords.length) {
suggestions.push(element);
}
}
});
return suggestions;
},
/**
* Populates the links in admin toolbar search.
*/
populateLinks: function ($self) {
// Populate only when links array is empty (only the first time).
if ($self.links.length === 0) {
var getUrl = window.location;
var baseUrl = getUrl.protocol + "//" + getUrl.host + "/";
$('.toolbar-tray a[data-drupal-link-system-path]').each(function () {
if (this.href !== baseUrl) {
var label = $self.getItemLabel(this);
$self.links.push({
'value': this.href,
'label': label + ' ' + this.href,
'labelRaw': Drupal.checkPlain(label)
});
}
});
}
},
};
})(jQuery, Drupal);
<?php
namespace Drupal\admin_toolbar_search\Controller;
use Drupal\admin_toolbar_search\SearchLinks;
use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
/**
* Class AdminToolbarSearchController to the search functionality.
*
* @package Drupal\admin_toolbar_tools\Controller
*/
class AdminToolbarSearchController extends ControllerBase {
/**
* The search links service.
*
* @var \Drupal\admin_toolbar_search\SearchLinks
*/
protected $links;
/**
* Constructs an AdminToolbarSearchController object.
*
* @param \Drupal\admin_toolbar_search\SearchLinks $links
* The search links service.
*/
public function __construct(SearchLinks $links) {
$this->links = $links;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('admin_toolbar_search.search_links')
);
}
/**
* Return additional search links.
*/
public function search() {
return new JsonResponse($this->links->getLinks());
}
}
<?php
namespace Drupal\admin_toolbar_search\Form;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
/**
* Configure Admin Toolbar Search settings for this site.
*/
class AdminToolbarSearchSettingsForm extends ConfigFormBase {
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'admin_toolbar_search_admin_toolbar_search_settings';
}
/**
* {@inheritdoc}
*/
protected function getEditableConfigNames() {
return ['admin_toolbar_search.settings'];
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$form['display_menu_item'] = [
'#type' => 'checkbox',
'#title' => $this->t('Display the search input as a menu item.'),
'#description' => $this->t("If set, instead of displaying a text input field, it displays a menu item in the toolbar so the user has to click on it to toggle the search input."),
'#default_value' => $this->config('admin_toolbar_search.settings')->get('display_menu_item'),
];
return parent::buildForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$this->config('admin_toolbar_search.settings')
->set('display_menu_item', $form_state->getValue('display_menu_item'))
->save();
parent::submitForm($form, $form_state);
}
}
<?php
namespace Drupal\Tests\admin_toolbar_search\Functional;
use Drupal\Core\Url;
use Drupal\Tests\BrowserTestBase;
/**
* Test the functionality of admin toolbar search.
*
* @group admin_toolbar
* @group admin_toolbar_search
*/
class AdminToolbarSearchSettingTest extends BrowserTestBase {
/**
* {@inheritdoc}
*/
protected $defaultTheme = 'stark';
/**
* {@inheritdoc}
*/
protected static $modules = [
'admin_toolbar_search',
'node',
'media',
'field_ui',
'menu_ui',
'block',
];
/**
* A user with the 'Use Admin Toolbar search' permission.
*
* @var \Drupal\user\UserInterface
*/
protected $userWithAccess;
/**
* A test user without the 'Use Admin Toolbar search' permission..
*
* @var \Drupal\user\UserInterface
*/
protected $noAccessUser;
/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();
$permissions = [
'access toolbar',
'administer menu',
'access administration pages',
'administer site configuration',
'administer content types',
];
$this->noAccessUser = $this->drupalCreateUser($permissions);
$permissions[] = 'use admin toolbar search';
$this->userWithAccess = $this->drupalCreateUser($permissions);
}
/**
* Tests search functionality without admin_toolbar_tools enabled.
*/
public function testToolbarSearch() {
$this->drupalLogin($this->userWithAccess);
$this->drupalGet(Url::fromRoute('system.admin'));
$this->assertSession()->responseNotContains('id="toolbar-item-administration-search');
$this->config('admin_toolbar_search.settings')->set('display_menu_item', 1);
$this->config('admin_toolbar_search.settings')->save();
$this->drupalGet(Url::fromRoute('system.admin'));
$this->assertSession()->responseContains('id="toolbar-item-administration-search');
$this->config('admin_toolbar_search.settings')->set('display_menu_item', 0);
$this->config('admin_toolbar_search.settings')->save();
$this->drupalGet(Url::fromRoute('system.admin'));
$this->assertSession()->responseNotContains('id="toolbar-item-administration-search');
}
}
<?php
namespace Drupal\Tests\admin_toolbar_search\FunctionalJavascript;
/**
* Test the functionality of admin toolbar search.
*
* @group admin_toolbar
* @group admin_toolbar_search
*/
class AdminToolbarSearchTest extends AdminToolbarSearchTestBase {
/**
* Tests search functionality without admin_toolbar_tools enabled.
*/
public function testToolbarSearch() {
$search_tab = '#admin-toolbar-search-tab';
$search_toolbar_item = '#toolbar-item-administration-search';
$search_tray = '#toolbar-item-administration-search-tray';
$this->drupalLogin($this->userWithAccess);
$assert_session = $this->assertSession();
$assert_session->responseContains('admin.toolbar_search.css');
$assert_session->responseContains('admin_toolbar_search.js');
$assert_session->waitForElementVisible('css', $search_tab);
$assert_session->waitForElementVisible('css', $search_toolbar_item);
$assert_session->waitForElementVisible('css', $search_tray);
$this->assertSuggestionContains('perfor', 'admin/config/development/performance');
$this->assertSuggestionContains('develop', 'admin/config/development/maintenance');
$this->assertSuggestionContains('types', 'admin/structure/types');
}
/**
* Tests a user without the search permission can't use search.
*/
public function testNoAccess() {
$search_tab = '#admin-toolbar-search-tab';
$search_toolbar_item = '#toolbar-item-administration-search';
$search_tray = '#toolbar-item-administration-search-tray';
$this->drupalLogin($this->noAccessUser);
$assert_session = $this->assertSession();
$assert_session->responseNotContains('admin.toolbar_search.css');
$assert_session->responseNotContains('admin_toolbar_search.js');
$assert_session->elementNotExists('css', $search_tab);
$assert_session->elementNotExists('css', $search_toolbar_item);
$assert_session->elementNotExists('css', $search_tray);
}
}
<?php
namespace Drupal\Tests\admin_toolbar_search\FunctionalJavascript;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
use Drupal\system\Entity\Menu;
/**
* Base class for testing the functionality of admin toolbar search.
*
* @group admin_toolbar
* @group admin_toolbar_search
*/
abstract class AdminToolbarSearchTestBase extends WebDriverTestBase {
/**
* {@inheritdoc}
*/
protected $defaultTheme = 'stark';
/**
* {@inheritdoc}
*/
protected static $modules = [
'admin_toolbar_search',
'node',
'media',
'field_ui',
'menu_ui',
'block',
];
/**
* A user with the 'Use Admin Toolbar search' permission.
*
* @var \Drupal\user\UserInterface
*/
protected $userWithAccess;
/**
* A test user without the 'Use Admin Toolbar search' permission..
*
* @var \Drupal\user\UserInterface
*/
protected $noAccessUser;
/**
* {@inheritdoc}
*/
public function setUp(): void {
parent::setUp();
$baby_names = [
'ada' => 'Ada',
'amara' => 'Amara',
'amelia' => 'Amelia',
'arabella' => 'Arabella',
'asher' => 'Asher',
'astrid' => 'Astrid',
'atticus' => 'Atticus',
'aurora' => 'Aurora',
'ava' => 'Ava',
'cora' => 'Cora',
'eleanor' => 'Eleanor',
'eloise' => 'Eloise',
'felix' => 'Felix',
'freya' => 'Freya',
'genevieve' => 'Genevieve',
'isla' => 'Isla',
'jasper' => 'Jasper',
'luna' => 'Luna',
'maeve' => 'Maeve',
'milo' => 'Milo',
'nora' => 'Nora',
'olivia' => 'Olivia',
'ophelia' => 'Ophelia',
'posie' => 'Posie',
'rose' => 'Rose',
'silas' => 'Silas',
'soren' => 'Soren',
];
foreach ($baby_names as $id => $label) {
$menu = Menu::create([
'id' => $id,
'label' => $label,
]);
$menu->save();
}
$this->drupalPlaceBlock('local_tasks_block');
$permissions = [
'access toolbar',
'administer menu',
'access administration pages',
'administer site configuration',
'administer content types',
];
$this->noAccessUser = $this->drupalCreateUser($permissions);
$permissions[] = 'use admin toolbar search';
$this->userWithAccess = $this->drupalCreateUser($permissions);
}
/**
* Assert that the search suggestions contain a given string with given input.
*
* @param string $search
* The string to search for.
* @param string $contains
* Some HTML that is expected to be within the suggestions element.
*/
protected function assertSuggestionContains($search, $contains) {
$this->resetSearch();
$page = $this->getSession()->getPage();
$page->fillField('admin-toolbar-search-input', $search);
$this->getSession()->getDriver()->keyDown('//input[@id="admin-toolbar-search-input"]', ' ');
$page->waitFor(3, function () use ($page) {
return ($page->find('css', 'ul.ui-autocomplete')->isVisible() === TRUE);
});
$suggestions_markup = $page->find('css', 'ul.ui-autocomplete')->getHtml();
$this->assertStringContainsString($contains, $suggestions_markup);
}
/**
* Assert that the search suggestions does not contain a given string.
*
* Assert that the search suggestions does not contain a given string with a
* given input.
*
* @param string $search
* The string to search for.
* @param string $contains
* Some HTML that is not expected to be within the suggestions element.
*/
protected function assertSuggestionNotContains($search, $contains) {
$this->resetSearch();
$page = $this->getSession()->getPage();
$page->fillField('admin-toolbar-search-input', $search);
$this->getSession()->getDriver()->keyDown('//input[@id="admin-toolbar-search-input"]', ' ');
$page->waitFor(3, function () use ($page) {
return ($page->find('css', 'ul.ui-autocomplete')->isVisible() === TRUE);
});
if ($page->find('css', 'ul.ui-autocomplete')->isVisible() === FALSE) {
return;
}
else {
$suggestions_markup = $page->find('css', 'ul.ui-autocomplete')->getHtml();
$this->assertStringNotContainsString($contains, $suggestions_markup);
}
}
/**
* Search for an empty string to clear out the autocomplete suggestions.
*/
protected function resetSearch() {
$page = $this->getSession()->getPage();
// Empty out the suggestions.
$page->fillField('admin-toolbar-search-input', '');
$this->getSession()->getDriver()->keyDown('//input[@id="admin-toolbar-search-input"]', ' ');
$page->waitFor(3, function () use ($page) {
return ($page->find('css', 'ul.ui-autocomplete')->isVisible() === FALSE);
});
}
/**
* Checks that there is a link with the specified url in the admin toolbar.
*
* @param string $url
* The url to assert exists in the admin menu.
*
* @throws \Behat\Mink\Exception\ElementNotFoundException
*/
protected function assertMenuHasHref($url) {
$this->assertSession()
->elementExists('xpath', '//div[@id="toolbar-item-administration-tray"]//a[contains(@href, "' . $url . '")]');
}
/**
* Checks that there is no link with the specified url in the admin toolbar.
*
* @param string $url
* The url to assert exists in the admin menu.
*
* @throws \Behat\Mink\Exception\ExpectationException
*/
protected function assertMenuDoesNotHaveHref($url) {
$this->assertSession()
->elementNotExists('xpath', '//div[@id="toolbar-item-administration-tray"]//a[contains(@href, "' . $url . '")]');
}
}
<?php
namespace Drupal\Tests\admin_toolbar_search\FunctionalJavascript;
use Drupal\media\Entity\MediaType;
use Drupal\Tests\media\Traits\MediaTypeCreationTrait;
/**
* Test the functionality of admin toolbar search.
*
* @group admin_toolbar
* @group admin_toolbar_search
*/
class AdminToolbarToolsSearchTest extends AdminToolbarSearchTestBase {
use MediaTypeCreationTrait;
/**
* {@inheritdoc}
*/
protected static $modules = [
'admin_toolbar_tools',
'admin_toolbar_search',
'node',
'media',
'field_ui',
'menu_ui',
'block',
];
/**
* The admin user for tests.
*
* @var \Drupal\user\UserInterface
*/
protected $adminUser;
/**
* {@inheritdoc}
*/
public function setUp(): void {
parent::setUp();
$this->drupalCreateContentType([
'type' => 'article',
'name' => 'Article',
]);
$dog_names = [
'archie' => 'Archie',
'bailey' => 'Bailey',
'bella' => 'Bella',
'buddy' => 'Buddy',
'charlie' => 'Charlie',
'coco' => 'Coco',
'daisy' => 'Daisy',
'frankie' => 'Frankie',
'jack' => 'Jack',
'lola' => 'Lola',
'lucy' => 'Lucy',
'max' => 'Max',
'milo' => 'Milo',
'molly' => 'Molly',
'ollie' => 'Ollie',
'oscar' => 'Oscar',
'rosie' => 'Rosie',
'ruby' => 'Ruby',
'teddy' => 'Teddy',
'toby' => 'Toby',
'tonga' => 'Tonga',
'tracey' => 'Tracey',
'tuna' => 'Tuna',
'uno' => 'Uno',
'venus' => 'Venus',
'vicky' => 'Vicky',
'wimpy' => 'Wimpy',
'yellow' => 'Yellow',
'zac' => 'zac',
'zora' => 'zora',
];
foreach ($dog_names as $machine_name => $label) {
$this->createMediaType('image', [
'id' => $machine_name,
'label' => $label,
]);
}
$this->adminUser = $this->drupalCreateUser([
'access toolbar',
'administer menu',
'access administration pages',
'administer site configuration',
'administer content types',
'administer node fields',
'access media overview',
'administer media',
'administer media fields',
'administer media form display',
'administer media display',
'administer media types',
'use admin toolbar search',
]);
}
/**
* Tests search functionality with admin_toolbar_tools enabled.
*/
public function testToolbarSearch() {
$search_tab = '#admin-toolbar-search-tab';
$search_toolbar_item = '#toolbar-item-administration-search';
$search_tray = '#toolbar-item-administration-search-tray';
$this->drupalLogin($this->adminUser);
$assert_session = $this->assertSession();
$assert_session->responseContains('admin.toolbar_search.css');
$assert_session->responseContains('admin_toolbar_search.js');
$assert_session->waitForElementVisible('css', $search_tab);
$assert_session->waitForElementVisible('css', $search_toolbar_item);
$assert_session->waitForElementVisible('css', $search_tray);
$this->assertSuggestionContains('basic', 'admin/config/system/site-information');
// Rebuild menu items.
drupal_flush_all_caches();
// Test that the route admin_toolbar.search returns expected json.
$this->drupalGet('/admin/admin-toolbar-search');
$search_menus = [
'maeve',
'milo',
'nora',
'olivia',
'ophelia',
'posie',
'rose',
'silas',
'soren',
];
$toolbar_menus = [
'ada',
'amara',
'amelia',
'arabella',
'asher',
'astrid',
'atticus',
'aurora',
'ava',
];
foreach ($search_menus as $menu_id) {
$assert_session->responseContains('\/admin\/structure\/menu\/manage\/' . $menu_id);
}
foreach ($toolbar_menus as $menu_id) {
$assert_session->responseNotContains('\/admin\/structure\/menu\/manage\/' . $menu_id);
}
$this->drupalGet('/admin');
foreach ($search_menus as $menu_id) {
$this->assertMenuDoesNotHaveHref('/admin/structure/menu/manage/' . $menu_id);
}
foreach ($toolbar_menus as $menu_id) {
$this->assertMenuHasHref('/admin/structure/menu/manage/' . $menu_id);
}
$this->drupalGet('admin/structure/types/manage/article/fields');
$assert_session->waitForElementVisible('css', $search_tray);
$this->assertSuggestionContains('article manage fields', '/admin/structure/types/manage/article/fields');
$suggestions = $assert_session
->waitForElementVisible('css', 'ul.ui-autocomplete');
// Assert there is only one suggestion with a link to
// /admin/structure/types/manage/article/fields.
$count = count($suggestions->findAll('xpath', '//span[contains(text(), "/admin/structure/types/manage/article/fields")]'));
$this->assertEquals(1, $count);
// Test that bundle within admin toolbar appears in search.
$this->assertSuggestionContains('lola', 'admin/structure/media/manage/lola/fields');
// Assert that a link after the limit doesn't appear in admin toolbar.
$zora_url = '/admin/structure/media/manage/zora/fields';
$assert_session->elementNotContains('css', '#toolbar-administration', $zora_url);
// Assert that a link excluded from admin toolbar appears in search.
$this->assertSuggestionContains('zora', $zora_url);
// Test that adding a new bundle updates the extra links loaded from
// admin_toolbar.search route.
$this->createMediaType('image', [
'id' => 'zuzu',
'label' => 'Zuzu',
]);
$this->drupalGet('admin');
$assert_session->waitForElementVisible('css', $search_tray);
$this->assertSuggestionContains('zuzu', '/admin/structure/media/manage/zuzu/fields');
// Test that deleting a bundle updates the extra links loaded from
// admin_toolbar.search route.
$zora = MediaType::load('zora');
$zora->delete();
$this->getSession()->reload();
$assert_session->waitForElementVisible('css', $search_tray);
$this->assertSuggestionNotContains('zora', $zora);
}
}
...@@ -15,7 +15,7 @@ INTRODUCTION ...@@ -15,7 +15,7 @@ INTRODUCTION
Admin Toolbar Extra Tools provides menu links to administration pages or actions Admin Toolbar Extra Tools provides menu links to administration pages or actions
(eg. Flushing caches) that are not generated by Drupal core. It adds menu items (eg. Flushing caches) that are not generated by Drupal core. It adds menu items
that are not generated by Drupal core. For example there are no menu items for that are not generated by Drupal core. For example there are no menu items for
each content type by default or menu links to Manage fields on each entity each content type by default or menu links to Manage fields on each entity
types. That's the purpose of Admin Toolbar Extra Tools to add them. types. That's the purpose of Admin Toolbar Extra Tools to add them.
* For a full description of the module, visit the project page: * For a full description of the module, visit the project page:
...@@ -58,5 +58,7 @@ Current maintainers: ...@@ -58,5 +58,7 @@ Current maintainers:
This project has been sponsored by: This project has been sponsored by:
* emerya * emerya
Founded in 2009, emerya is a human-sized company, dedicated to the design and Founded in 2009, emerya is a human-sized company, dedicated to the design and
implementation of web interfaces. Visit: http://http://emerya.fr/ for more implementation of web interfaces. Visit: http://emerya.fr/ for more
information. information.
* trained people
Trained People is a training company focused on Drupal.
name: Admin Toolbar Extra Tools name: Admin Toolbar Extra Tools
description: Adds menu links to the Admin Toolbar. description: Adds menu links like Flush cache, Run cron, Run updates, and Logout under Drupal icon.
package: Administration package: Administration
configure: admin_toolbar_tools.settings
type: module type: module
# core: 8.x core_version_requirement: ^8.8.0 || ^9.0
dependencies: dependencies:
- admin_toolbar:admin_toolbar - admin_toolbar:admin_toolbar
- drupal:system (>=8.6)
# Information added by Drupal.org packaging script on 2019-05-22 # Information added by Drupal.org packaging script on 2022-10-06
version: '8.x-1.27' version: '3.2.1'
core: '8.x'
project: 'admin_toolbar' project: 'admin_toolbar'
datestamp: 1558552277 datestamp: 1665044278
<?php
/**
* @file
* Install, update and uninstall functions for the Admin Toolbar Tools module.
*/
/**
* Install the Admin Toolbar Search module.
*/
function admin_toolbar_tools_update_8001() {
// Installing the Admin Toolbar Search module.
\Drupal::service('module_installer')->install(['admin_toolbar_search']);
}
/**
* Default setting for maximum number of bundles per entity type to display.
*/
function admin_toolbar_tools_update_8201() {
\Drupal::service('config.factory')
->getEditable('admin_toolbar_tools.settings')
->set('max_bundle_number', 20)
->save(TRUE);
}
/**
* Default setting for enable hoverintent.
*/
function admin_toolbar_tools_update_8202() {
\Drupal::service('config.factory')
->getEditable('admin_toolbar_tools.settings')
->set('hoverintent_functionality', TRUE)
->save(TRUE);
}
...@@ -40,7 +40,7 @@ admin_toolbar_tools.flush: ...@@ -40,7 +40,7 @@ admin_toolbar_tools.flush:
menu_name: admin menu_name: admin
admin_toolbar_tools.cssjs: admin_toolbar_tools.cssjs:
title: 'Flush CSS and Javascript' title: 'Flush CSS and JavaScript'
route_name: admin_toolbar_tools.cssjs route_name: admin_toolbar_tools.cssjs
parent: admin_toolbar_tools.flush parent: admin_toolbar_tools.flush
menu_name: admin menu_name: admin
...@@ -74,3 +74,19 @@ admin_toolbar_tools.flush_rendercache: ...@@ -74,3 +74,19 @@ admin_toolbar_tools.flush_rendercache:
route_name: admin_toolbar_tools.flush_rendercache route_name: admin_toolbar_tools.flush_rendercache
parent: admin_toolbar_tools.flush parent: admin_toolbar_tools.flush
menu_name: admin menu_name: admin
admin_toolbar_tools.theme_rebuild:
title: 'Rebuild theme registry'
route_name: admin_toolbar_tools.theme_rebuild
parent: admin_toolbar_tools.flush
menu_name: admin
admin_toolbar_tools.extra_links:
deriver: \Drupal\admin_toolbar_tools\Plugin\Derivative\ExtraLinks
menu_name: admin
admin_toolbar_tools.settings:
title: 'Admin Toolbar Tools'
description: 'Configure the Admin Toolbar Tools module.'
route_name: admin_toolbar_tools.settings
parent: system.admin_config_ui
...@@ -11,7 +11,7 @@ admin_toolbar_tools.cssjs: ...@@ -11,7 +11,7 @@ admin_toolbar_tools.cssjs:
path: '/admin/flush/cssjs' path: '/admin/flush/cssjs'
defaults: defaults:
_controller: '\Drupal\admin_toolbar_tools\Controller\ToolbarController::flushJsCss' _controller: '\Drupal\admin_toolbar_tools\Controller\ToolbarController::flushJsCss'
_title: 'Flush Css and Javascript' _title: 'Flush CSS and JavaScript'
requirements: requirements:
_permission: 'administer site configuration' _permission: 'administer site configuration'
_csrf_token: 'TRUE' _csrf_token: 'TRUE'
...@@ -70,6 +70,15 @@ admin_toolbar_tools.flush_twig: ...@@ -70,6 +70,15 @@ admin_toolbar_tools.flush_twig:
_permission: 'administer site configuration' _permission: 'administer site configuration'
_csrf_token: 'TRUE' _csrf_token: 'TRUE'
admin_toolbar_tools.theme_rebuild:
path: '/admin/flush/theme_rebuild'
defaults:
_controller: '\Drupal\admin_toolbar_tools\Controller\ToolbarController::themeRebuild'
_title: 'Theme Rebuild'
requirements:
_permission: 'administer site configuration'
_csrf_token: 'TRUE'
admin_toolbar.run.cron: admin_toolbar.run.cron:
path: '/run-cron' path: '/run-cron'
defaults: defaults:
...@@ -78,3 +87,11 @@ admin_toolbar.run.cron: ...@@ -78,3 +87,11 @@ admin_toolbar.run.cron:
requirements: requirements:
_permission: 'administer site configuration' _permission: 'administer site configuration'
_csrf_token: 'TRUE' _csrf_token: 'TRUE'
admin_toolbar_tools.settings:
path: '/admin/config/user-interface/admin-toolbar-tools'
defaults:
_form: '\Drupal\admin_toolbar_tools\Form\AdminToolbarToolsSettingsForm'
_title: 'Admin Toolbar Tools settings'
requirements:
_permission: 'administer site configuration'
services:
admin_toolbar_tools.helper:
class: Drupal\admin_toolbar_tools\AdminToolbarToolsHelper
arguments:
- '@entity_type.manager'
- '@plugin.manager.menu.local_task'
- '@current_route_match'
{
"name": "drupal/admin_toolbar_tools",
"description": "Adds menu links to the Admin Toolbar.",
"type": "drupal-module",
"keywords": ["Drupal", "Toolbar"],
"homepage": "http://drupal.org/project/admin_toolbar",
"license": "GPL-2.0+",
"authors": [
{
"name": "Wilfrid Roze (eme)",
"homepage": "https://www.drupal.org/u/eme",
"role": "Maintainer"
},
{
"name": "Romain Jarraud (romainj)",
"homepage": "https://www.drupal.org/u/romainj",
"role": "Maintainer"
},
{
"name": "Adrian Cid Almaguer (adriancid)",
"email": "adriancid@gmail.com",
"homepage": "https://www.drupal.org/u/adriancid",
"role": "Maintainer"
},
{
"name": "Mohamed Anis Taktak (matio89)",
"homepage": "https://www.drupal.org/u/matio89",
"role": "Maintainer"
}
],
"support": {
"issues": "https://www.drupal.org/project/issues/admin_toolbar",
"source": "http://cgit.drupalcode.org/admin_toolbar"
},
"require": {
"drupal/admin_toolbar": "^1",
"drupal/core": "~8.6"
}
}
max_bundle_number: 20
hoverintent_functionality: true
show_local_tasks: false
admin_toolbar_tools.settings:
type: config_object
label: 'Admin Toolbar Tools settings'
mapping:
max_bundle_number:
type: integer
label: 'Number of bundles per entity type to display'
hoverintent_functionality:
type: boolean
label: 'Enable or disable hoverintent functionality'
show_local_tasks:
type: boolean
label: 'Show local tasks in toolbar'
...@@ -2,16 +2,46 @@ ...@@ -2,16 +2,46 @@
text-indent: -9999px; text-indent: -9999px;
} }
.toolbar-icon-admin-toolbar-tools-help:before { .toolbar-icon-9 .toolbar-icon-admin-toolbar-tools-help:before,
.toolbar-icon-10 .toolbar-icon-admin-toolbar-tools-help:before {
box-sizing: content-box; box-sizing: content-box;
background-image: url(../misc/icons/ffffff/d8-item.svg); background-image: url(../misc/icons/ffffff/drupal-9-logo.svg);
padding-bottom: 0;
padding-left: 2px;
padding-right: 2px;
padding-top: 2px;
margin-left: 4px;
}
.toolbar-icon-9 .toolbar-icon-admin-toolbar-tools-help:active:before,
.toolbar-icon-9 .toolbar-icon-admin-toolbar-tools-help.active:before,
.toolbar-icon-10 .toolbar-icon-admin-toolbar-tools-help:active:before,
.toolbar-icon-10 .toolbar-icon-admin-toolbar-tools-help.active:before {
background-image: url(../misc/icons/ffffff/drupal-9-logo.svg);
}
.toolbar-icon-8 .toolbar-icon-admin-toolbar-tools-help:before {
box-sizing: content-box;
background-image: url(../misc/icons/ffffff/drupal-8-logo.svg);
padding-bottom: 0; padding-bottom: 0;
padding-left: 4px; padding-left: 4px;
padding-right: 8px; padding-right: 8px;
padding-top: 2px; padding-top: 2px;
} }
.toolbar-icon-admin-toolbar-tools-help:active:before, .toolbar-icon-8 .toolbar-icon-admin-toolbar-tools-help:active:before,
.toolbar-icon-admin-toolbar-tools-help.active:before { .toolbar-icon-8 .toolbar-icon-admin-toolbar-tools-help.active:before {
background-image: url(../misc/icons/ffffff/d8-item.svg); background-image: url(../misc/icons/ffffff/drupal-8-logo.svg);
}
.toolbar-oriented .toolbar-bar .local-tasks-toolbar-tab {
float: right;
}
.toolbar-horizontal .local-tasks-toolbar-tab .toolbar-menu {
float: right;
}
.toolbar-bar .toolbar-icon-local-tasks:before {
background-image: url(../misc/icons/bebebe/tasks.svg);
} }
<svg fill="#bebebe" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M4 10.5c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm0-6c-.83 0-1.5.67-1.5 1.5S3.17 7.5 4 7.5 5.5 6.83 5.5 6 4.83 4.5 4 4.5zm0 12c-.83 0-1.5.68-1.5 1.5s.68 1.5 1.5 1.5 1.5-.68 1.5-1.5-.67-1.5-1.5-1.5zM7 19h14v-2H7v2zm0-6h14v-2H7v2zm0-8v2h14V5H7z"/>
<path d="M0 0h24v24H0V0z" fill="none"/>
</svg>
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" preserveAspectRatio="xMinYMin" viewBox="0 0 611 646"><path fill="#2ba9e0" d="M 161.14248,607.07981 C 135.931,577.51327 120.7662,539.33875 120.7662,497.60876 c 0,-87.01545 66.15644,-158.68624 151.648,-168.60413 -14.59612,-20.95856 -23.31588,-46.40824 -23.31588,-73.72922 0,-71.85792 58.95316,-129.86822 131.7442,-129.86822 6.06592,0 11.94228,0.37426 17.62908,1.12278 C 355.44148,89.85249 312.41136,52.61362 278.48012,12.00641 295.73008,190.15417 114.1316,125.40719 46.8378,289.70733 1.91208,399.73977 42.47792,535.78328 161.14248,607.07981 Z m 143.1178,-351.8044 c 0,41.72999 34.31036,75.41339 76.39268,75.41339 42.08232,0 76.58224,-33.87053 76.58224,-75.41339 0,-41.72999 -34.31036,-75.41339 -76.39268,-75.41339 -42.08232,0 -76.58224,33.6834 -76.58224,75.41339 z m 112.97776,124.81571 c 29.57136,30.50219 47.76912,71.85792 47.76912,117.51764 0,57.82317 -29.19224,108.72253 -73.73884,139.41185 82.4586,-25.07542 150.7002,-86.26693 181.21936,-160.37041 42.27188,-102.54724 2.8434,-179.6448 -63.12348,-249.63142 2.08516,8.98224 3.22252,18.52587 3.22252,28.0695 -0.18956,59.50734 -40.37628,109.47105 -95.34868,125.00284 z m -124.35136,18.90013 c -55.16196,0 -99.89812,44.16268 -99.89812,98.61751 0,54.45483 44.73616,98.61751 99.89812,98.61751 55.16196,0 99.89812,-44.16268 99.89812,-98.61751 0,-54.45483 -44.73616,-98.61751 -99.89812,-98.61751 z" /></svg>
<svg width="214" height="214" viewBox="0 0 214 214" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M172 59C154.963 36 135 19 105 0C110.5 30.5 58.5 50 41 68.5C23.5 87 17 106.188 17 125.902C17 174.204 57.6985 213.5 106 213.5C154.302 213.5 196.5 174.204 196.5 125.902C196.5 106.188 189.037 82 172 59Z" fill="#008CF2"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M105.318 83.5C92.4745 83.5 81.0102 88.6894 73.0589 96.8593C70.2775 99.7171 68.2075 104.354 67.3793 109.481C66.5258 114.766 67.2414 118.928 68.2111 120.763C58 122 51.5 113 52.5 104.5C53.2059 98.5 55.8754 91.5746 61.5929 85.7C72.5277 74.4646 88.115 67.5 105.318 67.5C137.872 67.5 165 92.6234 165 124.5C165 156.377 137.872 181.5 105.318 181.5C100.829 181.5 93.7529 180.358 90 180C85.3088 179.654 71.5 179 64 182L83.5 108.5C85.5 102 91.7553 98.2637 102.602 99.6635L84.5586 164.168C86.3276 164.183 88.0427 164.274 89.7083 164.397C91.628 164.538 93.3802 164.707 95.0667 164.87C98.4724 165.198 101.61 165.5 105.318 165.5C129.85 165.5 149 146.747 149 124.5C149 102.253 129.85 83.5 105.318 83.5Z" fill="white"/>
</svg>
<svg width="214" height="214" viewBox="0 0 214 214" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M172 59C154.963 36 135 19 105 0C110.5 30.5 58.5 50 41 68.5C23.5 87 17 106.188 17 125.902C17 174.204 57.6985 213.5 106 213.5C154.302 213.5 196.5 174.204 196.5 125.902C196.5 106.188 189.037 82 172 59Z" fill="#008CF2"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M105.318 83.5C92.4745 83.5 81.0102 88.6894 73.0589 96.8593C70.2775 99.7171 68.2075 104.354 67.3793 109.481C66.5258 114.766 67.2414 118.928 68.2111 120.763C58 122 51.5 113 52.5 104.5C53.2059 98.5 55.8754 91.5746 61.5929 85.7C72.5277 74.4646 88.115 67.5 105.318 67.5C137.872 67.5 165 92.6234 165 124.5C165 156.377 137.872 181.5 105.318 181.5C100.829 181.5 93.7529 180.358 90 180C85.3088 179.654 71.5 179 64 182L83.5 108.5C85.5 102 91.7553 98.2637 102.602 99.6635L84.5586 164.168C86.3276 164.183 88.0427 164.274 89.7083 164.397C91.628 164.538 93.3802 164.707 95.0667 164.87C98.4724 165.198 101.61 165.5 105.318 165.5C129.85 165.5 149 146.747 149 124.5C149 102.253 129.85 83.5 105.318 83.5Z" fill="white"/>
</svg>
<?php
namespace Drupal\admin_toolbar_tools;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Menu\LocalTaskManager;
use Drupal\Core\Render\Element;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Security\TrustedCallbackInterface;
/**
* Admin Toolbar Tools helper service.
*/
class AdminToolbarToolsHelper implements TrustedCallbackInterface {
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* The local task manger.
*
* @var \Drupal\Core\Menu\LocalTaskManager
* The local task manager menu.
*/
protected $localTaskManager;
/**
* The route match interface.
*
* @var \Drupal\Core\Routing\RouteMatchInterface
* The route match.
*/
protected $routeMatch;
/**
* Create an AdminToolbarToolsHelper object.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\Core\Menu\LocalTaskManager $local_task_manager
* The local task manager.
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The route match.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager, LocalTaskManager $local_task_manager, RouteMatchInterface $route_match) {
$this->entityTypeManager = $entity_type_manager;
$this->localTaskManager = $local_task_manager;
$this->routeMatch = $route_match;
}
/**
* {@inheritdoc}
*/
public static function trustedCallbacks() {
return ['localTasksTrayLazyBuilder'];
}
/**
* Lazy builder callback for the admin_toolbar_local_tasks tray items.
*
* @return array
* A renderable array as expected by the renderer service.
*/
public function localTasksTrayLazyBuilder() {
// Get primary local task links and inject them into new
// admin_toolbar_local_tasks toolbar tray.
$links = $this->localTaskManager->getLocalTasks($this->routeMatch->getRouteName(), 0);
if (!empty($links['tabs'])) {
$build = [
'#theme' => 'links',
'#links' => [],
'#attributes' => [
'class' => ['toolbar-menu'],
],
];
Element::children($links['tabs'], TRUE);
$routes = Element::getVisibleChildren($links['tabs']);
foreach ($routes as $route) {
$build['#links'][$route] = $links['tabs'][$route]['#link'];
}
$links['cacheability']->applyTo($build);
return $build;
}
return [];
}
/**
* Gets a list of content entities.
*
* @return array
* An array of metadata about content entities.
*/
public function getBundleableEntitiesList() {
$entity_types = $this->entityTypeManager->getDefinitions();
$content_entities = [];
foreach ($entity_types as $key => $entity_type) {
if ($entity_type->getBundleEntityType() && ($entity_type->get('field_ui_base_route') != '')) {
$content_entities[$key] = [
'content_entity' => $key,
'content_entity_bundle' => $entity_type->getBundleEntityType(),
];
}
}
return $content_entities;
}
/**
* Gets an array of entity types that should trigger a menu rebuild.
*
* @return array
* An array of entity machine names.
*/
public function getRebuildEntityTypes() {
$types = ['menu'];
$content_entities = $this->getBundleableEntitiesList();
$types = array_merge($types, array_column($content_entities, 'content_entity_bundle'));
return $types;
}
}
...@@ -6,19 +6,19 @@ use Drupal\Component\Datetime\TimeInterface; ...@@ -6,19 +6,19 @@ use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\CronInterface; use Drupal\Core\CronInterface;
use Drupal\Core\Menu\ContextualLinkManagerInterface; use Drupal\Core\Menu\ContextualLinkManager;
use Drupal\Core\Menu\LocalActionManagerInterface; use Drupal\Core\Menu\LocalActionManager;
use Drupal\Core\Menu\LocalTaskManagerInterface; use Drupal\Core\Menu\LocalTaskManager;
use Drupal\Core\Menu\MenuLinkManagerInterface; use Drupal\Core\Menu\MenuLinkManagerInterface;
use Drupal\Core\Plugin\CachedDiscoveryClearerInterface; use Drupal\Core\Plugin\CachedDiscoveryClearerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\RequestStack;
use Drupal\Core\PhpStorage\PhpStorageFactory;
use Drupal\Core\Template\TwigEnvironment; use Drupal\Core\Template\TwigEnvironment;
use Drupal\Core\Theme\Registry;
/** /**
* Class ToolbarController. * Controller for AdminToolbar Tools.
* *
* @package Drupal\admin_toolbar_tools\Controller * @package Drupal\admin_toolbar_tools\Controller
*/ */
...@@ -41,21 +41,21 @@ class ToolbarController extends ControllerBase { ...@@ -41,21 +41,21 @@ class ToolbarController extends ControllerBase {
/** /**
* A context link manager instance. * A context link manager instance.
* *
* @var \Drupal\Core\Menu\ContextualLinkManagerInterface * @var \Drupal\Core\Menu\ContextualLinkManager
*/ */
protected $contextualLinkManager; protected $contextualLinkManager;
/** /**
* A local task manager instance. * A local task manager instance.
* *
* @var \Drupal\Core\Menu\LocalTaskManagerInterface * @var \Drupal\Core\Menu\LocalTaskManager
*/ */
protected $localTaskLinkManager; protected $localTaskLinkManager;
/** /**
* A local action manager instance. * A local action manager instance.
* *
* @var \Drupal\Core\Menu\LocalActionManagerInterface * @var \Drupal\Core\Menu\LocalActionManager
*/ */
protected $localActionLinkManager; protected $localActionLinkManager;
...@@ -101,6 +101,13 @@ class ToolbarController extends ControllerBase { ...@@ -101,6 +101,13 @@ class ToolbarController extends ControllerBase {
*/ */
protected $twig; protected $twig;
/**
* The search theme.registry service.
*
* @var \Drupal\Core\Theme\Registry
*/
protected $themeRegistry;
/** /**
* Constructs a ToolbarController object. * Constructs a ToolbarController object.
* *
...@@ -108,11 +115,11 @@ class ToolbarController extends ControllerBase { ...@@ -108,11 +115,11 @@ class ToolbarController extends ControllerBase {
* A cron instance. * A cron instance.
* @param \Drupal\Core\Menu\MenuLinkManagerInterface $menuLinkManager * @param \Drupal\Core\Menu\MenuLinkManagerInterface $menuLinkManager
* A menu link manager instance. * A menu link manager instance.
* @param \Drupal\Core\Menu\ContextualLinkManagerInterface $contextualLinkManager * @param \Drupal\Core\Menu\ContextualLinkManager $contextualLinkManager
* A context link manager instance. * A context link manager instance.
* @param \Drupal\Core\Menu\LocalTaskManagerInterface $localTaskLinkManager * @param \Drupal\Core\Menu\LocalTaskManager $localTaskLinkManager
* A local task manager instance. * A local task manager instance.
* @param \Drupal\Core\Menu\LocalActionManagerInterface $localActionLinkManager * @param \Drupal\Core\Menu\LocalActionManager $localActionLinkManager
* A local action manager instance. * A local action manager instance.
* @param \Drupal\Core\Cache\CacheBackendInterface $cacheRender * @param \Drupal\Core\Cache\CacheBackendInterface $cacheRender
* A cache backend interface instance. * A cache backend interface instance.
...@@ -126,18 +133,23 @@ class ToolbarController extends ControllerBase { ...@@ -126,18 +133,23 @@ class ToolbarController extends ControllerBase {
* A cache menu instance. * A cache menu instance.
* @param \Drupal\Core\Template\TwigEnvironment $twig * @param \Drupal\Core\Template\TwigEnvironment $twig
* A TwigEnvironment instance. * A TwigEnvironment instance.
* @param \Drupal\Core\Theme\Registry $theme_registry
* The theme.registry service.
*/ */
public function __construct(CronInterface $cron, public function __construct(
MenuLinkManagerInterface $menuLinkManager, CronInterface $cron,
ContextualLinkManagerInterface $contextualLinkManager, MenuLinkManagerInterface $menuLinkManager,
LocalTaskManagerInterface $localTaskLinkManager, ContextualLinkManager $contextualLinkManager,
LocalActionManagerInterface $localActionLinkManager, LocalTaskManager $localTaskLinkManager,
CacheBackendInterface $cacheRender, LocalActionManager $localActionLinkManager,
TimeInterface $time, CacheBackendInterface $cacheRender,
RequestStack $request_stack, TimeInterface $time,
CachedDiscoveryClearerInterface $plugin_cache_clearer, RequestStack $request_stack,
CacheBackendInterface $cache_menu, CachedDiscoveryClearerInterface $plugin_cache_clearer,
TwigEnvironment $twig) { CacheBackendInterface $cache_menu,
TwigEnvironment $twig,
Registry $theme_registry
) {
$this->cron = $cron; $this->cron = $cron;
$this->menuLinkManager = $menuLinkManager; $this->menuLinkManager = $menuLinkManager;
$this->contextualLinkManager = $contextualLinkManager; $this->contextualLinkManager = $contextualLinkManager;
...@@ -149,6 +161,7 @@ class ToolbarController extends ControllerBase { ...@@ -149,6 +161,7 @@ class ToolbarController extends ControllerBase {
$this->pluginCacheClearer = $plugin_cache_clearer; $this->pluginCacheClearer = $plugin_cache_clearer;
$this->cacheMenu = $cache_menu; $this->cacheMenu = $cache_menu;
$this->twig = $twig; $this->twig = $twig;
$this->themeRegistry = $theme_registry;
} }
/** /**
...@@ -166,7 +179,8 @@ class ToolbarController extends ControllerBase { ...@@ -166,7 +179,8 @@ class ToolbarController extends ControllerBase {
$container->get('request_stack'), $container->get('request_stack'),
$container->get('plugin.cache_clearer'), $container->get('plugin.cache_clearer'),
$container->get('cache.menu'), $container->get('cache.menu'),
$container->get('twig') $container->get('twig'),
$container->get('theme.registry')
); );
} }
...@@ -179,7 +193,7 @@ class ToolbarController extends ControllerBase { ...@@ -179,7 +193,7 @@ class ToolbarController extends ControllerBase {
return $request->server->get('HTTP_REFERER'); return $request->server->get('HTTP_REFERER');
} }
else { else {
return '/'; return base_path();
} }
} }
...@@ -269,4 +283,13 @@ class ToolbarController extends ControllerBase { ...@@ -269,4 +283,13 @@ class ToolbarController extends ControllerBase {
return new RedirectResponse($this->reloadPage()); return new RedirectResponse($this->reloadPage());
} }
/**
* Rebuild the theme registry.
*/
public function themeRebuild() {
$this->themeRegistry->reset();
$this->messenger()->addMessage($this->t('Theme registry rebuilded.'));
return new RedirectResponse($this->reloadPage());
}
} }
<?php
namespace Drupal\admin_toolbar_tools\Form;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Menu\MenuLinkManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Settings form for AdminToobar Tools.
*
* @package Drupal\admin_toolbar_tools\Form
*/
class AdminToolbarToolsSettingsForm extends ConfigFormBase {
/**
* The cache menu instance.
*
* @var \Drupal\Core\Cache\CacheBackendInterface
*/
protected $cacheMenu;
/**
* The menu link manager instance.
*
* @var \Drupal\Core\Menu\MenuLinkManagerInterface
*/
protected $menuLinkManager;
/**
* AdminToolbarToolsSettingsForm constructor.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
* The factory for configuration objects.
* @param \Drupal\Core\Menu\MenuLinkManagerInterface $menuLinkManager
* A menu link manager instance.
* @param \Drupal\Core\Cache\CacheBackendInterface $cacheMenu
* A cache menu instance.
*/
public function __construct(ConfigFactoryInterface $configFactory, MenuLinkManagerInterface $menuLinkManager, CacheBackendInterface $cacheMenu) {
parent::__construct($configFactory);
$this->cacheMenu = $cacheMenu;
$this->menuLinkManager = $menuLinkManager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('config.factory'),
$container->get('plugin.manager.menu.link'),
$container->get('cache.menu')
);
}
/**
* {@inheritdoc}
*/
protected function getEditableConfigNames() {
return [
'admin_toolbar_tools.settings',
];
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'admin_toolbar_tools_settings';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$config = $this->config('admin_toolbar_tools.settings');
$form['max_bundle_number'] = [
'#type' => 'number',
'#title' => $this->t('Maximum number of bundle sub-menus to display'),
'#description' => $this->t('Loading a large number of items can cause performance issues.'),
'#default_value' => $config->get('max_bundle_number'),
];
$form['hoverintent_functionality'] = [
'#type' => 'checkbox',
'#title' => $this->t('Enable/Disable the hoverintent functionality'),
'#description' => $this->t('Check it if you want to enable the hoverintent feature.'),
'#default_value' => $config->get('hoverintent_functionality'),
];
$form['show_local_tasks'] = [
'#type' => 'checkbox',
'#title' => $this->t('Enable/Disable local tasks display'),
'#description' => $this->t('Local tasks such as node edit and delete.'),
'#default_value' => $config->get('show_local_tasks'),
];
return parent::buildForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$this->config('admin_toolbar_tools.settings')
->set('max_bundle_number', $form_state->getValue('max_bundle_number'))
->set('hoverintent_functionality', $form_state->getValue('hoverintent_functionality'))
->set('show_local_tasks', $form_state->getValue('show_local_tasks'))
->save();
parent::submitForm($form, $form_state);
$this->cacheMenu->invalidateAll();
$this->menuLinkManager->rebuild();
}
}
<?php
namespace Drupal\admin_toolbar_tools\Plugin\Menu;
use Drupal\Core\Entity\EntityDescriptionInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Menu\MenuLinkDefault;
use Drupal\Core\Menu\StaticMenuLinkOverridesInterface;
use Drupal\node\NodeTypeInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides a menu link plugins for configuration entities.
*/
class MenuLinkEntity extends MenuLinkDefault {
/**
* The entity represented in the menu link.
*
* @var \Drupal\Core\Entity\EntityInterface
*/
protected $entity;
/**
* Constructs a new MenuLinkEntity.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Menu\StaticMenuLinkOverridesInterface $static_override
* The static override storage.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, StaticMenuLinkOverridesInterface $static_override, EntityTypeManagerInterface $entity_type_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $static_override);
$this->entity = $entity_type_manager->getStorage($this->pluginDefinition['metadata']['entity_type'])->load($this->pluginDefinition['metadata']['entity_id']);
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('menu_link.static.overrides'),
$container->get('entity_type.manager')
);
}
/**
* {@inheritdoc}
*/
public function getTitle() {
if ($this->entity) {
return (string) $this->entity->label();
}
return $this->pluginDefinition['title'] ?: $this->t('Missing');
}
/**
* {@inheritdoc}
*/
public function getDescription() {
// @todo Remove node_type special handling.
if ($this->entity instanceof EntityDescriptionInterface || $this->entity instanceof NodeTypeInterface) {
return $this->entity->getDescription();
}
return parent::getDescription();
}
/**
* {@inheritdoc}
*/
public function getCacheContexts() {
if ($this->entity) {
return $this->entity->getCacheContexts();
}
return parent::getCacheContexts();
}
/**
* {@inheritdoc}
*/
public function getCacheTags() {
if ($this->entity) {
return $this->entity->getCacheTags();
}
return parent::getCacheTags();
}
/**
* {@inheritdoc}
*/
public function getCacheMaxAge() {
if ($this->entity) {
return $this->entity->getCacheMaxAge();
}
return parent::getCacheMaxAge();
}
}
...@@ -22,6 +22,11 @@ class AdminToolbarToolsAlterTest extends BrowserTestBase { ...@@ -22,6 +22,11 @@ class AdminToolbarToolsAlterTest extends BrowserTestBase {
'admin_toolbar_tools', 'admin_toolbar_tools',
]; ];
/**
* {@inheritdoc}
*/
protected $defaultTheme = 'stark';
/** /**
* A test user with permission to access the administrative toolbar. * A test user with permission to access the administrative toolbar.
* *
...@@ -32,7 +37,7 @@ class AdminToolbarToolsAlterTest extends BrowserTestBase { ...@@ -32,7 +37,7 @@ class AdminToolbarToolsAlterTest extends BrowserTestBase {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
protected function setUp() { protected function setUp(): void {
parent::setUp(); parent::setUp();
// Create and log in an administrative user. // Create and log in an administrative user.
$this->adminUser = $this->drupalCreateUser([ $this->adminUser = $this->drupalCreateUser([
......
...@@ -2,9 +2,12 @@ ...@@ -2,9 +2,12 @@
"name": "drupal/admin_toolbar", "name": "drupal/admin_toolbar",
"description": "Provides a drop-down menu interface to the core Drupal Toolbar.", "description": "Provides a drop-down menu interface to the core Drupal Toolbar.",
"type": "drupal-module", "type": "drupal-module",
"keywords": ["Drupal", "Toolbar"], "keywords": [
"Drupal",
"Toolbar"
],
"homepage": "http://drupal.org/project/admin_toolbar", "homepage": "http://drupal.org/project/admin_toolbar",
"license": "GPL-2.0+", "license": "GPL-2.0-or-later",
"authors": [ "authors": [
{ {
"name": "Wilfrid Roze (eme)", "name": "Wilfrid Roze (eme)",
...@@ -26,10 +29,13 @@ ...@@ -26,10 +29,13 @@
"name": "Mohamed Anis Taktak (matio89)", "name": "Mohamed Anis Taktak (matio89)",
"homepage": "https://www.drupal.org/u/matio89", "homepage": "https://www.drupal.org/u/matio89",
"role": "Maintainer" "role": "Maintainer"
} }
], ],
"support": { "support": {
"issues": "https://www.drupal.org/project/issues/admin_toolbar", "issues": "https://www.drupal.org/project/issues/admin_toolbar",
"source": "http://cgit.drupalcode.org/admin_toolbar" "source": "https://git.drupalcode.org/project/admin_toolbar"
},
"require": {
"drupal/core": "^8.8.0 || ^9.0"
} }
} }
admin_toolbar.settings:
type: config_object
label: 'Admin Toolbar settings'
mapping:
menu_depth:
type: integer
label: 'Depth of displayed menu'
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
.toolbar-tray-horizontal .toolbar-menu:not(:first-child) li.menu-item--expanded > a:focus { .toolbar-tray-horizontal .toolbar-menu:not(:first-child) li.menu-item--expanded > a:focus {
background-position: center right; background-position: center right;
background-image: url('../misc/icons/0074bd/chevron-right.svg'); background-image: url(../misc/icons/0074bd/chevron-right.svg);
background-repeat: no-repeat; background-repeat: no-repeat;
} }
...@@ -24,18 +24,18 @@ ...@@ -24,18 +24,18 @@
.toolbar-tray-horizontal ul li li.menu-item { .toolbar-tray-horizontal ul li li.menu-item {
border-top: none transparent; border-top: none transparent;
border-right: 1px solid #dddddd; border-right: 1px solid #ddd;
border-bottom: 1px solid #dddddd; border-bottom: 1px solid #ddd;
border-left: 1px solid #dddddd; border-left: 1px solid #ddd;
} }
.toolbar .toolbar-tray-horizontal .menu-item:last-child { .toolbar .toolbar-tray-horizontal .menu-item:last-child {
border-left: 1px solid #dddddd; border-left: 1px solid #ddd;
border-right: 1px solid #dddddd; border-right: 1px solid #ddd;
} }
.toolbar .toolbar-tray-horizontal ul ul li.menu-item:first-child { .toolbar .toolbar-tray-horizontal ul ul li.menu-item:first-child {
border-top: 1px solid #dddddd; border-top: 1px solid #ddd;
} }
.toolbar-tray-horizontal li.menu-item--expanded.hover-intent ul ul, .toolbar-tray-horizontal li.menu-item--expanded.hover-intent ul ul,
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
.toolbar-tray-horizontal ul li.menu-item--expanded ul li.menu-item--expanded { .toolbar-tray-horizontal ul li.menu-item--expanded ul li.menu-item--expanded {
background-position: center right; background-position: center right;
background-image: url('../misc/icons/0074bd/chevron-right.svg'); background-image: url(../misc/icons/0074bd/chevron-right.svg);
background-repeat: no-repeat; background-repeat: no-repeat;
} }
...@@ -105,10 +105,10 @@ ...@@ -105,10 +105,10 @@
} }
.toolbar-menu .menu-item > span { .toolbar-menu .menu-item > span {
padding: 1em 1.3333em; padding: 1em 1.3333em;
display: block; display: block;
color: #434343; color: #434343;
cursor: pointer; cursor: pointer;
} }
[dir="rtl"] .toolbar-tray-horizontal .menu-item:hover { [dir="rtl"] .toolbar-tray-horizontal .menu-item:hover {
...@@ -121,7 +121,7 @@ ...@@ -121,7 +121,7 @@
[dir="rtl"] .toolbar-tray-horizontal .toolbar-menu:not(:first-child) li.menu-item--expanded > a:focus { [dir="rtl"] .toolbar-tray-horizontal .toolbar-menu:not(:first-child) li.menu-item--expanded > a:focus {
background-position: center right; background-position: center right;
background-image: url('../misc/icons/0074bd/chevron-right.svg'); background-image: url(../misc/icons/0074bd/chevron-right.svg);
background-repeat: no-repeat; background-repeat: no-repeat;
} }
...@@ -137,18 +137,18 @@ ...@@ -137,18 +137,18 @@
[dir="rtl"] .toolbar-tray-horizontal ul li li.menu-item { [dir="rtl"] .toolbar-tray-horizontal ul li li.menu-item {
border-top: none transparent; border-top: none transparent;
border-right: 1px solid #dddddd; border-right: 1px solid #ddd;
border-bottom: 1px solid #dddddd; border-bottom: 1px solid #ddd;
border-left: 1px solid #dddddd; border-left: 1px solid #ddd;
} }
[dir="rtl"] .toolbar .toolbar-tray-horizontal .menu-item:last-child { [dir="rtl"] .toolbar .toolbar-tray-horizontal .menu-item:last-child {
border-left: 1px solid #dddddd; border-left: 1px solid #ddd;
border-right: 1px solid #dddddd; border-right: 1px solid #ddd;
} }
[dir="rtl"] .toolbar .toolbar-tray-horizontal ul ul li.menu-item:first-child { [dir="rtl"] .toolbar .toolbar-tray-horizontal ul ul li.menu-item:first-child {
border-top: 1px solid #dddddd; border-top: 1px solid #ddd;
} }
[dir="rtl"] .toolbar-tray-horizontal li.menu-item--expanded.hover-intent ul ul, [dir="rtl"] .toolbar-tray-horizontal li.menu-item--expanded.hover-intent ul ul,
...@@ -188,7 +188,7 @@ ...@@ -188,7 +188,7 @@
[dir="rtl"] .toolbar-tray-horizontal ul li.menu-item--expanded ul li.menu-item--expanded { [dir="rtl"] .toolbar-tray-horizontal ul li.menu-item--expanded ul li.menu-item--expanded {
background-position: center left; background-position: center left;
background-image: url('../misc/icons/0074bd/chevron-left.svg'); background-image: url(../misc/icons/0074bd/chevron-left.svg);
background-repeat: no-repeat; background-repeat: no-repeat;
} }
......
...@@ -3,17 +3,17 @@ ...@@ -3,17 +3,17 @@
} }
#admin-toolbar-search-tab .toolbar-item:before { #admin-toolbar-search-tab .toolbar-item:before {
background-image: url('../misc/icons/bebebe/loupe.svg'); background-image: url(../misc/icons/bebebe/loupe.svg);
} }
#admin-toolbar-search-tab .toolbar-item:active:before, #admin-toolbar-search-tab .toolbar-item:active:before,
#admin-toolbar-search-tab .toolbar-item.is-active:before { #admin-toolbar-search-tab .toolbar-item.is-active:before {
background-image: url('../misc/icons/ffffff/loupe.svg'); background-image: url(../misc/icons/ffffff/loupe.svg);
} }
#toolbar-item-administration-search-tray label { #toolbar-item-administration-search-tray label {
display: inline-block; display: inline-block;
color: #000000; color: #000;
margin-right: .5em; margin-right: .5em;
font-weight: bold; font-weight: bold;
} }
...@@ -29,5 +29,5 @@ ...@@ -29,5 +29,5 @@
} }
.ui-autocomplete .ui-menu-item span.admin-toolbar-search-url { .ui-autocomplete .ui-menu-item span.admin-toolbar-search-url {
color: rgba(0, 0, 0, 0.50); display: none;
} }
(function ($) {
$(document).ready(function () {
$('.toolbar-tray.toolbar-tray-horizontal .menu-item.menu-item--expanded').hover(function () {
// At the current depth, we should delete all "hover-intent" classes.
// Other wise we get unwanted behaviour where menu items are expanded while already in hovering other ones.
$(this).parent().find('li').removeClass('hover-intent');
$(this).addClass('hover-intent');
},
function () {
$(this).removeClass('hover-intent');
});
});
})(jQuery);
(function ($) {
$(document).ready(function () {
$('.toolbar-tray-horizontal li.menu-item--expanded, .toolbar-tray-horizontal ul li.menu-item--expanded .menu-item').hoverIntent({
over: function () {
// At the current depth, we should delete all "hover-intent" classes.
// Other wise we get unwanted behaviour where menu items are expanded while already in hovering other ones.
$(this).parent().find('li').removeClass('hover-intent');
$(this).addClass('hover-intent');
},
out: function () {
$(this).removeClass('hover-intent');
},
timeout: 250
});
});
})(jQuery);
...@@ -4,19 +4,6 @@ ...@@ -4,19 +4,6 @@
$('a.toolbar-icon', context).removeAttr('title'); $('a.toolbar-icon', context).removeAttr('title');
$('.toolbar-tray li.menu-item--expanded, .toolbar-tray ul li.menu-item--expanded .menu-item', context).hoverIntent({
over: function () {
// At the current depth, we should delete all "hover-intent" classes.
// Other wise we get unwanted behaviour where menu items are expanded while already in hovering other ones.
$(this).parent().find('li').removeClass('hover-intent');
$(this).addClass('hover-intent');
},
out: function () {
$(this).removeClass('hover-intent');
},
timeout: 250
});
// Make the toolbar menu navigable with keyboard. // Make the toolbar menu navigable with keyboard.
$('ul.toolbar-menu li.menu-item--expanded a', context).on('focusin', function () { $('ul.toolbar-menu li.menu-item--expanded a', context).on('focusin', function () {
$('li.menu-item--expanded', context).removeClass('hover-intent'); $('li.menu-item--expanded', context).removeClass('hover-intent');
...@@ -48,6 +35,13 @@ ...@@ -48,6 +35,13 @@
} }
}); });
// Always hide the dropdown menu on mobile.
if (window.matchMedia("(max-width: 767px)").matches && $('body').hasClass('toolbar-tray-open')) {
$('body').removeClass('toolbar-tray-open');
$('#toolbar-item-administration').removeClass('is-active');
$('#toolbar-item-administration-tray').removeClass('is-active');
};
} }
}; };
})(jQuery, Drupal); })(jQuery, Drupal);
(function ($, Drupal) {
Drupal.behaviors.adminToolbarSearch = {
attach: function (context) {
if (context != document) {
return;
}
var getUrl = window.location;
var baseUrl = getUrl.protocol + "//" + getUrl.host + "/";
var $self = this;
this.links = [];
$('a[data-drupal-link-system-path]').each(function() {
if (this.href != baseUrl) {
var label = $self.getItemLabel(this);
$self.links.push({
'value': $(this).attr('href'),
'label': label + ' ' + $(this).attr('href'),
'labelRaw': label
});
}
});
$( "#admin-toolbar-search-input").autocomplete({
minLength: 2,
source: function(request, response) {
var data = $self.handleAutocomplete(request.term);
response(data);
},
open: function(){
var zIndex = $('#toolbar-item-administration-search-tray').css("z-index")+1;
$(this).autocomplete('widget').css('z-index', zIndex);
return false;
},
select: function( event, ui ) {
if (ui.item.value) {
location.href = ui.item.value;
return false;
}
}
}).data("ui-autocomplete")._renderItem = (function(ul, item) {
return $("<li>")
.append('<div>' + item.labelRaw + ' <span class="admin-toolbar-search-url">' + item.value + '</span></div>')
.appendTo(ul);
});
// Focus on search field when tab is clicked, or enter is pressed.
$(context).find('#toolbar-item-administration-search').once('admin_toolbar_search').each(function () {
if ($('#toolbar-item-administration-search-tray:visible').length) {
$('#admin-toolbar-search-input').focus();
}
$(this).on('click', function() {
$self.focusOnSearchElement();
});
});
},
focusOnSearchElement: function() {
var waitforVisible = function() {
if ($('#toolbar-item-administration-search-tray:visible').length) {
$('#admin-toolbar-search-input').focus();
} else {
setTimeout(function() {
waitforVisible();
}, 1);
}
};
waitforVisible();
},
getItemLabel: function(item) {
var breadcrumbs = [];
$(item).parents().each(function() {
if ($(this).hasClass('menu-item')) {
var $link = $(this).find('a:first');
if ($link.length && !$link.hasClass('admin-toolbar-search-ignore')) {
breadcrumbs.unshift($link.text());
}
}
});
label = breadcrumbs.join(' > ');
return label;
},
handleAutocomplete: function(term) {
var $self = this;
var keywords = term.split(" "); // split search terms into list.
var suggestions = [];
$self.links.forEach(function(element) {
var label = element.label.toLowerCase();
// Add exact matches.
if (label.indexOf(term.toLowerCase()) >= 0) {
suggestions.push(element);
}
else {
// Add suggestions where it matches all search terms.
var matchCount = 0;
keywords.forEach(function(keyword) {
if (label.indexOf(keyword.toLowerCase()) >= 0) {
matchCount++;
}
});
if (matchCount == keywords.length) {
suggestions.push(element);
}
}
});
return suggestions;
}
};
})(jQuery, Drupal);
This diff is collapsed.
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment