Skip to content
Snippets Groups Projects

Resolve #3498248 "Pagetemplate exposed regions"

4 unresolved threads

Closes #3498248

Merge request reports

Activity

Filter activity
  • Approvals
  • Assignees & reviewers
  • Comments (from bots)
  • Comments (from users)
  • Commits & branches
  • Edits
  • Labels
  • Lock status
  • Mentions
  • Merge request status
  • Tracking
  • Wim Leers
  • Wim Leers
  • Wim Leers
  • Wim Leers
  • Wim Leers
  • Wim Leers
  • Author Maintainer

    Self-review.

  • Wim Leers requested changes

    requested changes

  • Wim Leers added 1 commit

    added 1 commit

    Compare with previous version

  • Wim Leers added 2 commits

    added 2 commits

    • 07e18241 - Make `PageTemplate` HTTP API test coverage more representative.
    • 4bedddd0 - Unit test coverage for validating `editable`.

    Compare with previous version

  • 148 151
    149 152 private function addGlobalRegions(PageTemplate $template, array &$model, array &$layout): void {
    153 $active_component_trees = iterator_to_array($template->getComponentTrees());
    154 // Only expose regions marked as editable in the `layout` for the client.
    155 // @see experience_builder_form_system_theme_settings_alter()
    156 $editable_regions = array_keys(array_filter($template->get('editable')));
    157
    150 158 $draft_template = $this->autoSaveManager->getAutoSaveData($template);
    151 159 if ($draft_template === NULL) {
    152 foreach ($template->getComponentTrees() as $region => $tree) {
    160 foreach ($editable_regions as $region) {
    153 161 if ($region === 'content') {
    154 162 continue;
    155 163 }
    156 $layout[] = $this->buildRegion($region, $tree, $model);
    164 $layout[] = $this->buildRegion($region, $active_component_trees[$region] ?? NULL, $model);
  • 171 // editable regions.
    172 $draft_layout_region_nodes = array_filter($draft_template['layout'], fn (array $layout_node): bool => $layout_node['nodeType'] === 'region');
    173 $autosaved_regions = array_column($draft_layout_region_nodes, 'id');
    174 $missing_regions_in_auto_save = array_diff($editable_regions, $autosaved_regions);
    175 foreach ($missing_regions_in_auto_save as $region) {
    176 if ($region === 'content') {
    177 continue;
    178 }
    179 $layout[] = $this->buildRegion($region, $active_component_trees[$region] ?? NULL, $model);
    180 }
    181 $extraneous_regions_in_auto_save = array_diff($autosaved_regions, $editable_regions);
    182 foreach ($extraneous_regions_in_auto_save as $region) {
    183 foreach ($draft_template['layout'] as $index => $region_node) {
    184 if ($region_node['id'] === $region) {
    185 unset($draft_template['layout'][$index]);
    186 // @todo In principle, $model should be updated too, to omit props for components in the omitted regions. There's no consequences yet for not doing that though.
    • We already filter them out in \Drupal\experience_builder\Entity\PageTemplate::forAutoSaveData but yeah, we're wasting disk space in the DB so happy to keep the todo

    • Please register or sign in to reply
  • Lee Rowlands
  • 41 41 if ($preview && $autoSaveData = $this->autoSaveManager->getAutoSaveData($page_template)) {
    42 42 // Generate a new template based on the auto-saved data.
    43 43 try {
    44 $page_template = $page_template->forAutoSaveData($autoSaveData)->enable();
    44 $autosaved_page_template = $page_template->forAutoSaveData($autoSaveData)->enable();
    45 // There are fewer region component trees auto-saved than there are
    46 // regions when some of them are marked as not editable. For the regions
    47 // that cannot be edited: load them from the active page template.
    48 // @see experience_builder_form_system_theme_settings_alter()
    49 if (count($autosaved_page_template->get('component_trees')) < count($page_template->get('editable'))) {
    50 $autosaved_page_template->set('component_trees',
    51 $autosaved_page_template->get('component_trees')
    52 +
    53 $page_template->get('component_trees')
    • Comment on lines +51 to +53

      Are we cheating here by using ::get instead of one of our API methods? Do we need a PageTemplate::mergeRegions ?

    • Wim Leers changed this line in version 19 of the diff

      changed this line in version 19 of the diff

    • Author Maintainer

      You're on to something! :nerd: :smile:

      First thought: disagreement

      I think it's reasonable to use the "raw" information here, because AFAIK the entire auto-save functionality is done in a way that might change? The $autosaved_page_template config entity is not valid, because it doesn't contain information for all theme regions, which is required!

      So, I refactored the code to show that: 0154a9c6

      Second thought: connecting dots

      As I did 0154a9c6, I noticed that … this code is literally in a try … catch for catching ConstraintViolationException, so … naturally the logic I wrote here should be inside PageTemplate::forAutoSaveData()! But worse: why wasn't this already throwing an exception?!?!

      Turns out it was only performing validation for each region's component tree, instead of … just validating the entire PageTemplate :sweat_smile:

      1. To make this more apparent, I changed its test coverage to explicitly assert validation errors: b0a0ff85.
      2. That in turn made it easy to prove that in its current state, invalid PageTemplate config entities are returned: e7480d62.
      3. Finally, I was able to move the logic you're (rightfully! :clap:) questioning here into ::forAutoSaveData(): 9b92645e :partying_face:

      Conclusion

      1. I failed to see that I should've updated PageTemplate::forAutoSaveData() :see_no_evil:
      2. PageTemplate::forAutoSaveData() was buggy, because it was validating only parts. That likely would've helped me prevent 1.

      Fixed in the aforementioned commits, and in particular in 9b92645e. Auto-saving support for PageTemplates is now way more robust! :handshake:

    • Author Maintainer

      Turns out that this means one edge cases #3494114 has introduced test coverage for to protect against simply can no longer occur: 62d95848.

      Edited by Wim Leers
    • Author Maintainer

      … and having gotten all that in place, I was then able to refactor it to be way simpler: e369eb03 :smile: :

    • Please register or sign in to reply
  • 146 146 if ($region === 'content') {
    147 147 continue;
    148 148 }
    149 // Do not wrap regions marked as not editable; this causes visible whitespace.
    150 // @see experience_builder_form_system_theme_settings_alter()
    151 if ($page_template->get('editable')[$region] === FALSE) {
    152 continue;
    153 }
    • Comment on lines +151 to +153

      Are we missing PageTemplate::isRegionEditable(string $region_name) - this is spreading logic of the shape of the data further than we should. Putting it behind a method on PageTemplate lets us change the data structure later without it impacting anywhere else. The use of :get is a tell.

    • Author Maintainer

      Good call, added PageTemplate::isEditableRegion() in 37d5b718.

      Edited by Wim Leers
    • Please register or sign in to reply
  • Nice one, left some suggestions

  • Wim Leers added 1 commit

    added 1 commit

    Compare with previous version

  • Wim Leers added 1 commit

    added 1 commit

    Compare with previous version

  • Wim Leers added 1 commit

    added 1 commit

    Compare with previous version

  • Wim Leers added 1 commit

    added 1 commit

    • 0154a9c6 - @larowlan review: Show that `$page_template->forAutoSaveData($autoSaveData)`...

    Compare with previous version

  • Wim Leers added 3 commits

    added 3 commits

    • b0a0ff85 - Refactor `PageTemplateValidationTest::testInvalidAutoSave()` to make the...
    • e7480d62 - Prove beyond any doubt that `PageTemplate::forAutoSaveData()` can return...
    • e7449dc4 - Fix indirectly related bug that gets in the way here: when `$server_props` is...

    Compare with previous version

  • Wim Leers added 1 commit

    added 1 commit

    Compare with previous version

  • Wim Leers added 1 commit

    added 1 commit

    • 9b92645e - @larowlan review: move the most complex bit of new logic into `PageTemplate::forAutoSaveData()`.

    Compare with previous version

  • Wim Leers added 1 commit

    added 1 commit

    • 62d95848 - The automatic fallback to the (guaranteed-to-be-valid) active/stored...

    Compare with previous version

  • Wim Leers added 2 commits

    added 2 commits

    • e369eb03 - Self-review: refactor `::forAutoSaveData()` to be WAY simpler now! :smile:
    • b52a50a3 - Clarifications/clean-up.

    Compare with previous version

  • Feliksas Mazeikis approved this merge request

    approved this merge request

  • Wim Leers bypassed reviews on this merge request

    bypassed reviews on this merge request

  • Wim Leers added 29 commits

    added 29 commits

    • f2057353 - 1 commit from branch project:0.x
    • f2057353...72545fb0 - 18 earlier commits
    • 357e780c - Fix assertion.
    • 2f774831 - @larowlan review: Show that `$page_template->forAutoSaveData($autoSaveData)`...
    • 20c895ad - Refactor `PageTemplateValidationTest::testInvalidAutoSave()` to make the...
    • 996403a5 - Prove beyond any doubt that `PageTemplate::forAutoSaveData()` can return...
    • 95d2f0ed - Fix indirectly related bug that gets in the way here: when `$server_props` is...
    • cb4f40c9 - `phpcs` + `phpstan`
    • b492e23f - @larowlan review: move the most complex bit of new logic into `PageTemplate::forAutoSaveData()`.
    • 81b33ff4 - The automatic fallback to the (guaranteed-to-be-valid) active/stored...
    • 4f6d135e - Self-review: refactor `::forAutoSaveData()` to be WAY simpler now! :smile:
    • 9f556c0c - Clarifications/clean-up.

    Compare with previous version

  • merged

  • Please register or sign in to reply
    Loading