-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
HPC-9954: Prevent errors with mega menu block if menu link content entities disappear for some reason
- Loading branch information
Showing
5 changed files
with
191 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
50 changes: 50 additions & 0 deletions
50
html/modules/custom/ghi_menu/src/EventSubscriber/MenuRouterRebuildSubscriber.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
<?php | ||
|
||
namespace Drupal\ghi_menu\EventSubscriber; | ||
|
||
use Drupal\Core\Routing\RoutingEvents; | ||
use Drupal\ghi_menu\GhiMenuStorageHelper; | ||
use Symfony\Component\EventDispatcher\EventSubscriberInterface; | ||
|
||
/** | ||
* Rebuilds the default menu links and runs menu-specific code if necessary. | ||
*/ | ||
class MenuRouterRebuildSubscriber implements EventSubscriberInterface { | ||
|
||
/** | ||
* The menu storage helper service. | ||
* | ||
* @var \Drupal\ghi_menu\GhiMenuStorageHelper | ||
*/ | ||
protected $menuStorageHelper; | ||
|
||
/** | ||
* Constructs the MenuRouterRebuildSubscriber object. | ||
* | ||
* @param \Drupal\ghi_menu\GhiMenuStorageHelper $menu_storage_helper | ||
* The menu storage helper service. | ||
*/ | ||
public function __construct(GhiMenuStorageHelper $menu_storage_helper) { | ||
$this->menuStorageHelper = $menu_storage_helper; | ||
} | ||
|
||
/** | ||
* Cleanup the menu tree storage. | ||
* | ||
* @param \Drupal\Component\EventDispatcher\Event $event | ||
* The event object. | ||
*/ | ||
public function onRouterRebuild($event) { | ||
$this->menuStorageHelper->cleanupMenuStorage(); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public static function getSubscribedEvents(): array { | ||
// Run after CachedRouteRebuildSubscriber. | ||
$events[RoutingEvents::FINISHED][] = ['onRouterRebuild', 120]; | ||
return $events; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
<?php | ||
|
||
namespace Drupal\ghi_menu; | ||
|
||
use Drupal\Component\Plugin\Exception\PluginException; | ||
use Drupal\Core\Menu\MenuLinkTreeInterface; | ||
use Drupal\Core\Menu\MenuTreeParameters; | ||
use Drupal\Core\Menu\MenuTreeStorageInterface; | ||
use Drupal\menu_link_content\Plugin\Menu\MenuLinkContent; | ||
|
||
/** | ||
* Helper service for menu storage. | ||
*/ | ||
class GhiMenuStorageHelper { | ||
|
||
/** | ||
* The menu tree service. | ||
* | ||
* @var \Drupal\Core\Menu\MenuLinkTreeInterface | ||
*/ | ||
protected $menuTree; | ||
|
||
/** | ||
* The menu link tree storage. | ||
* | ||
* @var \Drupal\Core\Menu\MenuTreeStorageInterface | ||
*/ | ||
protected $treeStorage; | ||
|
||
/** | ||
* Constructs a \Drupal\Core\Menu\MenuLinkManager object. | ||
* | ||
* @param \Drupal\Core\Menu\MenuLinkTreeInterface $menu_tree | ||
* The menu tree service. | ||
* @param \Drupal\Core\Menu\MenuTreeStorageInterface $tree_storage | ||
* The menu link tree storage. | ||
*/ | ||
public function __construct(MenuLinkTreeInterface $menu_tree, MenuTreeStorageInterface $tree_storage) { | ||
$this->menuTree = $menu_tree; | ||
$this->treeStorage = $tree_storage; | ||
} | ||
|
||
/** | ||
* Cleanup the menu storage. | ||
* | ||
* While it seems like an edge case, we had situations where an item in the | ||
* menu storage referenced a menu content link that was already deleted, | ||
* resulting in a WSOD due to an unhandled PluginException. This logic here | ||
* removes those broken items in the menu tree storage. | ||
*/ | ||
public function cleanupMenuStorage() { | ||
$parameters = new MenuTreeParameters(); | ||
$menu_names = $this->treeStorage->getMenuNames(); | ||
foreach ($menu_names as $menu_name) { | ||
$menu_tree = $this->menuTree->load($menu_name, $parameters); | ||
$this->purgeBrokenItems($menu_tree); | ||
} | ||
} | ||
|
||
/** | ||
* Purge broken menu links from the tree. | ||
* | ||
* @param \Drupal\Core\Menu\MenuLinkTreeElement[] $menu_tree | ||
* The menu tree to filter. | ||
*/ | ||
private function purgeBrokenItems(array $menu_tree) { | ||
foreach ($menu_tree as $id => $item) { | ||
if (!empty($item->subtree)) { | ||
$this->purgeBrokenItems($item->subtree); | ||
} | ||
$link = $item->link; | ||
if (!$link instanceof MenuLinkContent) { | ||
continue; | ||
} | ||
try { | ||
// Just try to get the entity. If this throws an exception, this menu | ||
// item is broken. | ||
$link->getEntity(); | ||
} | ||
catch (PluginException $e) { | ||
$this->treeStorage->delete($id); | ||
} | ||
|
||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters