Problem/Motivation

Consider the block configuration schema:

block.block.*:
  type: config_entity
  label: 'Block'
  mapping:
#...
    settings:
      type: block.settings.[%parent.plugin]

And now look at this configuration:

#...
id: bartik_footer
plugin: 'system_menu_block:footer'
settings:
  visibility: {  }
#...

Looking at the plugin value in block.block.bartik_footer we have a problem. The plugin value is the derivative ID - system_menu_block:footer which means we end up looking for schema types of block.settings.system_menu_block:footer whereas we intend to look for block.settings.system_menu_block. This means we can't add a schema for the new settings being introduced by #474004: Add options to system menu block so primary and secondary menus can be blocks rather than variables.

Proposed resolution

Use colons in Drupal\Core\Config\TypedConfigManager::getFallbackName() to check for more schema fallback types.

For example:

block.block.*:
  type: config_entity
  label: 'Block'
  mapping:
#...
    settings:
      type: block.settings.[%parent.plugin]
block.settings.system_menu_block:*:
  type: mapping
  mapping:
#... the rest of the definition.

Remaining tasks

Commit.

User interface changes

None

API changes

None

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

alexpott’s picture

Issue summary: View changes
Status: Active » Needs review
Issue tags: +Needs tests
Related issues: +#474004: Add options to system menu block so primary and secondary menus can be blocks rather than variables
FileSize
86.36 KB

Like so.

Gábor Hojtsy’s picture

Woah, omg. The way we resolved it earlier is we introduced a key with the value we needed in the schema in the name of not complicating the schema format further. It was supposed to be an easy to grok and simple format.

vijaycs85’s picture

The way we resolved it earlier is we introduced a key with the value we needed in the schema in the name of not complicating the schema format further.

agreed, but we didn't manage to get ride of "budle:type" format in config schema and may be we need something like like 'type_regex' to solve it?

Wim Leers’s picture

I think (and HOPE :P) the patch in #1 contains another patch? :)

alexpott’s picture

FileSize
1.5 KB

it does... lol...

Gábor Hojtsy’s picture

Well, I think the dynamic typing is pretty confusing already, would love not to make it even more confusing :/

alexpott’s picture

Issue tags: +TCDrupal 2014

Tagging...

Gábor Hojtsy’s picture

Issue tags: +Drupalaton 2014
jibran’s picture

alexpott’s picture

@effulgentsia wondered if we could make the plugin have a custom schema and store the regex on there. For example:

block.block.*:
  type: config_entity
  label: 'Block'
  mapping:
#...
    plugin:
      type: plugin_id
      label: 'Plugin'
    settings:
      type: block.settings.[%parent.plugin]

plugin_id:
  type: string
  label: 'Plugin'
  type_regex: '/^[^:]*/'

Unfortunately this can not work because if we were replacing the type using the current data ([plugin] vs [%parent.plugin]) then at that point we have no idea what the type the plugin key is - that's what we're determining!

The benefit of this approach is that this is easier to share.

xjm’s picture

Issue tags: +beta blocker

This is probably beta-blocking (per discussion with @effulgentsia and @alexpott). We might settle on a solution that isn't but we're not there yet.

alexpott’s picture

FileSize
8.08 KB

Talked about this with @effulgentsia. Using the schema system we add the schema_type_resolver to a type and then determine the type.

Schema

plugin_id:
  type: string
  label: 'Plugin'
  schema_type_resolver: '/^[^:]*/'
config_schema_test.plugin_types:
  type: mapping
  mapping:
    tests:
      type: sequence
      sequence:
        - type: test.plugin_types.[plugin_id]
          base_type: test.plugin_types
    test_with_parents:
      type: sequence
      sequence:
        - type: mapping
          mapping:
            plugin_id:
              type: plugin_id
            settings:
              type: test_with_parents.plugin_types.[%parent.plugin_id]

test.plugin_types:
  type: mapping
  mapping:
    plugin_id:
      type: plugin_id

test.plugin_types.boolean:
  type: mapping
  mapping:
    plugin_id:
      type: plugin_id
    value:
      type: boolean

test_with_parents.plugin_types.boolean:
  type: mapping
  mapping:
    value:
      type: boolean

Data

Configuration name: config_schema_test.plugin_types

tests:
  -
    plugin_id: boolean
    value: TRUE
  -
    plugin_id: boolean:derivative
    value: TRUE
test_with_parents:
  -
    plugin_id: boolean
    settings:
      value: TRUE
  -
    plugin_id: boolean:derivative
    settings:
      value: TRUE

If the type is determined by the current data eg. test.plugin_types.[plugin_id] then we need to know a base type so that we can determine the schema type of the value being used to replace the plugin id.

Status: Needs review » Needs work

The last submitted patch, 12: 2317865.12.patch, failed testing.

RainbowArray’s picture

FileSize
8.08 KB
1.03 KB

I don't think this will fix the installation issue, but in reviewing this to try to find the cause of the failure I found a typo in the spelling of the word definition in several variable names. Small fix with a correction for that.

RainbowArray’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 14: 2317865.14.patch, failed testing.

fago’s picture

Wondering whether that is not possible to do with type-inheritance as usual? I've never really written config schema, so it might be nonsense, but I'd have thought of defining something like:

system_menu_block*:
  type: system_menu_block

So the derivative plugin would have to add that as well. Any reasons that does not work?

dawehner’s picture

I am glad that this finally got a beta blocker, as this block proper schema support for views since ever.

+++ b/core/lib/Drupal/Core/Config/TypedConfigManager.php
@@ -251,13 +265,23 @@ protected function replaceVariable($value, $data) {
+        if ($schema !== NULL) {
+          // If the schema for the value has a schema type resolver regular
+          // expression then use it to manipulate the value.
+          $definition = $schema->get($name)->getDataDefinition()->toArray();
+          if (isset($definition['schema_type_resolver'])) {
+            if (preg_match($definition['schema_type_resolver'], (string)$data[$name], $matches)) {
+              return $matches[0];
+            }
+          }
+        }
         return (string)$data[$name];
...
       else {

The problem with that approach is that it doesn't support the usecase that you might have a overridden plugin class for a specific derivative instance. For example the CommentRow plugin extends the EntityRow one with additional settings. We need to be sure that the specific one is loaded as well. The idea in #17 would solve that if I understand it correctly.

Gábor Hojtsy’s picture

So TypedConfigManager::getFallbackName() resolves stars only following dots. In this case, the variable part of the element is after a colon not a dot. I would also prefer a simpler solution for this. The regex is totally black magic, the whole dynamic typing situation is already complex to understand. What about making stars work in general, not just after dots? That sounds like would be way simpler than regexing...

alexpott’s picture

Status: Needs work » Needs review
FileSize
7.52 KB

Ok so here is something that will use colons in the fallback mechanism. Making stars work in general is going to add heaps of complexity to getFallbackName()

effulgentsia’s picture

Title: Schema types and plugin derivatives » Config schema definitions for plugins aren't applied to their derivatives

Retitling for clarity. I like the approach in #20, but given all the reviewers who commented in the earlier comments on prior approaches, let's get a couple more +1s on this before RTBC'ing it.

vijaycs85’s picture

+1 for #20 as we have same pattern (.*) support already.

alexpott’s picture

FileSize
3.68 KB
7.02 KB

I really was not happy with the quotes in the schema type keys so that we could have a : in there. Realised that there is a better way which slightly limits the number of fallback possibilities (not sure that this is a bad thing) for an improved DX.

-'test.plugin_types.boolean:*':
+test.plugin_types.boolean*:
   type: test.plugin_types.boolean

How much nicer is that?

neclimdul’s picture

I guess this means this supports derivatives but not derivatives with different separators. I'm ok with that, since its pretty hard to implement and I don't really see that being used.

Gábor Hojtsy’s picture

Status: Needs review » Needs work
Issue tags: +Needs issue summary update

Yay, this implementation looks much better than that complicated regex stuff. I only have relatively minor comments but important for making this easy to understand. Otherwise looks good.

  1. +++ b/core/lib/Drupal/Core/Config/TypedConfigManager.php
    @@ -155,7 +159,7 @@ public function clearCachedDefinitions() {
        *   Same name with the last part(s) replaced by the filesystem marker.
        *   for example, breakpoint.breakpoint.module.toolbar.narrow check for
    -   *   definition in below order:
    +   *   definitions in the following order:
    
    @@ -163,12 +167,20 @@ public function clearCachedDefinitions() {
        *     breakpoint.breakpoint.*
    ...
    +   *   Colons are also used, for example,
    +   *   block.settings.system_menu_block:footer check will for definitions in the
    +   *   following order:
    

    English should be unified on these. "check will for" definitely does not work. :D The first uses "check for definitions" which should probably also be "will check for"?

  2. +++ b/core/modules/config/src/Tests/ConfigSchemaTest.php
    @@ -397,4 +397,35 @@ function testSchemaFallback() {
    +   * Tests use of schema_type_resolver to determine schema..
    +   */
    +  function testSchemaTypeResolver() {
    

    The comment and method name do not match the current implementation anymore.

Will need an issue summary update and a change notice. I'll do a draft change notice now. Needs work for the code changes needed.

alexpott’s picture

Issue summary: View changes
Status: Needs work » Needs review
FileSize
2.53 KB
7.47 KB

Re: #24 yeah I thought about this too - not sure what to do. Do you think it is worth not allowing derivatives with different separators?

Re: #25

  1. Fixed - reworked the @return completely to make more sense.
  2. Fixed

Fixed issue summary too.

alexpott’s picture

effulgentsia’s picture

Re #23: I'm not happy with removing the colon from the schema key wildcard pattern. For example, I wouldn't want image.effect.image_scale* being a fallback for image.effect.image_scale_and_crop. However, turns out that the YAML spec does allow colons to appear in unquoted keys, so long as they're not followed by whitespace, and Symfony's YAML parser respects that spec. So test.plugin_types.boolean:*: works as a line of YAML.

Re #24: Let's not hold this issue up on it, but I opened #2319503: Should TypedConfigManager::getFallbackName() support plugin derivatives whose IDs are not delimited with a colon? so we can discuss it further.

alexpott’s picture

Issue summary: View changes
FileSize
4.07 KB
7.62 KB

Sure... here's a patch to swap it back and test that.

Status: Needs review » Needs work

The last submitted patch, 29: 2317865.29.patch, failed testing.

alexpott’s picture

Status: Needs work » Needs review
FileSize
7.97 KB
2.95 KB

Fixed the one star matching.

Gábor Hojtsy’s picture

Issue summary: View changes
Status: Needs review » Reviewed & tested by the community

Fix minor syntax glitch in issue summary. Added change notice at https://www.drupal.org/node/2319739

The updated patch looks good to me :) I'm *really* glad we did not (need to) go with the regex solution.

Dries’s picture

Status: Reviewed & tested by the community » Fixed

Glad we sorted this one out after all. Committed to 8.0.x. Thank you!

  • Dries committed 8ed2e20 on
    Issue #2317865 by alexpott, mdrummond: Fixed Config schema definitions...
Gábor Hojtsy’s picture

Superb, thanks!

chx’s picture

The regular expression here could be seriously simplified because you do not need to escape anything in a PCRE character class except the closing square bracket.

vijaycs85’s picture

turns out that the YAML spec does allow colons to appear in unquoted keys

If anyone wonder about the above statement, please refer: http://www.yaml.org/spec/1.2/spec.html#id2788859 and raised an issue with phpStorm(http://youtrack.jetbrains.com/issue/WI-24607) as it doesn't support this atm.

Status: Fixed » Closed (fixed)

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