In Page Manager in Drupal 7, you can make your page into a menu item - similar functionality should exist for Drupal 8!

The biggest difference is that in Drupal 7, this was just changing some of the values returned from hook_menu() since page callbacks and menu items were conflated. In Drupal 8, they are completely decoupled, which means we can actually create multiple different types of menu entries for the same page!

So, in Drupal 8, we should support declaring multiple different menu items of different types (including action links, etc) at the storage level. For the purposes of this patch, it's OK if the UI only allows creating a single menu item - we can figure out the UI later, but we don't want to have to deal with changing the config schema later.

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

dsnopek created an issue. See original summary.

dsnopek’s picture

Status: Active » Needs work
FileSize
26.11 KB

Here's a patch that's extracted from the wizard patch:

#2550879: Use CTools Wizard API to add/edit Pages (and move plugin UI using PluginWizardInterface)

It creates UIs that are basically just like the UIs in D7, but it only stores one menu item per page, and it doesn't actually create the menus. So, it's really just the UIs. And since it's implemented as a wizard step, it depends on the wizard patch linked above.

andypost’s picture

now wizard landed, and patch outdated

DamienMcKenna’s picture

NWOM’s picture

This would be a great feature to have indeed. I thought I had a bug until I ran into this issue.

NWOM’s picture

Version: 8.x-1.x-dev » 8.x-4.x-dev
edurenye’s picture

FileSize
25.82 KB

Rebased for 4.x branch.

edurenye’s picture

Status: Needs work » Needs review
FileSize
19.05 KB
37.23 KB

The form was not working at all, I make it 'work' but it does not save the form, I get an error:
Warning: call_user_func_array() expects parameter 1 to be a valid callback, class 'normal_menu' not found in Drupal\Core\Form\FormValidator->executeValidateHandlers() (line 82 of core/lib/Drupal/Core/Form/FormValidator.php).
Where 'normal_menu' takes the value of the selected menu type.
If I comment in FormBuilder.php the line 262 where the form is retrieved from the cache $form = $this->getCache($input['form_build_id'], $form_state); then it works fine, but obviously I can't do that, so any help is appreciated.
Also the menu forms are a bit messy, the only that works fine is the normal menu I think, and is missing functionality like delete menu, enable/disable, and much more.

Status: Needs review » Needs work

The last submitted patch, 8: 2620036-8.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

edurenye’s picture

Rebased.
Use none instead of route when there is no menu.
Make menu deletable.

kevineinarsson’s picture

FileSize
38.75 KB
1.98 KB

I ran into caching issues when using access conditions on the routes. Attached patch fixes them pretty much like how the block module does it. Not super happy about two foreach()-loops, could probably be simplified.

kevineinarsson’s picture

FileSize
38.74 KB
38.42 KB
792 bytes

Patch no longer applied, so rerolled. Updated the patch to no loger log when catching the UnexepectedValueException in Url::getRouteName() as it's not an error per se and the log was getting spammed.

dwkitchen’s picture

Was testing and doesn't work on pages with a token in the URL.

E.g. url: /user/{user}/admin

Note

Having looked views doesn't support this either and says "Views cannot create normal menu items for paths with a % in them."

So this should say "Page Manager cannot create normal menu items for paths with a parameter in them."

Christopher Riley’s picture

Tried this patch against 9.2.2 and got the following:

he website encountered an unexpected error. Please try again later.

Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException: You have requested a non-existent service "user.shared_tempstore". in Drupal\Component\DependencyInjection\Container->get() (line 156 of core/lib/Drupal/Component/DependencyInjection/Container.php).

Drupal\page_manager_ui\Form\PageMenuForm::create(Object) (Line: 28)
Drupal\Core\DependencyInjection\ClassResolver->getInstanceFromDefinition('\Drupal\page_manager_ui\Form\PageMenuForm') (Line: 238)
Drupal\ctools\Wizard\FormWizardBase->getFormId() (Line: 205)
Drupal\Core\Form\FormBuilder->getFormId(Object, Object) (Line: 227)
Drupal\Core\Form\FormBuilder->buildForm(Object, Object) (Line: 57)
Drupal\ctools\Wizard\WizardFactory->getWizardForm(Object, Array, ) (Line: 78)
Drupal\ctools\Controller\WizardFormController->getContentResult(Object, Object)
call_user_func_array(Array, Array) (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 578)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 158)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 80)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 57)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 106)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 52)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 717)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)

Suggestions?

tim.plunkett’s picture

user.shared_tempstore was renamed to tempstore.shared in #2935617: Move User module's temp stores to core (January 2018!) and the BC layer was removed in D9

andypost’s picture

+++ b/src/Plugin/PageManagerMenu/NormalMenu.php
@@ -0,0 +1,102 @@
+    $menus = [];
+    foreach ($this->menuStorage->loadMultiple() as $id => $menu) {
+      $menus[$id] = $menu->label();

it could use views' approach, like #3021804: Remove optional dependency on menu_ui module in \Drupal\views\Plugin\views\wizard\WizardPluginBase

edurenye’s picture

This patch just fixes deprecated dependencies for D9, I still need to take a deeper look at the issue with views.

Christopher Riley’s picture

When I try to create a page with a menu or go back to add a menu item I get the following on Drupal 9.2.7:

The website encountered an unexpected error. Please try again later.
TypeError: Argument 2 passed to Drupal\page_manager_ui\Form\PageMenuForm::__construct() must be an instance of Drupal\user\SharedTempStoreFactory, instance of Drupal\Core\TempStore\SharedTempStoreFactory given, called in /home/sites/sitename/public_html/modules/contrib/page_manager/page_manager_ui/src/Form/PageMenuForm.php on line 31 in Drupal\page_manager_ui\Form\PageMenuForm->__construct() (line 34 of modules/contrib/page_manager/page_manager_ui/src/Form/PageMenuForm.php).

Drupal\page_manager_ui\Form\PageMenuForm->__construct(Object, Object) (Line: 31)
Drupal\page_manager_ui\Form\PageMenuForm::create(Object) (Line: 28)
Drupal\Core\DependencyInjection\ClassResolver->getInstanceFromDefinition('\Drupal\page_manager_ui\Form\PageMenuForm') (Line: 238)
Drupal\ctools\Wizard\FormWizardBase->getFormId() (Line: 205)
Drupal\Core\Form\FormBuilder->getFormId(Object, Object) (Line: 227)
Drupal\Core\Form\FormBuilder->buildForm(Object, Object) (Line: 57)
Drupal\ctools\Wizard\WizardFactory->getWizardForm(Object, Array, ) (Line: 78)
Drupal\ctools\Controller\WizardFormController->getContentResult(Object, Object)
call_user_func_array(Array, Array) (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 578)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 158)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 80)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 57)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 106)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 50)
Drupal\ban\BanMiddleware->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 52)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 717)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)

Suggestions?

Christopher Riley’s picture

Is this something that is actively being supported or looked into?

dsnopek’s picture

Here's an updated patch, that cleans things up a bunch, and gets normal menu items and tabs working, as well as default tabs partially working. This could still use more clean-up, and finishing out the default tabs and actions.

dsnopek’s picture

Status: Needs work » Needs review
FileSize
53.81 KB
19.2 KB

And here's a patch that finishes default tabs and local actions! I did some more clean-up too, and while there's more that could be done, it's in a much better place.

This implements most of the same functionality (minus a few little details) as #2273531: Add ability to provide local actions and tasks so I'm going to close that one as a duplicate of this one.

dsnopek’s picture

Just hiding some older patches...

Christopher Riley’s picture

Does anyone have this working? I am using the latest dev, create a layout page, add it to the main menu save the page. I then flush the cache and no menu entry is generated and when I go to check the menu definition within page manager it defaults to the user menu even though there is no menu entry.

Suggestions?

dsnopek’s picture

Does anyone have this working?

Hm, well, I have the patch from #21 working for me! You shouldn't need to flush any caches, the code in the patch should handle that for you. Are you sure you're using the latest patch?

dsnopek’s picture

FileSize
53.85 KB

Here's a re-rolled patch! Still working in my testing.

Status: Needs review » Needs work

The last submitted patch, 25: page_manager-2620036-25.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

kevineinarsson’s picture

Changed some code from #25 since it broke my normal menu links, the derivative manager was only adding default_menu_tab and menu_tab items to the array of derivatives, as well as some inconsistent usage of the keys "menu" and "menu_name" causing some further issues.

I've also used core's menu link overrides to move some menu links around. With #25, none were applied. When I tried to update some values, the call to updateMenuLink caused a WSOD due to it trying to set the values directly to on page entity (i.e. $page->weight->value) which obviously doesn't exist. Should these overrides even be written directly to the page entity? Why not do what core does where menu link overrides are saved in a separate config entry? makes more sense IMO.

ivnish’s picture

Patch #27 work, but I can't select menu item 2 level for my page. Only menu 1 level

greenSkin’s picture

Rolled patch from #27 that is compatible with 4.0.0-rc2.

jenniferhoude’s picture

Patch #29 fails