-
Task
-
Resolution: Fixed
-
Major
-
3.7
-
None
Implements hierarchical tags.
[CMS-5485] Hierarchical tags
Migration script part 2 :
importClass(org.apache.commons.lang.StringUtils); importClass(org.apache.jackrabbit.util.Text); importClass(javax.jcr.NodeIterator); importClass(org.apache.jackrabbit.commons.predicate.NodeTypePredicate); importClass(org.apache.jackrabbit.spi.commons.iterator.Iterators); importClass(org.apache.jackrabbit.spi.commons.iterator.Predicate); var TMP_CAT_SUFFIX = '__TO_BE_MIGRATED'; var IS_TAG_PREDICATE = new NodeTypePredicate("ametys:tag", true); // Not working because ametys:tag-category is not defined as a nodetype anymore. // var IS_CATEGORY_PREDICATE = new NodeTypePredicate("ametys:tag-category", true); var IS_CATEGORY_PREDICATE = new Predicate() { evaluate: function(node) { return node.getProperty('jcr:primaryType').getString() == 'ametys:tag-category'; } } var ID_MAPPER = {}; var catCount = 0; var deductTagTarget = function(catNode) { // Filter on category children. var tagNodes = Iterators.filterIterator(Iterators.nodes(catNode.getNodes()), new Predicate() { evaluate: function(node) { return IS_TAG_PREDICATE.evaluate(node); } }); if (tagNodes.hasNext()) { var tagNode = tagNodes.next(); return tagNode.hasProperty('ametys-internal:target') ? tagNode.getProperty('ametys-internal:target').getString() : null; } return null; } var migrateCategory = function(catNode, s) { var parent = catNode.getParent(); var tagInfo = { name: StringUtils.removeEnd(catNode.getName(), TMP_CAT_SUFFIX), title: catNode.hasProperty('ametys-internal:title') ? catNode.getProperty('ametys-internal:title').getString() : 'Unknown title', description: catNode.hasProperty('ametys-internal:description') ? catNode.getProperty('ametys-internal:description').getString() : 'Unknown description', visibility: 'PUBLIC', target: deductTagTarget(catNode) || 'CONTENT' }; // Add and populate a new tag node var tagNode = parent.addNode(tagInfo.name, 'ametys:tag'); tagNode.setProperty('ametys-internal:title', tagInfo.title); if (tagInfo.description) tagNode.setProperty('ametys-internal:description', tagInfo.description); tagNode.setProperty('ametys-internal:visibility', tagInfo.visibility); tagNode.setProperty('ametys-internal:target', tagInfo.target); // Keep track of old identifer <-> new tag name to be able update service parameters below ID_MAPPER[catNode.getIdentifier()] = Text.unescapeIllegalJcrChars(tagNode.getName()); // Add category child nodes to the new tag. var childNodes = catNode.getNodes(); while (childNodes.hasNext()) { var childNode = childNodes.next(); s.move(childNode.getPath(), tagNode.getPath() + '/' + childNode.getName()); } // Remove tag category node. catNode.remove(); } var migrateCategories = function(parentNode, s) { // Filter on category children. var catNodes = Iterators.filterIterator(Iterators.nodes(parentNode.getNodes()), IS_CATEGORY_PREDICATE); while (catNodes.hasNext()) { var catNode = catNodes.next(); // Recursive preprocessing migrateCategories(catNode); if (StringUtils.endsWith(catNode.getName(), TMP_CAT_SUFFIX)) { migrateCategory(catNode, s); catCount++; } } } // 1 - Migrate categories... var migrateStep1 = function(s) { var qm = s.getWorkspace().getQueryManager(); var query = qm.createQuery("//element(*, ametys:site)/ametys-internal:plugins/web/tags", javax.jcr.query.Query.XPATH); var rootTagsNodes = query.execute().getNodes(); while (rootTagsNodes.hasNext()) { migrateCategories(rootTagsNodes.next(), s); } } migrateStep1(session); migrateStep1(liveSession); // 2 - Migrate impacted service parameters var serviceParamNames = { 'org.ametys.plugins.calendar.Agenda': 'ametys:tag-categories', 'org.ametys.plugins.tagcloud.services.Tags': 'ametys:search-by-tags', 'org.ametys.web.service.FrontSearchService': 'ametys:search-by-tags' }; var serviceCount = 0; var serviceChange = false; var migrateStep2 = function(s) { var qm = s.getWorkspace().getQueryManager(); var serviceQueryPart = "@ametys-internal:service='org.ametys.plugins.calendar.Agenda' or @ametys-internal:service='org.ametys.plugins.tagcloud.services.Tags' or @ametys-internal:service='org.ametys.web.service.FrontSearchService'"; var query = qm.createQuery("//element(*, ametys:zoneItem)[@ametys-internal:type='SERVICE' and (" + serviceQueryPart + ")]", javax.jcr.query.Query.XPATH); var serviceNodes = query.execute().getNodes(); while (serviceNodes.hasNext()) { var serviceNode = serviceNodes.next(); var serviceId = serviceNode.getProperty('ametys-internal:service').getString(); var paramsNode = serviceNode.getNode('ametys:service_parameters'); var paramName = serviceParamNames[serviceId]; serviceChange = false; if (paramsNode.hasProperty(paramName)) { var values = StringUtils.split(paramsNode.getProperty(paramName).getString(), ','); if (values != null) { for (var idx in values) { var v = values[idx]; if (StringUtils.startsWith(v, "tag-category://")) { var id = StringUtils.removeStart(v, "tag-category://"); values[idx] = ID_MAPPER[id] || values[idx]; serviceChange = true; } } // update service property paramsNode.setProperty(paramName, StringUtils.join(values, ',')); } } if (serviceChange) { serviceCount++; } } } migrateStep2(session); migrateStep2(liveSession); session.save(); liveSession.save(); println("Successfully migrated " + catCount + " tag categories."); println("Successfully migrated " + serviceCount + " impacted service.");
Migration script part 1 (pre-processing) :
importClass(org.apache.commons.lang.StringUtils); importClass(javax.jcr.NodeIterator); importClass(org.apache.jackrabbit.spi.commons.iterator.Iterators); importClass(org.apache.jackrabbit.spi.commons.iterator.Predicate); var TMP_CAT_SUFFIX = '__TO_BE_MIGRATED'; // Not working because ametys:tag-category is not defined as a nodetype anymore. // var IS_CATEGORY_PREDICATE = new NodeTypePredicate("ametys:tag-category", true); var IS_CATEGORY_PREDICATE = new Predicate() { evaluate: function(node) { return node.getProperty('jcr:primaryType').getString() == 'ametys:tag-category'; } } var catCount = 0; var preprocessCategories = function(parentNode, s) { // Filter on category children. var catNodes = Iterators.filterIterator(Iterators.nodes(parentNode.getNodes()), IS_CATEGORY_PREDICATE); while (catNodes.hasNext()) { var catNode = catNodes.next(); // Recursive preprocessing preprocessCategories(catNode); // Renaming category node var catNodeName = catNode.getName(), newCatNodeName; if (!StringUtils.endsWith(catNodeName, TMP_CAT_SUFFIX)) { newCatNodeName = catNode.getName().replaceAll('\\W', '_') + TMP_CAT_SUFFIX; s.move(catNode.getPath(), catNode.getParent().getPath() + '/' + newCatNodeName.toUpperCase()); catCount++; } } } // Processing default workspace var qm = session.getWorkspace().getQueryManager(); var query = qm.createQuery("//element(*, ametys:site)/ametys-internal:plugins/web/tags", javax.jcr.query.Query.XPATH); var rootTagsNodes = query.execute().getNodes(); while (rootTagsNodes.hasNext()) { preprocessCategories(rootTagsNodes.next(), session); } // Processing live workspace qm = liveSession.getWorkspace().getQueryManager(); query = qm.createQuery("//element(*, ametys:site)/ametys-internal:plugins/web/tags", javax.jcr.query.Query.XPATH); rootTagsNodes = query.execute().getNodes(); while (rootTagsNodes.hasNext()) { preprocessCategories(rootTagsNodes.next(), liveSession); } session.save(); liveSession.save(); println("Successfully pre-processed " + catCount + " tag categories.");
New patchs (and repository scripts have been updated)