- Issue created by @phenaproxima
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
This is inaccurate.
ComponentTreeItem
doesn't allowDynamicPropSource
s. That's been the case since ๐ Tighten validation: only allow StaticPropSource in XB fields + PageTemplate, DynamicPropSource in ContentTypeTemplate Active .Only
ContentTemplate
config entities' (being introduced in #3517741, which spawned this issue to keep scope tight there) component trees will be allowed to useDynamicPropSource
s. - First commit to issue fork.
- Merge request !908[#3518336]: Initial POC on moving field dependencies to the ContentTemplate entity โ (Open) created by danielveza
- ๐ณ๐ฟNew Zealand danielveza Brisbane, AU
Im pretty interested in following the ContentTemplate work, so I figured I'd make a start on this one based on the IS and the discussion from #2. I've pushed up a POC of the existing work I've done so far, which now adds config dependencies for fields to the content template entities. This has test coverage, but still additional work to be done around code cleanup and removing the legacy code from `ComponentTreeItemTest`
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
Woohoo, thanks so much! ๐
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
Per #3518248-11: [PP-1] Content templates, part 4 (boss battle): create a UI for editing templates โ , this should block that.
- ๐บ๐ธUnited States phenaproxima Massachusetts
I did some work on this to move the dependency resolution into
ComponentInputs
. I also made sure that it checks for base field overrides, which are another kind of config dependency (and we do need to test for this). - ๐บ๐ธUnited States phenaproxima Massachusetts
I have a question that either Wim or Lauri need to answer, brought up by this issue.
The way the MR currently works, a content template that contains a dynamic prop expression targeting a field -- base field override or normal bundle field -- will cause the template to be dependent on that field.
That makes sense from a data integrity standpoint, but are we not setting up a situation where, if a site builder deletes a field, all templates that mention that field are deleted too? That seems extremely bad.
What should we do here? We probably need
ContentTemplate
to implementonDependencyRemoval()
to handle this case in some way, or XB to be able to show a graceful fallback (assuming it doesn't already) if a prop expression is referring to a field that no longer exists. Either way, this needs product and tech lead input, so assigning this to Wim before we do any more work on it. - ๐ซ๐ฎFinland lauriii Finland
We certainly should not delete the whole content template as a result of deleting a field. ๐ I think we should just remove the use of the dynamic prop from the content template. In case the deleted field happens to be a required, we replace the dynamic prop expression with example value.
- ๐บ๐ธUnited States phenaproxima Massachusetts
Cool. This sounds like it's more of a frontend issue, then, and not really a data integrity problem (and thus, I'd imagine, not a stable blocker).
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
This sounds like it's more of a frontend issue, then,
How/why do you conclude that? ๐ค ๐
It's not the front end that is deleting a
FieldConfig
; that's a pure server-side concern. It might also happen through a configuration sync.This is the
ContentTemplate
equivalent of #3484682-12: Handle update and delete of Block `Component`s, plus missing config dependencies โ : we need to implementContentTemplate::onDependencyRemoval()
. - ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
This is at minimum soft-blocked on ๐ Calculate field and component dependencies on save and store them in an easy to retrieve format Active , but not yet sure whether I should hard-block it on that. Your help on that issue would surely be appreciated, @phenaproxima ๐
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
So: @lauriii and I +1'd @phenaproxima's proposal in #10:
We probably need
ContentTemplate
to implementonDependencyRemoval()
โฆ and I missed that while writing #13 โ but you can see that there's other cases where we still need to do that, @phenaproxima โ it'd be nice for you to lead the way here :)
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
See #3457504-33: XB field type: calculate all dependencies, store them in queryable format, surface in new Component "Audit" operation โ โ as of that moment, that MR implements a superset of
ComponentInputs::getDependencies()
that this MR was adding.That means that:
- This is now hard-blocked on ๐ Calculate field and component dependencies on save and store them in an easy to retrieve format Active โ because that other MR clearly is the more precise, complete, reliable solution.
- This issue can now be rescoped to handle the
::onDependencyRemoval()
part ๐ฅณ
@phenaproxima: can you please help finish that issue? ๐
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
Related, from ~10 months ago, where we predicted exactly this issue: ๐ Prevent fields from being deleted if they are used in Experience Builder field's dynamic prop values Active .
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
๐ Calculate field and component dependencies on save and store them in an easy to retrieve format Active is in!
The current MR is AFAICT obsolete; everything in it has already been implemented (in a more comprehensive manner) in #3457504.
That means that the remaining scope here should be implementing (and testing)
::onDependencyRemoval()
. - ๐บ๐ธUnited States phenaproxima Massachusetts
Took a crack at this - still needs tests and such, but does it look basically like what you're hoping for? I'm not sure what to do if a prop expression in a content template is referring to a removed field, but I'm hoping that just unsetting the input will allow it to fall back to the example value.
- ๐บ๐ธUnited States phenaproxima Massachusetts
Actually, never mind - the issue summary definitely says what a reasonable test would look like.
- ๐บ๐ธUnited States phenaproxima Massachusetts
Re-titled and updated the issue summary to reflect the current realities.
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
The content template should not be deleted.
Indeed!
This should make XB to fall back to the default (example) values for those inputs.
Yes, that's what @lauriii proposed in #11 ๐
In my mind, we would just delete the component instance. But โฆ I think what you propose here (and I guess makes more sense indeed! ๐So:
- I have a
ContentTemplate
(forarticle
nodes) with ahero
component instance whosemarquee
prop is populated by
{ "marquee": { "sourceType":"dynamic", "expression":"โน๏ธโentity:node:articleโfield_funny_messageโโvalue" } }
i.e. it fetches the
value
field property of thefield_funny_message
field on thearticle
node type.This was a
DynamicPropSource
. - The site builder wants to delete
field_funny_message
; and it's not reasonable for aContentTemplate
to block that, but theContentTemplate
should also not be deleted. ContentTemplate::onDependencyRemoval()
, checks iterates over all component instance inputs and finds the one that actually depends on this particular field (i.e. on thefield.field.node.article.field_funny_message
config). It replaces theDynamicPropSource
with aStaticPropSource
.Rough outline of algorithm:
- Check if this component requires explicit input
ComponentSourceInterface::requiresExplicitInput()
. If not:[]
(the empty array) - Sanity check: assert that
Component::getSource() instanceof GeneratedFieldExplicitInputUxComponentSourceBase
โ only these sources can be populated by fields. - (Untested PoC.) Populate all props with examples (which means: all required ones, plus the optional ones that do have an example).
$component = Component::load(โฆ); $source = $component->getSource(); assert($source instanceof GeneratedFieldExplicitInputUxComponentSourceBase); if (!$component->requiresExplicitInput()) { return []; } // @see `type: experience_builder.generated_field_explicit_input_ux` $props_with_examples = array_keys(array_filter( $source->getSettings()['prop_field_definitions'], fn (array $def) => $def['default_value'] !== NULL )); return array_map( fn (string $prop_name) => $source->getDefaultStaticPropSource()->toArray() $props_with_examples );
๐ This should return something like
{ "marquee": { "sourceType":"static:field_item:string", "value": "Hello, world!", "expression":"โน๏ธstringโvalue" } }
(You will need to refactor
GeneratedFieldExplicitInputUxComponentSourceBase
to make certain methods available toContentTemplate
. For alternative implementation inspiration, seeGeneratedFieldExplicitInputUxComponentSourceBase::buildConfigurationForm()
). ComponentSourceInterface::validateComponentInput()
on the end result- Prior to saving, verify the end result by using
\Drupal\experience_builder\Plugin\Validation\Constraint\ValidComponentTreeConstraintValidator::validate()
IOW: kinda like
\Drupal\Core\Entity\EntityDisplayBase::onDependencyRemoval()
:)- Check if this component requires explicit input
- I have a
- ๐บ๐ธUnited States phenaproxima Massachusetts
Wrote an initial (functional) test, but I will still need to update the code based on Wim's outline in #23.
- ๐บ๐ธUnited States phenaproxima Massachusetts
Probably ready for an initial review.
- ๐ฆ๐บAustralia larowlan ๐ฆ๐บ๐.au GMT+10
wim leers โ credited larowlan โ .
- ๐บ๐ธUnited States phenaproxima Massachusetts
OK, I did some refactoring here to both bring things more in line with what Lee and Wim are asking for, and make it so that only the affected inputs are the ones that get replaced or cleared out (that bit still needs test coverage).