Goal
AEM's Revert to this Version, reverts the asset as a whole (both binary and metadata) to selected version, however if you want the binary to be reverted to a specific version but keep metadata current, try the following approach...
Demo | Package Install | Github
Solution
1) Login to CRXDE Lite (http://localhost:4502/crx/de), create folder /apps/eaem-revert-binary-not-metadata
2) Create node /apps/eaem-revert-binary-not-metadata/clientlib of type cq:ClientLibraryFolder, add String property categories with value cq.gui.coral.common.admin.timeline, String[] property dependencies with value lodash
3) Create file (nt:file) /apps/eaem-revert-binary-not-metadata/clientlib/js.txt, add
revert-binary-not-metadata.js
4) Create file (nt:file) /apps/eaem-revert-binary-not-metadata/clientlib/revert-binary-not-metadata.js, add the following code (logic injects a hidden field eaem-revert-toversion-file-only into the form posted and filter in next step reads it for taking a backup of metadata before its reverted to another version)
(function($, $document) { var EAEM_REVERT_CSS = "eaem-revert-toversion-file-only", REVERT_FILE_NOT_METADATA_TITLE = "Revert to this Version (File)", REVERT_TO_VERSION_SEL = ".cq-common-admin-timeline-event-button"; $document.on("click", ".cq-common-admin-timeline-event", addRevertToThisVersionFile); function addRevertToThisVersionFile(){ var $timeLineButton = $(this).find(REVERT_TO_VERSION_SEL); if(!_.isEmpty($timeLineButton.next("." + EAEM_REVERT_CSS))){ return; } $(getButtonHtml()).insertAfter($timeLineButton).click(revertToVersion); } function getButtonHtml(){ return '<button is="coral-button" class="' + EAEM_REVERT_CSS + '" size="M" variant="secondary" style="width:100%; margin-top:.2rem">' + '<coral-button-label>' + REVERT_FILE_NOT_METADATA_TITLE + '</coral-button-label>' + '</button>' } function revertToVersion(event){ event.preventDefault(); var $form = $(this).closest("form"), $otbRevert = $(this).prev(REVERT_TO_VERSION_SEL); $form.append("<input type='hidden' name='" + EAEM_REVERT_CSS + "' value='true'/>"); $otbRevert.click(); } })(jQuery, jQuery(document));
5) Add filter apps.experienceaem.assets.ExperienceAEMVersionFilter for taking backup of metadata before product's logic reverts both binary and metadata. Later, restore metadata from the backup, thereby keeping it current...
package apps.experienceaem.assets; import com.day.cq.commons.jcr.JcrUtil; import org.apache.commons.lang3.StringUtils; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceResolver; import org.osgi.framework.Constants; import org.osgi.service.component.annotations.Component; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.jcr.Node; import javax.jcr.Session; import javax.servlet.*; import java.io.IOException; @Component( service = Filter.class, immediate = true, name = "Experience AEM Restore file only (not metadata) Filter", property = { Constants.SERVICE_RANKING + ":Integer=-99", "sling.filter.scope=COMPONENT", "sling.filter.selectors=version" } ) public class ExperienceAEMVersionFilter implements Filter { private static final Logger logger = LoggerFactory.getLogger(ExperienceAEMVersionFilter.class); private static String EAEM_REVERT_PARAM = "eaem-revert-toversion-file-only"; private static String METADATA_BACKUP = "metadata-backup"; @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { SlingHttpServletRequest slingRequest = (SlingHttpServletRequest)request; String assetPath = slingRequest.getParameter("path"); if(StringUtils.isEmpty(assetPath)){ chain.doFilter(slingRequest, response); return; } String revertParam = slingRequest.getParameter(EAEM_REVERT_PARAM); if(StringUtils.isEmpty(revertParam)){ chain.doFilter(slingRequest, response); return; } ResourceResolver resolver = slingRequest.getResourceResolver(); Session session = resolver.adaptTo(Session.class); Resource assetResource = resolver.getResource(assetPath); if(assetResource == null){ chain.doFilter(slingRequest, response); return; } String folderPath = assetPath.substring(0, assetPath.lastIndexOf("/")); String backupName = assetResource.getName() + "-" + METADATA_BACKUP; String backupPath = folderPath + "/" + backupName; Resource metadata = assetResource.getChild("jcr:content/metadata"); if(metadata == null){ chain.doFilter(slingRequest, response); return; } try{ if(session.itemExists(backupPath)){ session.removeItem(backupPath); } JcrUtil.copy(metadata.adaptTo(Node.class), resolver.getResource(folderPath).adaptTo(Node.class), backupName, true); chain.doFilter(slingRequest, response); String metadataPath = metadata.getPath(); session.removeItem(metadataPath); session.move(backupPath, metadataPath); session.save(); }catch(Exception e){ logger.error("Error taking metadata backup - " + assetPath , e); } } @Override public void destroy() { } }
No comments:
Post a Comment