groovy references replace System Administrator

How to replace hardcoded link on richText with dynamic references

Question

Some of my users use richText with hard link URL in it like :

<a href="/sites/tech/home/groups/main/section--container-groups/section--container-groups/groups/audio-systems.html" title="Audio Systems">Audio</a>

Have you a script that I can run to fix these URLs into references?

Answer

We can imagine a script with search replace, for instance

  • search: /sites/tech/home/
  • replace: /cms/{mode}/{lang}/sites/tech/home/

Here is a script that could do such a search replace, for specific contents. You will need to edit this script for your needs. This script allow multiple search and replaces, in different properties of nodeTypes.

import org.jahia.api.Constants
import org.jahia.services.content.*
import org.jahia.services.sites.JahiaSite

import javax.jcr.NodeIterator
import javax.jcr.RepositoryException
import javax.jcr.query.Query

/* set to true to save the result */
boolean doIt = false;

/* siteKey */
String siteKey = "tech";

/* limit the search/replace to a certain path */
String descendentnode = "/sites/tech";

/* propertiesToLookAt is the list of nodeTypes/properties to search in */
def propertiesToLookAt = new HashMap<String, Object>();
propertiesToLookAt.put("jnt:text",["prop1","prop2"]);
propertiesToLookAt.put("jnt:toto",["myproperty"]);

/* only search/replace in path that contains a pathRestriction */
Set<String> pathRestriction = new HashSet<String>();
pathRestriction.add("/"); // search everywhere
//pathRestriction.add("/home/documentation/");
//pathRestriction.add("/another/path/");

/* list of search / replace text */
def searchReplace = new LinkedHashMap<String, String>();
searchReplace.put("/sites/tech/home/","/cms/{mode}/{lang}/sites/tech/home/");
searchReplace.put("/files/live/sites/tech/","/files/{workspace}/sites/tech/");


def JahiaSite site = org.jahia.services.sites.JahiaSitesService.getInstance().getSiteByKey(siteKey);
for (Locale locale : site.getLanguagesAsLocales()) {
    JCRTemplate.getInstance().doExecuteWithSystemSession(null, Constants.EDIT_WORKSPACE, locale, new JCRCallback() {
        @Override
        Object doInJCR(JCRSessionWrapper session) throws RepositoryException {

            for (String nt : propertiesToLookAt.keySet()) {
                def props = propertiesToLookAt.get(nt);
                for (String prop : props) {
                    def q = "select * from [" + nt + "] where isdescendantnode('" + descendentnode + "')";

                    NodeIterator iterator = session.getWorkspace().getQueryManager().createQuery(q, Query.JCR_SQL2).execute().getNodes();
                    while (iterator.hasNext()) {
                        final JCRNodeWrapper node = (JCRNodeWrapper) iterator.nextNode();
                        String nodePath = node.getPath();
                        if (isInPathRestriction(nodePath,pathRestriction)) {
                            if (updateNode(node, prop, searchReplace)) {
                                log.info("update [" + nt + "  " + prop + "] in path " + node.path + " " );
                            }
                        }
                    }
                }
            }
            if (doIt) {
                session.save();
            }

            return null;
        }
    });
}

public boolean isInPathRestriction(String nodePath, Set<String> pathToCheck) {
    Iterator<Integer> iterator = pathToCheck.iterator();
    while(iterator.hasNext()) {
        if (nodePath.contains(iterator.next())) {
            return true;
        }
    }
    return false;
}

public boolean updateNode(JCRNodeWrapper node, String property, LinkedHashMap searchReplace) {
    String prop = node.getPropertyAsString(property);
    boolean needToBeUpdated = false;
    if (prop != null) {
        String tmp = updateContent(prop,searchReplace);
        if (!tmp.equals(prop)) {
            needToBeUpdated = true;
            node.setProperty(property, tmp);
        }
    }
    return needToBeUpdated;
}

public String updateContent(String str,LinkedHashMap searchReplace) {
    if (str == null) {
        return "";
    }
    for (String searchFrom : searchReplace.keySet()) {
        def searchTo = searchReplace.get(searchFrom);
        str = str.replaceAll(searchFrom, searchTo);
    }
    return str;
}