How can I alter the list of available layouts in the Panels IPE? I'm trying to hide or remove several layouts from the layout selectors, so that users can only select from an approved list. I can do this successfully with hook_form_alter() code, but the Panels IPE isn't using a form for its layout selection tray. It seems the best method would be to use LayoutPluginManagerInterface somehow, so that any function that displays a list of available layouts will have the same list available, but so far I haven't figured it out. Is there a way to do this?
I've been trying to curate the Panels IPE more to my liking, and so far, it seems like overriding the controller is a decent way to go.

Say you're wanting to do this in my_example module:


Inside your custom module, create src/Controller/CustomPanelsIPEController.php. We want to extend from panels_ipe/src/Controller/PanelsIPEPageController.php into this file, and change the namespace declaration and change the class name to match:

&lt;?php

namespace Drupal\my_module\Controller;

use Drupal\panels_ipe\Controller\PanelsIPEPageController;

/**
 * Contains all JSON endpoints required for Panels IPE + Page Manager.
 */
class MyModuleIPEController extends PanelsIPEPageController {
...

Now, we need to have our routing subscriber tune in to panels IPE being called, and re-route it to our new method. Create src/Routing/MyExampleRoutingSubscriber.php, and add the following:

namespace Drupal\my_example\Routing;

use Drupal\Core\Routing\RouteSubscriberBase;
use Symfony\Component\Routing\RouteCollection;

/**
 * Listens to the dynamic route events.
 */
class MyExampleRoutingSubscriber extends RouteSubscriberBase {
  /**
   * {@inheritdoc}
   */
  protected function alterRoutes(RouteCollection $collection) {
    if ($route = $collection-&gt;get('panels_ipe.block_plugins')) {
      $route-&gt;setDefault('_controller', '\Drupal\my_example\Controller\MyModuleIPEController:getBlockPlugins');
    }
  }
}



So now what will happen is our Panels IPE is now calling our method.

So now, we can do some more precise altering. For a simple example, when it comes to creating blocks, let's say we wanted to only give users a single module called 'awesome_blocks' for their choices when creating content. 

public function getBlockPluginsData($panels_storage_type, $panels_storage_id) {
   $panels_display = $this-&gt;loadPanelsDisplay($panels_storage_type, 
   $panels_storage_id);

   // Get block plugin definitions from the server.
   $definitions = $this-&gt;blockManager-&gt;getDefinitionsForContexts($panels_display-&gt;getContexts());

   // Assemble our relevant data.
   $blocks = [];
   foreach ($definitions as $plugin_id =&gt; $definition) {
     if ($definition['provider'] == "awesome_blocks") { // Added this logic
     ...


In this simple example, I've altered the logic to ONLY show blocks from the awesome_blocks module. Now of curse, I was altering the blocks, and you were asking about the layouts. The layouts can be altered the same way! Inside of the getLayoutsData() function that is in this same class, you could implement custom logic. To alter the layouts in the same way, we could add another function inside our custom Routing controller, inside the alterRoutes() method:

    if ($route = $collection-&gt;get('panels_ipe.layouts')) {
        $route-&gt;setDefault('_controller', '\Drupal\my_example\Controller\MyModuleIPEController:getLayouts');
    }


Now, just implement custom logic in the getLayouts method:

public function getLayoutsData($panels_storage_type, $panels_storage_id) {
    $panels_display = $this-&gt;loadPanelsDisplay($panels_storage_type, $panels_storage_id);

    // Get the current layout.
    $current_layout_id = $panels_display-&gt;getLayout()-&gt;getPluginId();

    // Get a list of all available layouts.
    $layouts = $this-&gt;layoutPluginManager-&gt;getDefinitions();
    $base_path = base_path();
    $data = [];
    foreach ($layouts as $id =&gt; $layout) {
        if ($layout['provider'] == 'my_layout_module') { // Added logic check here
        ...
        }


Hope this helps!