Uploaded image for project: 'Hippo CMS'
  1. Hippo CMS
  2. CMS-13875

HST model loading can 'deep copy' referenced component(item)s which do not have DynamicComponentParameters populated

    XMLWordPrintable

Details

    • Bug
    • Status: Closed
    • Blocker
    • Resolution: Fixed
    • None
    • 14.3.0
    • None
    • None

    Description

      This only happens for old-style-component-items.

      What can happen here is that a component below hst:components or hst:pages references another component which is a tree of components which get deep-copied into the referencee.

      However, if the referenced tree contains items which should have DynamicComponentParameters, it can happen that these are not populated yet, and thus a deep copy is done without population, which does not happen after the deep copy any more, since only the 'canonical components' get their DynamicComponentParameters populated and deep-copies get it copy of it.

      The fix is super simple: instead of

          public void populateComponentReferences(final Collection<HstComponentConfiguration> populate,
                                                  final ClassLoader websiteClassLoader) {
              for (HstComponentConfiguration child : populate) {
                  if (isNotEmpty(child.getComponentDefinition())) {
                      ((HstComponentConfigurationService) child).populateCatalogItemReference(availableContainerItems);
                  }
              }
      
              final Map<String, List<DynamicParameter>> legacyComponentParametersCache = new HashMap<>();
              final Map<String, List<DynamicFieldGroup>> legacyComponentFieldGroupsCache = new HashMap<>();
      
              for (HstComponentConfiguration child : populate) {
                  if (isEmpty(child.getComponentDefinition())) {
      
                      // In case the component is a container item, this is legacy component instances support. For components
                      // which are not container items, this is not legacy!
                      // If component instance does not have a component definition reference, explicitly populate component parameters.
                      ((HstComponentConfigurationService) child).populateLegacyComponentParameters(websiteClassLoader,legacyComponentParametersCache);
                      ((HstComponentConfigurationService) child).populateLegacyFieldGroups(websiteClassLoader, legacyComponentFieldGroupsCache);
                      ((HstComponentConfigurationService) child).populateComponentReferences(canonicalComponentConfigurations);
                  }
              }
          }
      

      we must do

          public void populateComponentReferences(final Collection<HstComponentConfiguration> populate,
                                                  final ClassLoader websiteClassLoader) {
      
              final Map<String, List<DynamicParameter>> legacyComponentParametersCache = new HashMap<>();
              final Map<String, List<DynamicFieldGroup>> legacyComponentFieldGroupsCache = new HashMap<>();
      
              for (HstComponentConfiguration child : populate) {
                  if (isNotEmpty(child.getComponentDefinition())) {
                      ((HstComponentConfigurationService) child).populateCatalogItemReference(availableContainerItems);
                  } else {
                      // In case the component is a container item, this is legacy component instances support. For components
                      // which are not container items, this is not legacy!
                      // If component instance does not have a component definition reference, explicitly populate component parameters.
                      ((HstComponentConfigurationService) child).populateLegacyComponentParameters(websiteClassLoader,legacyComponentParametersCache);
                      ((HstComponentConfigurationService) child).populateLegacyFieldGroups(websiteClassLoader, legacyComponentFieldGroupsCache);
                  }
              }
      
              for (HstComponentConfiguration child : populate) {
                  if (isEmpty(child.getComponentDefinition())) {
                      // Only AFTER #populateCatalogItemReference, #populateLegacyComponentParameters and #populateLegacyFieldGroups
                      // have been done it is allowed to invoke #populateComponentReferences : If we do it while not all
                      // components have the 'component parameters' set, the result can be that referenced component items are
                      // already merged/deep copied into another component while not having their 'dynamic component parameters' set, and
                      // thus are not fully functional!
                      ((HstComponentConfigurationService) child).populateComponentReferences(canonicalComponentConfigurations);
                  }
              }
      
          }
      

      Attachments

        Issue Links

          Activity

            People

              Unassigned Unassigned
              aschrijvers Ard Schrijvers
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: