lock = $lock; $this->menuLinkManager = $menu_link_manager; $this->connection = $connection; $this->replicaKillSwitch = $replica_kill_switch; if ($this->logger === NULL) { @trigger_error('Calling ' . __METHOD__ . '() without the $logger argument is deprecated in drupal:10.1.0 and it will be required in drupal:11.0.0. See https://www.drupal.org/node/2932520', E_USER_DEPRECATED); $this->logger = \Drupal::service('logger.channel.menu'); } } /** * Rebuilds the menu links and deletes the local_task cache tag. * * @param \Drupal\Component\EventDispatcher\Event $event * The event object. */ public function onRouterRebuild($event) { $this->menuLinksRebuild(); Cache::invalidateTags(['local_task']); } /** * Perform menu-specific rebuilding. */ protected function menuLinksRebuild() { if ($this->lock->acquire(__FUNCTION__)) { try { $transaction = $this->connection->startTransaction(); // Ensure the menu links are up to date. $this->menuLinkManager->rebuild(); // Ignore any database replicas temporarily. $this->replicaKillSwitch->trigger(); } catch (\Exception $e) { if (isset($transaction)) { $transaction->rollBack(); } Error::logException($this->logger, $e); } $this->lock->release(__FUNCTION__); } else { // Wait for another request that is already doing this work. // We choose to block here since otherwise the router item may not // be available during routing resulting in a 404. $this->lock->wait(__FUNCTION__); } } /** * {@inheritdoc} */ public static function getSubscribedEvents(): array { // Run after CachedRouteRebuildSubscriber. $events[RoutingEvents::FINISHED][] = ['onRouterRebuild', 100]; return $events; } }