cleanup groovy nodetypes properties Jahia 7.3 Jahia 8

How to remove a property from a nodeType?

Question

How to clean up a nodeType definition to remove a property?

Answer

If you want to clean up a nodeType definition by removing a property, you first need to remove all related content.

To do it, you can use the following groovy script, and edit the following variables:

  • doIt: if set to "true", this script write to the JCR (first run it using false value to check if everything is OK)
  • nodeType: nodeType to search on
  • propertyName: name of the property
     

Then you can run the script from the OSGI console. 

import org.jahia.api.Constants
import org.jahia.services.content.*
import org.jahia.registries.ServicesRegistry
import javax.jcr.NodeIterator
import javax.jcr.RepositoryException
import javax.jcr.query.Query
/*
This groovy script can be userd to cleanup some content. 
You need to set the nodeType and the name pf the property ro remove.
This script will try to publish all updated nodes (only if there was no pending updates)
 */


// doIt: if set to "true", this script write to the JCR (first run it using false value to check if everything is OK)
boolean doIt = false;

// nodeType: node Type to search on
String nodeType = "jnt:myNodetype";

// propertyName: name of the property
String propertyName = "myProperty";


def logger = log;
Set<String> nodesToAutoPublish = new HashSet<String>();
Set<String> nodesToManuelPublish = new HashSet<String>();

JCRTemplate.getInstance().doExecuteWithSystemSession(null, Constants.EDIT_WORKSPACE, new JCRCallback<Object>() {
    @Override
    public Object doInJCR(JCRSessionWrapper session) throws RepositoryException {
        def q = "SELECT * FROM [" + nodeType + "]";

        NodeIterator iterator = session.getWorkspace().getQueryManager().createQuery(q, Query.JCR_SQL2).execute().getNodes();
        while (iterator.hasNext()) {
            final JCRNodeWrapper node = (JCRNodeWrapper) iterator.nextNode();
            if (node.hasProperty(propertyName)) {
                if (hasPendingModifications(node)) {
                    nodesToManuelPublish.add(node.getIdentifier());
                } else {
                    nodesToAutoPublish.add(node.getIdentifier());
                }
                try {
                    if (doIt) {
                        node.getProperty(propertyName).remove();
                        node.save();
                    }
                    logger.info("Remove property " + propertyName + " for node " + node.getPath());
                } catch (Exception e) {
                    log.warn("Property " + propertyName + " cannot deleted", e);
                }
            }

        }
        if (doIt) {
            session.save();
        }

        if (CollectionUtils.isNotEmpty(nodesToAutoPublish)) {
            if (doIt) {
                ServicesRegistry.getInstance().getJCRPublicationService().publish(nodesToAutoPublish.asList(), Constants.EDIT_WORKSPACE, Constants.LIVE_WORKSPACE, null);
            };
            logger.info("");
            logger.info("Nodes published:")
            for (String identifier : nodesToAutoPublish) {
                logger.warn("   " + session.getNodeByIdentifier(identifier).getPath());
            }
        }
        if (CollectionUtils.isNotEmpty(nodesToManuelPublish)) {

            logger.info("");
            logger.info("Nodes publish manually (has pending modifications):")
            for (String identifier : nodesToManuelPublish) {
                logger.warn("   " + identifier + " " + session.getNodeByIdentifier(identifier).getPath());
            }
        }
        return null;
    }
});

private boolean hasPendingModifications(JCRNodeWrapper node) {
    try {
        if (!node.isNodeType(Constants.JAHIAMIX_LASTPUBLISHED)) return false;
        if (!node.hasProperty(Constants.LASTPUBLISHED)) return true;
        final GregorianCalendar lastPublished = (GregorianCalendar) node.getProperty(Constants.LASTPUBLISHED).getDate();
        if (lastPublished == null) return true;
        if (!node.hasProperty(Constants.JCR_LASTMODIFIED)) {
            // If this occurs, then it should be detected by an integrityCheck. But here there's no way to deal with such node.
            logger.error("The node has no last modification date set " + node.getPath());
            return false;
        }
        final GregorianCalendar lastModified = (GregorianCalendar)  node.getProperty(Constants.JCR_LASTMODIFIED).getDate();

        return lastModified.after(lastPublished);
    } catch (RepositoryException e) {
        logger.error("", e);
        // If we can't validate that there's some pending modifications here, then we assume that there are no one.
        return false;
    }
}

 

This script will remove the property values from all matching nodes, and will automatically publish the content if no updates were done. Else wit will list the nodes to manually publish.