- Get link
- X
- Other Apps
- Get link
- X
- Other Apps
As we all know that when we create a live copy of experience fragment or rollout any experience fragments the site's link reference inside it does not get updated as it gets updated in a page. This feature is not available OOTB.
In order to achieve that we can create a custom rollout config and can achieve our use case.
Steps :
Add Synchronization Actions to the Rollout Configuration
- Go to /apps/msm , create folder named rolloutconfig
- Under this node create another node
- jcr:primaryType ----- cq:RolloutConfig
- Title: Update XF Site Links
- Name: updateXFlinks
- cq:trigger: rollout
- Under this node now create another node
- Name:
linksUpdateXF
- Type:
cq:LiveSyncAction
Implement LiveActionFactory :
The following LiveActionFactory
class implements a LiveAction
which updates the link refence in experience fragment on creating a live copy or rollout from master experience fragment. I have excluded countryselector component from update , you can update that part according to your needs.
import java.util.Collections;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.PropertyIterator;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import org.apache.commons.lang.StringUtils;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.adobe.cq.xf.ExperienceFragmentsServiceFactory;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageManager;
import com.day.cq.wcm.api.WCMException;
import com.day.cq.wcm.commons.ReferenceSearch;
import com.day.cq.wcm.msm.api.LiveActionFactory;
import com.day.cq.wcm.msm.api.LiveRelationship;
import com.day.cq.wcm.msm.api.LiveRelationshipManager;
import com.day.cq.wcm.msm.commons.BaseAction;
import com.day.cq.wcm.msm.commons.BaseActionFactory;
import com.demo.core.constants.Constants;
import com.demo.core.utils.CommonUtils;
/**
* A factory to update experience fragments link on rollout.
*/
@Component(service = LiveActionFactory.class, property = {
LiveActionFactory.LIVE_ACTION_NAME + "=" + XFReferencesUpdateActionFactory.LIVE_ACTION_CLASS_NAME,
LiveActionFactory.LIVE_ACTION_NAME + "=" + XFReferencesUpdateActionFactory.LIVE_ACTION_NAME })
public class XFReferencesUpdateActionFactory extends BaseActionFactory<BaseAction> {
/** The Constant LIVE_ACTION_CLASS_NAME. */
public static final String LIVE_ACTION_CLASS_NAME = "XFReferencesUpdateAction";
/** The Constant LIVE_ACTION_NAME. */
public static final String LIVE_ACTION_NAME = "linksUpdateXF";
/** The Constant CONTENT_PATH_REGEXP. */
private static final String CONTENT_PATH_REGEXP = "/content/(we-retail)[\\w\\-/]*";
/** The Constant CONTENT_PATH_PATTERN. */
private static final Pattern CONTENT_PATH_PATTERN = Pattern.compile(CONTENT_PATH_REGEXP);
/** The relationship manager. */
@Reference
private LiveRelationshipManager relationshipManager;
/** The experience fragments service factory. */
@Reference
ExperienceFragmentsServiceFactory experienceFragmentsServiceFactory;
/**
* New action instance.
*
* @param valueMap the value map
* @return the XF references update action
*/
@Override
protected XFReferencesUpdateAction newActionInstance(ValueMap valueMap) {
return new XFReferencesUpdateAction(valueMap, this);
}
/**
* Creates a new XFReferencesUpdateAction object.
*
* @return the string
*/
public String createsAction() {
return LIVE_ACTION_NAME;
}
/**
* The Class XFReferencesUpdateAction.
*/
class XFReferencesUpdateAction extends BaseAction {
/** The log. */
private Logger log = LoggerFactory.getLogger(XFReferencesUpdateAction.class);
/**
* Instantiates a new XF references update action.
*
* @param valueMap the value map
* @param factory the factory
*/
public XFReferencesUpdateAction(ValueMap valueMap, XFReferencesUpdateActionFactory factory) {
super(valueMap, factory);
}
/**
* Do execute.
*
* @param source the source
* @param target the target
* @param relation the relation
* @param resetRollout the reset rollout
* @throws WCMException the WCM exception
*/
@Override
public void doExecute(Resource source, Resource target, LiveRelationship relation, boolean resetRollout)
throws WCMException {
ResourceResolver resolver = target.getResourceResolver();
PageManager pageManager = resolver.adaptTo(PageManager.class);
Page targetPage = pageManager.getPage(relation.getLiveCopy().getPath());
String sourcePath = source.getPath();
Resource sourceRoot = resolver.getResource(sourcePath);
Node sourceNode = sourceRoot.adaptTo(Node.class);
try {
PropertyIterator pi = sourceNode.getProperties();
while (pi.hasNext()) {
Property property = pi.nextProperty();
if (property.isMultiple()) {
for (Value value : property.getValues()) {
processSingleValue(value, resolver, target, pageManager, targetPage);
}
} else {
processSingleValue(property.getValue(), resolver, target, pageManager, targetPage);
}
}
} catch (RepositoryException e) {
log.error("Repository Exception", e);
}
}
/**
* Process single value.
*
* @param value the value
* @param resolver the resolver
* @param target the target
* @param pageManager the page manager
* @param targetPage the target page
* @throws RepositoryException the repository exception
*/
private void processSingleValue(Value value, ResourceResolver resolver, Resource target,
PageManager pageManager, Page targetPage) throws RepositoryException {
if (value.getType() != PropertyType.STRING) {
return;
}
String ctaPath = value.getString();
if (ctaPath == null || !ctaPath.startsWith("/content/we-retail")) {
return;
}
Matcher pathMatcher = CONTENT_PATH_PATTERN.matcher(ctaPath);
while (pathMatcher.find()) {
Resource cta = resolver.getResource(pathMatcher.group());
adjustReferences(pageManager, cta, target, targetPage);
}
}
/**
* Adjust references.
*
* @param pageManager the page manager
* @param cta the cta
* @param target the target
* @param targetPage the target page
* @throws RepositoryException the repository exception
*/
private void adjustReferences(PageManager pageManager, Resource cta, Resource target, Page targetPage)
throws RepositoryException {
if (Objects.nonNull(target) && !target.getPath().contains("countryselector") && Objects.nonNull(cta)) {
String[] array = targetPage.getPath().replace("/content/experience-fragments/we-retail/", StringUtils.EMPTY)
.split(Constants.SLASH);
Page ctaPage = pageManager.getPage(cta.getPath());
String targetCountryLanguage = array[0] + Constants.SLASH + array[1];
String ctaCountryLanguage = CommonUtils.getCountryCode(ctaPage) + Constants.SLASH
+ CommonUtils.getLanguageCode(ctaPage);
String targetPagePath = cta.getPath().replace(ctaCountryLanguage, targetCountryLanguage);
new ReferenceSearch().adjustReferences(target.adaptTo(Node.class), cta.getPath(), targetPagePath, false,
Collections.emptySet());
}
}
/**
* Handles.
*
* @param source the source
* @param target the target
* @param relation the relation
* @param resetRollout the reset rollout
* @return true, if successful
* @throws RepositoryException the repository exception
* @throws WCMException the WCM exception
*/
@Override
protected boolean handles(Resource source, Resource target, LiveRelationship relation, boolean resetRollout)
throws RepositoryException, WCMException {
return source.getPath().contains("experience-fragments");
}
}
}
Code from CommonUtils:
public static String getCountryCode(final Page currentPage) {Page languagePage = getLanguagePage(currentPage);final String country = "us";if (Objects.nonNull(languagePage) && Objects.nonNull(languagePage.getParent())&& Objects.nonNull(languagePage.getParent().getName())) {return languagePage.getParent().getName();}return country;}public static Page getLanguagePage(final Page currentPage) {if (Objects.nonNull(currentPage)) {return currentPage.getAbsoluteParent(3);}return null;}public static String getLanguageCode(final Page currentPage) {if (Objects.nonNull(currentPage)) {return currentPage.getLanguage(Boolean.FALSE).getLanguage();}return StringUtils.EMPTY;}
Now while rolling out or creating your experience fragment choose Update XF Site Links rollout config along with Standard rollout config, then Save and then rollout or create live copy. You will see the Link references inside Experience fragment are updated and pointing correctly.
AEM
AEM 6.5
AEM as a Cloud Service
AEM SDK
AEMaaCS
base action
blueprint
experience fragment
language copy
link update
live action
live copy
reference update
rollout
rollout config
- Get link
- X
- Other Apps
Comments
Post a Comment