Hi

The documentation requires you to define layouts that define the usage of layout_options like so:

Defining a Layout
First, you need a layout that uses the LayoutOptions class. Here's a simple example that
would be in your *.layouts.yml file:

my_1col_100:
label: One column - 100
category: My Layouts
class: '\Drupal\layout_options\Plugin\Layout\LayoutOptions'
template: templates/my_1col_100
icon_map:
- [main]
regions:
main:
label: Content

Now the issue, I'm using a contributed module that defines the layouts for me, so how would one add the "class" definition to indicate that those layouts are supposed to use the layout_options on my site? Is there a way to "extend" or "override" the layouts from the contributed module?

Comments

BramDriesen created an issue. See original summary.

bramdriesen’s picture

Issue summary: View changes
cgmonroe’s picture

A lot depends on how the 3rd party module is built. If it is just using a layout.yml to define the layouts, then you should be able to use

hook_layout_alter(&$descriptions)

I have not used this but I figured out how to get a quick debug dumps of the descriptions array.

First, it looks like this can not be called from the theme and has to be called from a module.

The descriptions array contains keys for all the layouts defined on the site (e.g. your module, core's, and any others).

The value of the this key is a Drupal\Core\Layout\LayoutDefinition object, e.g.:

'layout_onecol' => Drupal\Core\Layout\LayoutDefinition

The properties of this class are "standardized information from the yaml file, E.g.:

protected deriver -> NULL
protected label -> Drupal\Core\StringTranslation\TranslatableMarkup(5)
protected description -> NULL
protected category -> Drupal\Core\StringTranslation\TranslatableMarkup(5)
protected template -> string(14) "layout--onecol"
protected templatePath -> string(44) "core/modules/layout_discovery/layouts/onecol"
protected theme_hook -> string(14) "layout__onecol"
protected path -> string(44) "core/modules/layout_discovery/layouts/onecol"
protected library -> string(23) "layout_discovery/onecol"
protected icon -> NULL
protected icon_map -> array(1)
protected regions -> array(1)
protected default_region -> string(7) "content"
protected additional -> array(0)
protected id -> string(13) "layout_onecol"
protected class -> string(32) "Drupal\Core\Layout\LayoutDefault"
protected provider -> string(16) "layout_discovery"
protected config_dependencies -> array(1). 

Note the class property. There is a setClass($fullyQualifiedClassNameString) method.

Looks like you should be able inject the layout_options class into the template here.

I would only attempt this if the class is the default "Drupal\Core\LayoutLayoutDefault value.

I don't have time right now to do any testing, but the theory here seems sound. Please report back if this works out for you.

bramdriesen’s picture

Aha cool! I'll take a look at that this weekend :-) I didn't know there was an alter hook that would work on the YAML files. The module I'm using is radix_layouts (bootstrap 4 that is), and it's indeed just using the default layouts.yml implementation, so indeed, in theory this should work.

Thanks for the directions and I'll update you if it's working or not :-).

bramdriesen’s picture

Hi @cgmonroe,

Thank you so much for the directions! This indeed solved the issue for me with a simple implementation of the layout_alter hook.

/**
 * Implements hook_layout_alter().
 */
function MYMODULE_layout_alter(&$definitions) {
  /** @var Drupal\Core\Layout\LayoutDefinition $definition */
  foreach ($definitions as $definition) {
    if (strpos($definition->id(), 'radix_') === 0) {
      $definition->setClass('\Drupal\layout_options\Plugin\Layout\LayoutOptions');
    }
  }
}

Maybe it's a good idea to include this in the documentation of the module that it's possible to override templates provided by modules.

cgmonroe’s picture

Thanks for the feedback.

I'm working on a "layout_options_ui" submodule now. This will provide a admin page at Config->System->Layout Options Overrides that will display a list of layouts that use the default class by provider (module/theme machine name) and layout name.

Admins can check which layouts to use the layout options class with and the module's implementation of hook_layout_alter will use this configuration to override the selected layouts.

No special code needed, just enable the ui module.

bramdriesen’s picture

Status: Active » Postponed

Sounds promising :-) I'll set it to postponed then ;-)

  • cgmonroe committed cc5f05d on 8.x-1.x
    Issue #3113215 by cgmonroe: How to override layouts from a contributed...
cgmonroe’s picture

Status: Postponed » Fixed

The dev branch now includes a layout_options_ui submodule. Here's the readme from it:

Layout Options UI
=================

This module allows existing layouts supplied by other modules or core to have their default layout plugin class replaced with the Layout Options class. These layouts will now show the layout configuration options defined in your layout_options YAML files.

First, enable this module on your site.

Then, to select the layouts to override, go to the Admin->Configuration->System->Layout Options page. You will see a list of
providers (module machine names) and layouts that are can be overridden.

Check the ones you want to override and submit.

Note: Only layouts that use the default Layout Plugin Class will be shown. Layouts that use their own custom classes will not work with this.

bramdriesen’s picture

Cool, maybe tag a new RC candidate? :-) or you maybe don't want to have that included yet?

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.