Problem/Motivation
In #3340712: Add Single Directory Components as a new experimental module comment #70 highlights the need to have sub-schema references, or type aliases. Then #104 explores how to use the JSON Schema reference syntax to structure complex schemas in SDC.
However we are not expanding prop schemas with $ref in the current implementation.
Proposed resolution
We can leverage the JsonSchema\SchemaStorage along with a custom URI retriever to allow referencing other schemas. I am proposing that we support module:/ and theme:/ in component props. The custom URI retriever will likely extend FileGetContents and will expand module:/my-module to file:///var/www/html/web/modules/custom/my-module (or similar).
This way we could have a module or theme with custom definitions:
In web/themes/custom/my-theme/schema-definitions.json:
{
"$defs": {
"iconType": {
"type": "string",
"enum": ["type1", "type2"]
},
"color": {
"type": "string",
"pattern": "^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$"
}
}
}
Then any component could do:
# ...
props:
type: object
properties:
bgColor:
$ref: theme:/my-theme/schema-definitions.json#$defs/color
title: Background Color
# ...
Remaining tasks
Ensure schemas are expanded for all the schema uses:
- Component validation
- Replacement validation
- Input validation
Note that SchemaStorage is not a full dependency but a core-dev dependency. We might need to do a similar trick as we did for setValidator.
User interface changes
None
API changes
None
Data model changes
None
| Comment | File | Size | Author |
|---|---|---|---|
| #9 | 3352063--schema-refs--wip--9.patch | 4.01 KB | e0ipso |
| #7 | 3352063--schema-refs--test-only--7.patch | 1.27 KB | e0ipso |
Issue fork drupal-3352063
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:
Comments
Comment #2
e0ipsoThis is blocked until SDC is an experimental module.
Comment #3
e0ipsoWe could also allow referencing other components with a new custom scheme
component:/. Any component could then reference prop definitions from other components:However, I don't think this is good UX. IMO components should not be artificially interlinked like this.
Comment #4
e0ipsoComment #6
e0ipsoComment #7
e0ipsoAdding a test only patch that shows the goal we want to accomplish.
Comment #8
e0ipsoComment #9
e0ipsoI did start working on the retriever on the plane on my ride back from DrupalCon. Here is some progress, in case someone wants to pick it up.
Next we need to go into
ComponentMetadata::parseSchemaInfoand instantiate a newSchemaStoragewith the custom retriever toaddSchemaand thengetSchema. This will resolve the references in the schema to save in theComponentMetadataproperty.However this will require the library
justinrainbow/json-schemato be vetted as runtime drupal core dependency. Which is a big blocker.Comment #10
e0ipsoComment #11
e0ipsoComment #12
dieterholvoet commentedComment #13
pdureau commentedHello e0ipso,
On your "Single Directory Components in Drupal Core " article, there is this code snippet:
Source: https://www.lullabot.com/articles/getting-single-directory-components-dr...
It is managed by ComponentValidator::getClassProps() but:
Comment #14
e0ipsoWe are using a superset of JSON-Schema. This was the best solution we could find to non-JSON data types, which are valid Twig variables.
This is the main place where it is used in core. In contrib,
cl_editorialwill likely fail to generate a form element for these classes.Comment #16
wim leersSeems like this is SUPER important for DX, to avoid repeating the same definitions over and over again (and preventing subtle inconsistencies)? 🤓
Or am I misunderstanding this? How is it possible that we only have
core/modules/sdc/src/metadata.schema.jsonandcore/modules/sdc/src/metadata-full.schema.jsontoday, because based on this issue I'd think there'd be many*.schema.jsonfiles? 🤔Comment #17
pdureau commentedHi Wim,
We "solved" this issue in UI Patterns 2.x.
We have added a new "prop type" plugin type which have a JSON schema annotation.
Examples:
https://git.drupalcode.org/project/ui_patterns/-/blob/2.0.x/src/Plugin/U...
https://git.drupalcode.org/project/ui_patterns/-/blob/2.0.x/src/Plugin/U...
A developer can use JSON schema references targeting the prop type plugin ID:
The URL are resolved by justinrainbow/json-schema thanks to a stream wrapper service https://git.drupalcode.org/project/ui_patterns/-/blob/2.0.x/src/SchemaMa...
With a bit of help to manage the recursive references: https://git.drupalcode.org/project/ui_patterns/-/blob/2.0.x/src/SchemaMa...
So, the
"$ref"is replaced by the schema of the prop type plugin annotation.This system is extensible by adding new prop type plugins.
We would be happy to get rid of our implementation if Core is solving this issue too.
Comment #18
wim leersSo: bumping to .
Comment #19
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue.
While you are making the above changes, we recommend that you convert this patch to a merge request. Merge requests are preferred over patches. Be sure to hide the old patch files as well. (Converting an issue to a merge request without other contributions to the issue will not receive credit.)
Comment #20
e0ipsoOne goal that I want to keep in mind is that this needs to have a very low friction. That's why I initially thought about letting components reference props in other components. This had the benefit of not having to do anything to declare the referenceable schemas. Sadly, this is not viable. Mainly because the referenced component may be deleted, and then the schema would break. This stems from the fact that there is no dependency chain between components (which I believe it's a good thing).
So, if we don't want to introduce dependencies between components but we want to re-use schemas, what dependencies do we introduce? I think the easiest is to depend on modules / themes. They are the things we install and uninstall, and we do check dependencies on such operations.
#7 proposes a JSON file (with any name) in a module, which can be referenced as
module:/modulename/path-to-any-file#json-path-to-schema-definition. This may be too lose, and therefore give pause and be hard to document. Perhaps we want to enforce a specific name for the file (how aboutcomponents/prop-types.json?), and then reference itcomponent-schemas:/modulename#json-path-to-schema-definition.Comment #21
wim leers+1
I think in #7 and #9, you were already heading in a different direction though, that would not be dependent on component existence? There it'd be individual extensions (modules/themes) that can declare additional JSON schema definitions. Since SDCs always ship as part of an extension (module or theme), it would be guaranteed that that JSON schema file will exist (thanks to containing module/theme's declared dependencies).
So +1 to:
Why would it be too loose? 🤔
👆 YES! 🤩 Heck, it could even be
json-schema-definitions://<extension name>#$defs/<DEFNAME>, so for examplejson-schema-definitions://image_gallery#$defs/galleryTitleAndCaptionand core could provide commonly used things likejson-schema-definitions://core#$defs/image!Tangentially related, but off-topic:
🤔 I was wondering about this. Does that also mean it's impossible to compose SDCs using only SDCS? I.e. put SDC B into SDC A's slot, and declare that result as SDC C?
Comment #22
wim leersIn the PoC I'm working on for Experience Builder, I was able to transform this SDC prop metadata:
to
thanks to a new
./schema.jsonfile in my module namedexperience_builder, as well as the more complex SDC prop metadatato
thanks to:
plus a new stream wrapper service inspired by @pdureau's superb work in
ui_patterns2.0.x(see #17 — I'd never have found it otherwise!).The
SdcPropToFieldTypePropTestkernel test is still passing, meaning it's still finding Drupal field type props that match 1:1 shape-wise and semantically into exactly those SDC props. (Grep for the stringℹ︎␜entity:node:foo␝field_silly_image␞␟{src↝entity␜ℹ︎␜entity:file␝uri␞␟value, alt↠alt, width↠width, height↠height}— that's the string representation of the expression that defines the mapping from Drupal field type props into SDC props).Code: https://git.drupalcode.org/project/experience_builder/-/commit/f784af412...
Comment #23
e0ipsoThis is great progress! It shows that it can be done.
I would advocate for a name that is more specific to components. I propose
components/shared-schemas.json. This is because it is scoped to thecomponents/folder, and it conveys that you only need this if you want to share definitions.justinrainbow/json-schemahas a the concept of UriRetriever, which accomplishes the same. The advantage is that by following their pattern we can resolve schemas recursively every time (without having to pluck out the reference and resolve it manually). This includes loading the schema for validation during development time.Comment #24
wim leersI actually did that intentionally: the idea would be that other things in Drupal core or the general Drupal (contrib) ecosystem could use this same infrastructure. For SDC's purposes, we'd verify that there'd be a top-level
$defs(with definitions underneath), but anything else in that file it'd just ignore.… but that's probably a premature abstraction, so I'm fine with changing that — it was just a proposal 🤓 I liked the simplicity of
/schema.json, but I don't feel strongly about it.Are you sure that actually works? https://github.com/justinrainbow/json-schema/issues/427 suggests it does not?
Comment #25
wim leers@lauriii in DM:
My response:
That’s not valid JSON Schema. Defining new types is not permitted. Although https://json-schema.org/understanding-json-schema/reference/schema#vocab... seems to be changing that … 🤞 Per https://github.com/json-schema-org/json-schema-vocabularies, there aren’t a whole lot of examples just yet.
@lauriii again:
So I'm curious what you think, @e0ipso.
Still, trying to indulge Lauri here, by taking the above to its logical conclusion: :nerd_face:
The use of a dialect like I mentioned above would allow us to declare:
instead of
but with one significant downside: now you need a custom JSON schema implementation everywhere you want to run validation. See https://json-schema.org/understanding-json-schema/reference/schema#guide....
Comment #26
pdureau commentedWhat about
$ref: module://experience_builder/image?This proposal with static declarations in
shared-schemas.jsonis exciting.But, while implementing it, let's not block the use of alternative and complementary reference systems, like the one we already use in UI Patterns 2:
ui-patterns://colorwhere "color" is a plugin ID.They all can live together inside a single reference solver mechanism, because the implementation is the same until the stream wrappers. What happens after the stream wrappers can differ.
Comment #27
e0ipsoThat's tricky because I disagree with the premise in #25.

I think type:
'drupal-image'is way more confusing. It only gives you a label. It doesn't give you any info about what adrupal-imageis, what are its dependencies, or were to find more info about it. Everything is implicit with that.
On the other hand, using
$ref: <uri>#<locator>you are:JSON PathJSON Pointer, in this case) to locate a data sub-structure within a file.experience_builderdrupalmodule.I agree with @pdureau that perhaps a different URI template would give less pause.
$ref: module-components://experience_builder#definitions/imagewould be my preference, but I realize that's exactly what Lauri is trying to avoid.I think the key here is that this feature is not for the ambitious site builder, but for the component developer. It is likely that they won't try to remember either or. They will copy an example and adapt to their needs. With just
drupal-imageyou cannot explore other options, guess them, or know how to declare your own. You are restricted to the examples you come across. With the$refyou find the file where it is declared, you see other definitions, you can find for other files with the same name with other definitions, infer that you can create a file with that name to add your own definitions, etc.Comment #28
wim leers+1!
Nothing to add to #27 — thanks for articulating it so clearly, @e0ipso 😊
Comment #29
lauriiiCreating components is a common enough task that it should be really easy for someone who is a) not familiar with Drupal b) not a senior developer and hence c) does not know JSON-Schema. This is highly relevant for workflows where the user has a pre-existing design system that they want to integrate with Drupal. For this persona,
type: 'drupal-image'would be the north star experience because they don't care whether we use JSON-Schema or not.That said, using JSON-Schema as a starting point makes sense, but we should not let it define what is the developer experience we provide. We just don't want to require users to learn JSON-Schema in order to be successful. Because of this, we need to consider how we can simplify some of the more complex workflows instead of being dogmatic about implementing the specification.
What's being proposed in #26 seems to be making this more reasonable already. However, even that could be seen as a strange by someone who is not familiar with the syntax. This user might ask; what is difference between
$refandtype, why do I now need these two now, and why does the value need to follow a strange pattern with://.Comment #30
e0ipsoI think that from the SDC perspective:
a) Writing a component does not require much knowledge about Drupal, by design (as you very well know from being a co-conspirator on SDC)
b) I don't think this is required for writing SDC, or referencing schemas.
c) I think this is a soft requirement. If you want to write components with schemas, you kinda need to know they way they are written (JSON Schema). Now, do you need to be an expert? Definitely not.
I think the discussion is not weather or not it's OK to elevate the barrier of entry to newcomers to Drupal, I think we all agree on keeping it the lowest possible.
I think the discussion is that @lauriii in #29 argues that the
$refthing is complicated, and might put people off. And I think that using made up types likedrupal-imagemakes things more complicated and dis-empowers said newcomers.In #27 I tried to argue why an open list of made up types is bad UX. How do we document the made up types that contrib modules provide? How do we make the eventual documentation page discoverable for front-end developers? How do we tell newcomers that there may be other types? (in addition to all those challenges, now we are back to our island instead of following an industry standard... I think I am repeating myself at this point, sorry).
Comment #31
lauriii@e0ipso are you saying that in your mind, the syntax proposed in #26 leads into a better DX for a user who is a) not familiar with Drupal b) not a senior developer c) and hence does not know JSON-Schema? Is it because it's able to better solve the problems you are raising in #30?
Comment #32
e0ipsoYeah. I even have a slight preference with
$ref: module-components://experience_builder#definitions/image* as mentioned in #27. Not because it is easier to write, or easier to remember, but because it's easier to copy&tweak and easier to find the documentation about it (specially when the component author is already writing optional JSON-Schema).*My slight preference comes from the fact that it uses the $ref recommended syntax JSON Pointer. Which is documented for us, and the resolution mechanism is already implemented in the
justinrainbow/json-schemalibrary without additional stream wrappers.Comment #33
effulgentsia commentedI haven't read all the discussion here, but I noticed some discussion about the DX of JSON schema, or certain decisions we might want to make about the details of the JSON schema we want to use, so I want to quickly mention that https://github.com/vega/ts-json-schema-generator is a pretty great library that lets you convert TypeScript definitions to JSON schema. In other words, if we want to optimize for DX, we might want to consider a DX where people can write TypeScript definitions instead of writing JSON schema by hand, and then the JSON schema creation can be automated which would allow us to optimize the JSON schema to suit SDC's needs rather than optimizing for manually writing it.
Comment #34
e0ipsoWhile I am an advocate of TS (I even pushed an ADR at Lullabot to the effect), I do not think that we should prescribe it in order to write re-usable schemas. This is specially true since we are not writing JSX components in Drupal (yet).
In any case the import method is a bit similar. In one case we defer to the native module loader and a URI, and in the other we use a custom code loader and a URI.
Comment #35
pdureau commentedA declarative format is better than an executable format for such definitions. No runtime needed, no performance issue, no security risk.
https://en.m.wikipedia.org/wiki/Rule_of_least_power
Yet? Oh god 😳
Comment #36
wim leersAgreed that the source of truth should always be a JSON schema definition.
But I think @effulgentsia was merely stating that it's possible to provide a TypeScript-only DX that generates such a JSON schema definition. I doubt he's proposing to enforce it, nor make it the default.
The fact that it's possible is … nice, interesting and potentially powerful eventually :)
Comment #37
e0ipsoAh! Thanks for the clarification @Wim Leers. I was taking it as a "there is no need to dwell too much in this now, since we'll be able so solve it with a build step".
To pile on that spirit that @effulgentsia brings on #33, I'll say that using industry standards will bring us more and more of these tools for free. Not only to generate the schemas, but also to read and leverage them. Staying true to the JSON-Schema standard will also allow us to auto-generate forms for the component props, synthetic examples, etc. Carving out (more) exceptions like
drupal-imagewill make these tools fail without specific handling.Comment #38
nod_Ended up here through #3514072: SDC slots can set expectations and cardinality , I like
$ref: module://experience_builder/imagefrom #26.We agreed on JSON-schema for props, let's follow-though on our decision and build on this as explained by @e0ipso and @pdureau (our 2 SDC maintainers). The DX concerns can be handled once things actually work, there are ways to address them as demonstrated by @effulgentsia in #33. We can have a whole layer of SDC generation that smooth out things for end users in contrib if it's not nice enough by default. The important thing here is that it works reliably in a non-drupal specific way
Comment #39
nod_Comment #40
pdureau commentedA little up-to-date summary of the 2 existing JSON Schema stream wrappers in contrib.
Experience Builder
Example:
json-schema-definitions://foo.module/barJsonSchemaDefinitionsStreamwrapper service is:
foomodule as extension andbar$defschema.jsonfile from the extension path. Example:/modules/contrib/foo/schema.jsonPro: is generic, any module can provide JSON schema definition without any dependency to Experience builder outside this stream wrapper.
Con: only static declaration
UI Patterns 2
Example:
ui-patterns://barStreamwrapper service is:
barIDPro: $defs are shipped alongside some niceties (type converter, data normalizer...) as a cohesive mechanism.
Con: a dependency to
plugin.manager.ui_patterns_prop_typeserviceProposal
We can go the Experience Builder way because it is easier to ask UI Patterns 2 maintainers to add and maintain a
schema.jsonfile in their module instead of introducing a new plugin type to Core.Also, this may be the opportunity to:
$ref: module://experience_builder/imagebut we can propose another schema if "module" or "theme" are too generic) because this kind of URL will be typed a lot by component authors, with a lot of chance of mistakes$ref: <uri>#<locator>) to leverage existing JSON schema mechanisms instead of extracting manually like JsonSchemaDefinitionsStreamwrapper is actually doing (however, I would advise to explore $anchor keyword instead of the propsoed JSON pointer)So, if we mix both, we can have something like that:
$ref: module://experience_builder#imageThis may not be enough
However, this proposal is not solving another issue reported by @finnsky : #3480464: [2.1.x] Make the SDC scheme more universal.
We are becoming more and more generic, but it is still a Drupal only proposal (
moduleandthemescheme,schema.jsonconvention...).What can we do to make those references working outside of Drupal (for example: in storybook)?
Comment #41
pdureau commentedComment #42
pdureau commentedModules and themes are sharing a single namespace, so we have the opportunity to do something like
drupal://orextension://instead ofmodule://andtheme://Comment #43
pdureau commentedComment #44
mherchelOr if we have an image component that we want to be able to use with and without Experience Builder.
Is it possible to have a fallback value? Maybe something like
Comment #45
pdureau commentedAs far as I know, Json schema allows only one value in $ref
https://json-schema.org/understanding-json-schema/structuring
Comment #46
pdureau commentedWe can't use
module://andtheme://because the schemes are already "taken" by #1308152: Add stream wrappers to access .json files in extensions.By the way, we can go fully the #1308152: Add stream wrappers to access .json files in extensions way instead of adding our dedicated wrapper.
Also, do we still need a schema resolver to help
justinrainbow/json-schemaresolving recursive structures like UI Patterns is doing? (justinrainbow/json-schemagot new releases since last year)So, component users, will need to explicitly :
This proposal is interesting because it is not a SDC specific proposal with magic loading of data in an arbitray named file, but a combination of:
Schemas: proposal for inclusion
So, this MR may be empty of PHP :) That would be nice. But it will also be the opportunity to add some schemas directly in Core modules.
In a perfect Drupal world, neither UI Patterns nor Experience builder will bring its own schemas to avoid dependencies from themes to those display building modules.
So, proposal:
module://image/schema.json#image(replacing
json-schema-definitions://experience_builder.module/image)module://image/schema.json#image-uri(replacing
json-schema-definitions://experience_builder.module/image-uri)module://system/schema.json#attributes(replacing
ui-patterns://attributes)module://system/schema.json#links(replacing
ui-patterns://links)See also #3474528: Add unified Links data type for menus, pagers, breadcrumbs...
module://system/schema.json#identifier(replacing
ui-patterns://identifier)A string with characters suitable for an HTML ID
What else?
Comment #47
pdureau commentedGiving a try. Still targeting11.3
Comment #48
pdureau commentedIt may also be the opportunity to remove this from
ComponentMetadata:Which is making a mess with the JSON schema. We need to rely only on what the component author provides. Let's check if this removal breaks tests and contrib projects like UI Patterns or Canvas (it must be OK).
Comment #49
pdureau commentedIndeed. So we are dependent on 2 other issues:
My first MR will embed them. Let's have a working proposal first.
Also, let's check if the proposal will work with HTTP URI to see if we cover: #3480464: [2.1.x] Make the SDC scheme more universal.
Comment #51
pdureau commentedMerge request opened with 3 commits: https://git.drupalcode.org/project/drupal/-/merge_requests/13457
2 commits from other issues
A squash of #1308152: Add stream wrappers to access .json files in extensions
✅ Seems to work well.
An implementation of #3365985: Promote justinrainbow/json-schema from dev-dependency to full dependency
We simply moved the requirement out of
dev.⚠️ However:
composer update --lockfix this but is making the diff huge.The scope of the current issue
The addition of
ComponentPluginManager::resolveJsonSchemaReferences()That's cool because we use only "standards":
justinrainbow/json-schemawith JSON pointers❌ However, some JSON objects, all under
anyOf, are transformed intostdClassinstead of an array. That's the reason why phpunit fails.1 definition coming from Canvas
module://image/schema.json#imageas ajson-schema-definitions://canvas.module/imagereplacement.⚠️ Not exactly the same as Canvas because of this JSON schema error:
2 definitions coming from UI Patterns 2
Those one have nested references, so we can check this mechanism is also OK:
module://system/schema.json#attributesas aui-patterns://attributesreplacement.module://system/schema.json#linksas aui-patterns://linksreplacement.Update
ComponentValidatorAdd a little security t in the "Ensure that all property types are strings" logic introduced in Drupal 11.2 in case the
$refwas not resolved successfully. It is how the schema resolver of justinrainbow works.The removal of the
{"type": "object"}additionWith an adaptation of
ComponentMetadataTest::testMetadata().A kernel test
core/tests/Drupal/KernelTests/Components/SchemaReferenceResolverTest.phpwithcore/modules/system/tests/themes/sdc_theme_test_referencesComment #52
pdureau commentedUpdated.
Some pipepline jobs KO but I don't see if it is related to my current work: https://git.drupalcode.org/issue/drupal-3352063/-/pipelines/625236
Locally,
phpunit -c core/ --group sdcis OKCommits from other issues
A squash of #1308152: Add stream wrappers to access .json files in extensions
✅ Seems to work well.
An implementation of #3365985: Promote justinrainbow/json-schema from dev-dependency to full dependency
We simply moved the requirement out of
dev.✅ Seems to work well after
composer update --lock.The scope of the current issue
The addition of
ComponentPluginManager::resolveJsonSchemaReferences()That's cool because we use only "standards":
justinrainbow/json-schemawith JSON pointers✅ works OK
I was a bit afraid
json_decode(json_encode($schema), TRUE)would be too slow but I saw than the equivalent logic dromjustinrainbowis doing the same: https://github.com/jsonrainbow/json-schema/blob/main/src/JsonSchema/Cons...1 definition coming from Canvas
module://image/schema.json#imageas ajson-schema-definitions://canvas.module/imagereplacement.⚠️ Not exactly the same as Canvas because of this JSON schema error:
2 definitions coming from UI Patterns 2
Those one have nested references, so we can check this mechanism is also OK:
module://system/schema.json#attributesas aui-patterns://attributesreplacement.module://system/schema.json#linksas aui-patterns://linksreplacement.Update
ComponentValidatorAdd a little security t in the "Ensure that all property types are strings" logic introduced in Drupal 11.2 in case the
$refwas not resolved successfully. It is how the schema resolver of justinrainbow works.The removal of the
{"type": "object"}additionWith an adaptation of
ComponentMetadataTest::testMetadata().A kernel test
core/tests/Drupal/KernelTests/Components/SchemaReferenceResolverTest.phpwithcore/modules/system/tests/themes/sdc_theme_test_referencesComment #53
wim leersDid a first round of review, found a few concerns. 😇
Looking forward to #3365985: Promote justinrainbow/json-schema from dev-dependency to full dependency landing, which will be step #1 to simplify this MR!
Comment #54
pdureau commentedWill look at the comment and move the proposed schema to test module. Adding schema will be its own issue for a next Drupal release.
Comment #55
pdureau commentedKeeping on my side because of the PHPunit errors: https://git.drupalcode.org/issue/drupal-3352063/-/jobs/6934948/viewer
However, they are all related to
Drupal\KernelTests\Core\StreamWrapper\ExtensionStreamTestso it has to be fixed in #1308152: Add stream wrappers to access .json files in extensionsComment #56
pdureau commentedOK for review.
The duplicate of #3365985: Promote justinrainbow/json-schema from dev-dependency to full dependency has been removed.
The duplicate of #1308152: Add stream wrappers to access .json files in extensions is still here.
No phpunit error anymore. A functional test error (
Drupal\Tests\field_ui\FunctionalJavascript\ManageDisplay) but doesn't seem related to the current work.@wim, we have 2 ongoing discussions on https://git.drupalcode.org/project/drupal/-/merge_requests/13457/diffs
Comment #57
wim leersComment #58
pdureau commentedAll changes to ComponentMetadata and ComponentMetdataTests has been moved to specific issue #3554720: Remove addition of a object type in all props.
Comment #59
pdureau commented#1308152: Add stream wrappers to access .json files in extensions is merged, I will rebase and send back to review.
Comment #60
pdureau commentedRebase is done.
The MR is full green and only 30-40 line of PHP code added to Core (blank lines, comments and tests removed).
Comment #61
pdureau commentedComment #62
pdureau commentedI take it back for:
Comment #63
wim leersPer https://git.drupalcode.org/project/drupal/-/merge_requests/13457#note_63..., I think #1308152: Add stream wrappers to access .json files in extensions would need to be changed to actually generate valid URIs that JSON Schema would not consider validation errors.
Either that, or
justinrainbow/json-schema's\JsonSchema\Tool\Validator\UriValidator::isValid()is wrong 😑However … most other URI validators are fine with it. So perhaps … it is related to the fact that DNS host names aren't allowed to contain underscores, but non-DNS-based hostnames are fine? It is https://www.rfc-editor.org/rfc/rfc952 that dictates underscores are forbidden, but the same doesn't necessarily apply here.
Comment #64
wim leersHm, checking https://www.ietf.org/rfc/rfc3986.txt:
There it is: underscores are allowed.
So
in
\JsonSchema\Tool\Validator\UriValidator::isValid()is wrong. Despite it literally referencing RFC 3986. Still wrong in the latest release: https://github.com/jsonrainbow/json-schema/blob/6.6.1/src/JsonSchema/Too....😑
Comment #65
wim leersThis will need an upstream bugfix, but we can work around it here … although it will require duplicating literally the entirety of
\JsonSchema\Constraints\FormatConstraint, or decorating it and calling it for everything exceptformat: uri|uri-reference|iri|iri-reference🤠This will still need that underscore test coverage I requested, because without it,
module://content_translation/whateverwould cause\JsonSchema\Tool\Validator\UriValidator::isValid()to fail.Comment #66
wim leersPosted a one-line work-around to not have to do the very big amount of work that #65 describes: https://git.drupalcode.org/project/drupal/-/merge_requests/13457/diffs#n... — brought to you by my sibling Canvas MR at https://git.drupalcode.org/project/canvas/-/merge_requests/255.
Comment #67
longwave@Wim as I posted over in #1308152: Add stream wrappers to access .json files in extensions while the grammar allows underscores, the RFC still discourages names that are not valid DNS records, which is why I think validation tools want to ensure they conform:
But this is a "should", not a "must".
Comment #68
effulgentsia commentedPHP 8.5 now has a spec-compliant URI parser, and there's also a polyfill for it for PHP 8.1+. I think we should file an upstream issue for JsonSchema to switch out their incorrect regex for this. In the meantime, does JsonSchema support us overriding its UriValidator?
Comment #69
longwaveI opened https://github.com/jsonrainbow/json-schema/pull/853 to see if upstream will help us out here.
@effulgentsia because justinrainbow/json-schema is a dependency of Composer, they are extremely conservative in PHP support; the 6.x branch still supports PHP 7.2, so any polyfill would have to go back that far. It's also a much bigger change than just tweaking the regex which I think is enough for us here.
Comment #70
longwavehttps://github.com/jsonrainbow/json-schema/releases/tag/6.6.2 should fix the issue.
Comment #71
pdureau commentedThat was so efficient! It was such a good idea to go upstream. Thanks @longwave.
Comment #72
wim leersWow!!!
Can we now bump core's requirement to require 6.6.2?
Comment #73
wim leersAlso, this was discovered independently by somebody else on Canvas: #3560455: [upstream] Stream wrapper URIs are incorrectly flagged as invalid (hostname misinterpreted) due to bug in `justinrainbow/json-schema` — bump minimum version to 6.6.2 — what a coincidence!
Comment #74
pdureau commentedCan I add it this to the MR or does it need a specific MR?
Comment #75
longwaveThat can be added here, as it's this issue that requires the new version.
Comment #76
pdureau commentedPipeline running...
Done. Simply by commiting Wim's proposal.
Done, but I have added a new public method instead of changing the existing one, in order to keep internal mechanisms private. IS it OK for you?
It is already the case. Theme for tests is
sdc_theme_test_referenceswith references to URL like such:theme://sdc_theme_test_references/schema.json#imageDone. From
^5.2 || ^6.5.2to^6.6.2Comment #77
pdureau commentedGreen :)
Comment #78
wim leersGiven the amazing upstream contributing experience, I asked the
jsonrainbow/json-schemamaintainer whether they'd be interested in accepting a PR from us to add recursive$refresolving. That'd mean we could omitComponentPluginManager::resolveJsonSchemaReferences()from this MR. Or, at least have to not maintain it forever. (It really does make sense to live in that project, after all.)See https://github.com/jsonrainbow/json-schema/pull/853#issuecomment-3595541100
Comment #79
wim leers$refof a required prop to become point to a nonsensical URI, that the exception is swallowed (i.e. does not cause a crash) except when verbose error reporting (ERROR_REPORTING_DISPLAY_VERBOSE) is enabled — I then get a\JsonSchema\Exception\ResourceNotFoundExceptionwith this message:(which required one tiny bugfix)
… which means Canvas starts relying on the updated
ComponentPluginManagerthat this MR introduces. A crucial kernel test passes, meaning Canvas will indeed be able to drop this, and use the exact same resolving logic, which of course is the intent. 👍 (And it's what Canvas forward-ported in #3515074: Shape matching MUST work with the resolved equivalents of $refs AND must be compatible with core's upcoming $ref resolving in SDCs.)\Drupal\Core\Theme\ComponentPluginManager::resolveJsonSchemaReferences()— see https://git.drupalcode.org/project/drupal/-/merge_requests/13457/diffs#n...Thanks, @pdureau! 🤝
Comment #81
wim leersQuoting myself from #78:
They responded there. It looks like they think we would not need to implement our own recursive
$refresolving. They asked to double-check, so I did in a new test-only MR to avoid disrupting the RTBC MR: I removed the recursion, which results in failures:Plus, even if it works upstream we still have our own special-casing now: “swallow all errors for invalid $refs unless they are for a required required prop AND verbose error logging is enabled".
Comment #82
pdureau commentedI got the same results.
Comment #83
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #85
pdureau commentedComment #87
pdureau commented3352063-11.x-pdureau and
3352063-prove-to-upstream-this-is-needed has been rebased.
Comment #88
pdureau commentedSo I hide the experimental branch which is failing phpunit by deisgn: 3352063-prove-to-upstream-this-is-needed
Comment #90
pdureau commentedTest are passing. Additional tests didn't get triggered but I guess it is in purpose.
Someone want to have a fresh look?
There is still at least one open topic to discuss: from @longwave with @effulgentsia about justinrainbow/json-schema being extremely conservative in PHP support
And I am not sure about our modifications of the root's
composer.jsonComment #91
mherchel@deviantintegral left a review in the MR.
Comment #92
pdureau commentedI will address some of Andrew's and Christian's feedbacks
Comment #93
pdureau commentedFixed, following documentation: https://www.drupal.org/about/core/policies/core-dependency-policies-and-...
It was also the opportunity to bump the dependency as suggested by Wim in #79, in order to retrieve Longwave's upstream contribution.
Done in dedicated commits.
So, Wim, we are back in "Needs review", with also an additional feedback from Andrew (@deviantintegral): https://git.drupalcode.org/project/drupal/-/merge_requests/13457#note_73... I believe you are the best to answer this specific subject.
Comment #94
grimreaperComment #96
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #97
pdureau commentedI have rebased the branch and fix the conflicts.
There is a phpunit warning, but I saw it on other current MR targeting main and there is no specific fail to check: https://git.drupalcode.org/project/drupal/-/jobs/9759002
Andrew (@deviantintegral)'s note is still the remaining part to check: https://git.drupalcode.org/project/drupal/-/merge_requests/13457#note_73
Comment #98
wim leersThe 3 commits since my review in #81 look like nice tidying. The upstream bugfix landed, and this now bumps the required upstream version instead.
I didn't re-test against Canvas like I did in #79.3, but I don't see how one of those 3 commits could cause any problems!
Thanks for making this happen! 🤩
Comment #99
alexpottAdded comments to the MR.
Also the change record seems to be full of history and not instructions for developers and what this change means for them.
Comment #100
wim leersThere is no change record yet. The linked change record is for Canvas, because it forward-ported this. 😅
Unlinked CR, added tag instead.
Comment #101
pdureau commentedComment #102
pdureau commentedHi Alex,
Thanks for your feedbacks. I am assigning the ticket to you because the last MR note is between us.
Comment #103
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #104
pdureau commentedI will do the rebase, and it will be the opportunity to think again about Alex feedback.
Comment #105
pdureau commentedRebased.
Comment #106
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #107
pdureau commentedRebasing and answering Wim questions.
Comment #108
pdureau commentedComment #109
pdureau commentedChange record: https://www.drupal.org/node/3591541
Comment #110
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #111
pdureau commentedRebased.
There is a PHPUnit Functional Javascript error:
Investigating
Comment #112
pdureau commentedRunning
core/modules/config/tests/src/Functional/ConfigInstallProfileOverrideTest.phplocally is OK. So, it may not be related to the current change.Comment #113
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.