Conflicting-blueprints

I have a conundrum that I’ve so far not found a programmatic or pragmatic way to bypass: A theme and a plugin both hook into a blueprint by extending in, but the latter breaks the former.

In the theme, an upcoming revision of Project Space, I have a blueprint in project-space/blueprints/post.yaml:

Theme post.yaml
title: Theme options
'@extends':
  type: default
  context: blueprints://pages

form:
  fields:
    tabs:
      type: tabs
      active: 1
      fields:
        options:
          type: tab
          fields:
            styleoptions:
              type: section
              title: Style
              underline: true
            header.image:
              type: filepicker
              folder: '@self'
              preview_images: true
              label: Image for thumbnail and header
              help: Sets the image to use as thumbnail and header
              accept:
                - 'image/*'
            header.color:
              type: select
              label: Background color
              help: Sets the background color for the project
              default: white
              highlight: 0
              options:
                white: White
                red: Red
                orange: Orange
                yellow: Yellow
                green: Green
                teal: Teal
                blue: Blue
                dark-blue: Dark Blue
                purple: Purple
                pink: Pink
                brown: Brown
                gray: Gray
            header.truncate:
              type: text
              label: Truncate words
              help: Limits the amount of words in each note to an integer or boolean state
              default: 40
              validate:
                  type: int
                  min: 1
                  max: 65536
            taxonomies:
              type: section
              title: PLUGIN_ADMIN.TAXONOMIES
              underline: true
              fields:
                header.taxonomy:
                  unset@: true
                header.taxonomy.category:
                  type: select
                  label: Category
                  help: Sets the state of the project
                  highlight: 0
                  config-options@: site.categories
                  options:
                    idea: 'Idea'
                    ongoing: 'Ongoing'
                    done: 'Done'
                    archived: 'Archived'
                    
                header.taxonomy.tag:
                  type: selectize
                  allowEmptyOption: true
                  label: Tags
                  help: Applies tags to the project
                  selectize:
                    data-options@: '\Grav\Theme\ProjectSpace::tags'
                  validate:
                    type: commalist

This enables options for the post.html.twig-template like custom taxonomy-handling (handled in theme settings and methods, working) and styling, and should only occur in this template’s Admin-interface.

In the plugin, an upcoming revision of Bibliography, I have a blueprint in bibliography/blueprints/post.yaml:

Plugin post.yaml
title: Bibliography options
'@extends':
  type: default
  context: blueprints://pages

form:
  fields:
    tabs:
      type: tabs
      active: 1
      fields:
        options:
          type: tab
          fields:
            bibliography:
              type: section
              title: Bibliography
              underline: true
              fields:
                header.bibliography:
                  type: filepicker
                  folder: 'user/data/bibliography'
                  preview_images: false
                  label: Bibliography-file
                  help: Sets which file to use for citations
                  accept:
                    - .json

This enables selecting a file from user/data/bibliography, that is uploaded via the plugin’s settings (working), and should also only be shown in this template’s Admin-interface. The blueprint is loaded via (as described in the docs):

public function onGetPageTemplates($event)
{
    $types = $event->types;
    $locator = Grav::instance()['locator'];
    $types->scanBlueprints($locator->findResource('plugin://' . $this->name . '/blueprints'));
}

Now, the theme’s options for post.html.twig work without issue on their own. But when I enable the plugin’s options as well, the taxonomy-fields return to being selectize, and the style-fields disappear altogether – replaced by the plugin’s bibliography filepicker-field.

In trying to solve this I have tested with Grav Core 1.4.5 and Admin 1.7.4, as well as Core 1.5.0-beta.1 and Admin 1.8.5, in addition to the theme’s dependencies. I’ve put together a test-case using the newest Core, Admin and associated plugins with the working-in-progress theme and plugin, available here. The username is admin and password is Admin000.

The behavior can be observed by commenting out line 85 of /user/plugins/bibliography/bibliography.php (ie. $types->scanBlueprints($locator->findResource('plugin://' . $this->name . '/blueprints'));)

Has anyone observed similar behavior between extensions?

After some discussion with @paul about his SEO-plugin, the resolution is for the plugin to hook into a different event and extend blueprints programmatically:

public function onBlueprintCreated(Event $event)
{
    $blueprint = $event['blueprint'];
    $blueprints = new Blueprints(__DIR__ . '/blueprints/');
    $extends = $blueprints->get($this->name);
    $blueprint->extend($extends, true);
}

This is what the plugin runs in Admin now, utilizing the upstream extend()-method, and stripping the '@extends': part from the blueprint:

Plugin bibliography.yaml
form:
  fields:
    tabs:
      type: tabs
      active: 1
      fields:
        options:
          type: tab
          fields:
            bibliography:
              type: section
              title: Bibliography
              underline: true
              fields:
                header.bibliography:
                  type: filepicker
                  folder: 'user/data/bibliography'
                  preview_images: false
                  label: Bibliography-file
                  help: Sets which file to find citations in
                  accept:
                    - .json

For clarity post.yaml was renamed to bibliography.yaml, since it is now applied globally to all page-types, as intended.

If it was desirable to only show it given some conditions, a conditional-field could be used, or the plugin’s onBlueprintCreated-method would have to hook into some logic in Admin to check for the page-type currently being edited.