diff --git a/core/lib/Drupal/Core/Breadcrumb/BreadcrumbBuilderInterface.php b/core/lib/Drupal/Core/Breadcrumb/BreadcrumbBuilderInterface.php index 7aae91a..c19100e 100644 --- a/core/lib/Drupal/Core/Breadcrumb/BreadcrumbBuilderInterface.php +++ b/core/lib/Drupal/Core/Breadcrumb/BreadcrumbBuilderInterface.php @@ -19,6 +19,11 @@ * * @param \Symfony\Component\HttpFoundation\Request $request * The HttpRequest object representing the current request. + * + * @return array|FALSE|NULL + * A render array for the breacrumbs, or + * FALSE, to suppress breadcrumbs on this page, or + * NULL, to let other builders decide. */ public function build(Request $request); } diff --git a/core/lib/Drupal/Core/Breadcrumb/BreadcrumbManager.php b/core/lib/Drupal/Core/Breadcrumb/BreadcrumbManager.php index d6d2d0f..d8b1dbe 100644 --- a/core/lib/Drupal/Core/Breadcrumb/BreadcrumbManager.php +++ b/core/lib/Drupal/Core/Breadcrumb/BreadcrumbManager.php @@ -25,6 +25,15 @@ class BreadcrumbManager implements BreadcrumbBuilderInterface { */ protected $builders = array(); + /** + * Holds the array of breadcrumb builders sorted by priority. + * + * @var array|NULL + * An array of breadcrumb builders sorted by priorities, or + * NULL, if the array needs to be re-calculated. + */ + protected $sortedBuilders; + /* * Add another breadcrumb builder. * @@ -45,16 +54,41 @@ public function addBuilder(BreadcrumbBuilderInterface $builder, $priority) { * * @param \Symfony\Component\HttpFoundation\Request $request * The HttpRequest object representing the current request. + * + * @return array|FALSE|NULL + * A render array for the breacrumb, or + * FALSE, if one of the builders explicitly wants no breadcrumb, or + * NULL, if no plugin found a breadcrumb. + * In the general use case, FALSE and NULL will have the same effect. */ public function build(Request $request) { // Call the build method of all breadcrumb builders. - foreach ($this->builders as $priority => $builders) { - foreach ($builders as $builder) { - $breadcrumb = $builder->build($request); - if (isset($breadcrumb) && is_array($breadcrumb)) { - return $breadcrumb; - } + foreach ($this->getSortedBuilders() as $builder) { + $breadcrumb = $builder->build($request); + if (isset($breadcrumb)) { + // $breadcrumb may be either a render array, + // or FALSE, to suppress the breadcrumbs on this page. + return $breadcrumb; + } + } + } + + /** + * Returns the sorted array of breadcrumb builders. + * + * @return array + * An array of breadcrumb builder objects. + */ + protected function getSortedBuilders() { + if (!isset($this->sortedBuilders)) { + // Sort the builders according to priority. + krsort($this->builders); + // Merge the nested $this->builders array into $this->sortedBuilders. + $this->sortedBuilders = array(); + foreach ($this->builders as $builders) { + $this->sortedBuilders = array_merge($this->sortedBuilders, $builders); } } + return $this->sortedBuilders; } } diff --git a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkBreadcrumbBuilder.php b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkBreadcrumbBuilder.php index 992b6da..5002b64 100644 --- a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkBreadcrumbBuilder.php +++ b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkBreadcrumbBuilder.php @@ -20,10 +20,25 @@ class MenuLinkBreadcrumbBuilder implements BreadcrumbBuilderInterface { * * @param \Symfony\Component\HttpFoundation\Request $request * The HttpRequest object representing the current request. + * + * @return array|FALSE|NULL + * A render array for the breacrumbs, or + * FALSE, to suppress breadcrumbs on this page, or + * NULL, to let other builders decide. */ public function build(Request $request) { - // TODO: Move the implementation out of menu.inc, into this method. + // TODO: Rewrite the implementation. $breadcrumb = menu_get_active_breadcrumb(); - return $breadcrumb; + if (is_array($breadcrumb)) { + // $breadcrumb is expected to be an array of rendered breadcrumb links. + return array( + '#theme' => 'breadcrumb', + '#breadcrumb' => $breadcrumb, + ); + } + else { + // $breadcrumb is expected to be FALSE or NULL. + return $breadcrumb; + } } } diff --git a/core/modules/menu_link/menu_link.services.yml b/core/modules/menu_link/menu_link.services.yml index 2915123..a428476 100644 --- a/core/modules/menu_link/menu_link.services.yml +++ b/core/modules/menu_link/menu_link.services.yml @@ -1,6 +1,5 @@ services: menu_link.breadcrumb: class: Drupal\menu_link\MenuLinkBreadcrumbBuilder - arguments: ['@request'] tags: - - { name: breadcrumb_builder, priority: 1000 } + - { name: breadcrumb_builder, priority: 0 } diff --git a/core/modules/system/lib/Drupal/system/LegacyBreadcrumbBuilder.php b/core/modules/system/lib/Drupal/system/LegacyBreadcrumbBuilder.php new file mode 100644 index 0000000..87ee473 --- /dev/null +++ b/core/modules/system/lib/Drupal/system/LegacyBreadcrumbBuilder.php @@ -0,0 +1,46 @@ + 'breadcrumb', + '#breadcrumb' => $breadcrumb, + ); + } + else { + // $breadcrumb is expected to be FALSE or NULL. + return $breadcrumb; + } + } +} diff --git a/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemBreadcrumbBlock.php b/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemBreadcrumbBlock.php index 813005b..1420199 100644 --- a/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemBreadcrumbBlock.php +++ b/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemBreadcrumbBlock.php @@ -7,6 +7,7 @@ namespace Drupal\system\Plugin\block\block; +use Drupal; use Drupal\block\BlockBase; use Drupal\Component\Annotation\Plugin; use Drupal\Core\Annotation\Translation; @@ -24,16 +25,18 @@ class SystemBreadcrumbBlock extends BlockBase { /** * Implements \Drupal\block\BlockBase::build(). + * + * @return array|NULL + * A render array to display the breadcrumbs for the current page, or + * NULL, if no breadcrumb should be displayed. */ public function build() { - $builder = \Drupal::service('breadcrumb'); - $request = \Drupal::service('request'); + $builder = Drupal::service('breadcrumb'); + $request = Drupal::service('request'); $breadcrumb = $builder->build($request); - if (isset($breadcrumb) && is_array($breadcrumb)) { - return array( - '#theme' => 'breadcrumb', - '#breadcrumb' => $breadcrumb, - ); + if (!empty($breadcrumb)) { + // $breadcrumb is expected to be a render array. + return $breadcrumb; } } } diff --git a/core/modules/system/system.services.yml b/core/modules/system/system.services.yml index bf43cd4..7f36e61 100644 --- a/core/modules/system/system.services.yml +++ b/core/modules/system/system.services.yml @@ -6,3 +6,7 @@ services: plugin.manager.system.plugin_ui: class: Drupal\system\Plugin\Type\PluginUIManager arguments: ['%container.namespaces%'] + system.breadcrumb.legacy: + class: Drupal\system\LegacyBreadcrumbBuilder + tags: + - {name: breadcrumb_builder, priority: 500}