diff --git a/core/lib/Drupal/Core/Menu/MenuTreeParameters.php b/core/lib/Drupal/Core/Menu/MenuTreeParameters.php index 702dcb4978a..f7c61488018 100644 --- a/core/lib/Drupal/Core/Menu/MenuTreeParameters.php +++ b/core/lib/Drupal/Core/Menu/MenuTreeParameters.php @@ -12,7 +12,7 @@ namespace Drupal\Core\Menu; * a parent in the list will be included. * - Which menu links are omitted, depending on the minimum and maximum depth. */ -class MenuTreeParameters { +class MenuTreeParameters implements \Serializable { /** * A menu link plugin ID that should be used as the root. @@ -28,9 +28,6 @@ class MenuTreeParameters { /** * The minimum depth of menu links in the resulting tree relative to the root. * - * Defaults to 1, which is the default to build a whole tree for a menu - * (excluding the root). - * * @var int|null */ public $minDepth = NULL; @@ -211,4 +208,39 @@ class MenuTreeParameters { return $this; } + /** + * {@inheritdoc} + */ + public function serialize() { + // Enforce type consistency for all the internal properties of this object. + $this->root = (string) $this->root; + $this->minDepth = $this->minDepth !== NULL ? (int) $this->minDepth : NULL; + $this->maxDepth = $this->maxDepth !== NULL ? (int) $this->maxDepth : NULL; + $this->activeTrail = array_values(array_filter($this->activeTrail)); + + // Sort 'expanded' and 'conditions' to prevent duplicate cache items. + sort($this->expandedParents); + asort($this->conditions); + + return serialize([ + 'root' => $this->root, + 'minDepth' => $this->minDepth, + 'maxDepth' => $this->maxDepth, + 'expandedParents' => $this->expandedParents, + 'activeTrail' => $this->activeTrail, + 'conditions' => $this->conditions, + ]); + } + + /** + * {@inheritdoc} + */ + public function unserialize($serialized) { + foreach (unserialize($serialized) as $key => $value) { + $this->{$key} = $value; + } + + return $this; + } + } diff --git a/core/lib/Drupal/Core/Menu/MenuTreeStorage.php b/core/lib/Drupal/Core/Menu/MenuTreeStorage.php index f6578fe63e0..4e971f98d9c 100644 --- a/core/lib/Drupal/Core/Menu/MenuTreeStorage.php +++ b/core/lib/Drupal/Core/Menu/MenuTreeStorage.php @@ -845,10 +845,6 @@ class MenuTreeStorage implements MenuTreeStorageInterface { * {@inheritdoc} */ public function loadTreeData($menu_name, MenuTreeParameters $parameters) { - // Build the cache ID; sort 'expanded' and 'conditions' to prevent duplicate - // cache items. - sort($parameters->expandedParents); - asort($parameters->conditions); $tree_cid = "tree-data:$menu_name:" . serialize($parameters); $cache = $this->menuCacheBackend->get($tree_cid); if ($cache && isset($cache->data)) { diff --git a/core/modules/system/system.post_update.php b/core/modules/system/system.post_update.php index b4e2b860a77..980cbcb5e31 100644 --- a/core/modules/system/system.post_update.php +++ b/core/modules/system/system.post_update.php @@ -190,3 +190,12 @@ function system_post_update_add_expand_all_items_key_in_system_menu_block(&$sand return strpos($block->getPluginId(), 'system_menu_block:') === 0; }); } + +/** + * Clear the menu cache. + * + * @see https://www.drupal.org/project/drupal/issues/3044364 + */ +function system_post_update_clear_menu_cache() { + // Empty post-update hook. +} diff --git a/core/tests/Drupal/Tests/Core/Menu/MenuTreeParametersTest.php b/core/tests/Drupal/Tests/Core/Menu/MenuTreeParametersTest.php index ccaf3b9c72e..864ab5f4c23 100644 --- a/core/tests/Drupal/Tests/Core/Menu/MenuTreeParametersTest.php +++ b/core/tests/Drupal/Tests/Core/Menu/MenuTreeParametersTest.php @@ -142,4 +142,24 @@ class MenuTreeParametersTest extends UnitTestCase { $this->assertEquals(1, $parameters->minDepth); } + /** + * @covers ::serialize + * @covers ::unserialize + */ + public function testSerialize() { + $parameters = new MenuTreeParameters(); + $parameters->setRoot(1); + $parameters->setMinDepth('2'); + $parameters->setMaxDepth('9'); + $parameters->addExpandedParents(['', 'foo']); + $parameters->setActiveTrail(['', 'bar']); + + $after_serialize = unserialize(serialize($parameters)); + $this->assertSame('1', $after_serialize->root); + $this->assertSame(2, $after_serialize->minDepth); + $this->assertSame(9, $after_serialize->maxDepth); + $this->assertSame(['', 'foo'], $after_serialize->expandedParents); + $this->assertSame(['bar'], $after_serialize->activeTrail); + } + }