diff --git a/src/main/frontend/model/samples/add-node.json b/src/main/frontend/model/samples/add-node.json new file mode 100644 index 0000000..f0c01d8 --- /dev/null +++ b/src/main/frontend/model/samples/add-node.json @@ -0,0 +1,45 @@ +{ + "logLevel": "info", + "hops": [ + { + "type": "nodeQuery", + "query": "/* The search query has to return the parent nodes we want to act on */\nSELECT * FROM [nt:unstructured] AS s WHERE ISDESCENDANTNODE([/content/project])", + "queryType": "JCR-SQL2", + "hops": [ + { + "type": "createChildNode", + "conflict": "force", + "name": "${args.nName}", + "runOnExistingNode": false, + "hops": [ + { + "type": "setProperty", + "conflict": "force", + "propertyName": "sling:resourceType", + "value": "args.slingResourceType" + } + ], + "primaryType": "${args.jcrPrimaryType}" + } + ] + } + ], + "parameters": [ + { + "name": "nName", + "defaultValue": "nName", + "evaluation": "STRING" + }, + { + "name": "jcrPrimaryType", + "defaultValue": "cq:PageContent", + "evaluation": "STRING", + "type": "text" + }, + { + "name": "slingResourceType", + "defaultValue": "project/components/page", + "evaluation": "STRING" + } + ] +} diff --git a/src/main/frontend/model/samples/add-or-replace-property.json b/src/main/frontend/model/samples/add-or-replace-property.json new file mode 100644 index 0000000..f5accc0 --- /dev/null +++ b/src/main/frontend/model/samples/add-or-replace-property.json @@ -0,0 +1,32 @@ +{ + "logLevel": "info", + "hops": [ + { + "type": "nodeQuery", + "query": "SELECT * FROM [nt:unstructured] AS s WHERE ISDESCENDANTNODE([/content/project/language])", + "queryType": "JCR-SQL2", + "hops": [ + { + "type": "setProperty", + "conflict": "force", + "propertyName": "${args.propertyName}", + "value": "args.propertyValue" + } + ] + } + ], + "parameters": [ + { + "name": "propertyName", + "defaultValue": "pName", + "type": "text", + "evaluation": "STRING" + }, + { + "name": "propertyValue", + "defaultValue": "pValue", + "type": "text", + "evaluation": "STRING" + } + ] +} diff --git a/src/main/frontend/model/samples/batch-search-and-replace.json b/src/main/frontend/model/samples/batch-search-and-replace.json new file mode 100644 index 0000000..9dd116f --- /dev/null +++ b/src/main/frontend/model/samples/batch-search-and-replace.json @@ -0,0 +1,77 @@ +{ + "logLevel": "info", + "hops": [ + { + "type": "nodeQuery", + "query": "SELECT * FROM [nt:unstructured] WHERE ISDESCENDANTNODE([/content/example]) AND [sling:resourceType] = 'granite/ui/components/coral/foundation/form/textfield'", + "queryType": "JCR-SQL2", + "hops": [ + { + "type": "each", + "expression": "args.inputPropertyValues", + "hops": [ + { + "type": "runScript", + "code": "/*\n The inputPropertyValues file should be in the format ,, ex.:\n propertyName,oldVal,newVal\n propertyName1,oldVal1,newVal1\n*/\n\nsplit = str:split(vals, ',');\n\nif(arr:getLength(split) == 3) {\n propertyName = split[0];\n oldValue = split[1];\n newValue = split[2];\n} else {\n propertyName = \"\";\n oldValue = \"\";\n newValue = \"\";\n}\n", + "extension": "jexl", + "putLocalsBackIntoScope": true + }, + { + "type": "filterNode", + "expression": "jcr:val(node, propertyName) == oldValue", + "hops": [ + { + "type": "setProperty", + "conflict": "force", + "propertyName": "${propertyName}", + "value": "newValue" + } + ] + } + ], + "iterator": "vals" + } + ] + }, + { + "type": "each", + "expression": "args.inputXPath", + "hops": [ + { + "type": "runScript", + "code": "/*\n The inputXPath file should be in the form ;; ex.:\n propertyName;/jcr:root/content/swisscom/de//*[@sling:resourceType='foundation/components/parsys']/*[not(@sling:resourceType)];newVal\n propertyName1;/jcr:root/content/swisscom/de//*[(jcr:like(@sling:resourceType, 'swisscom/components/content/text'))];newVal1\n*/\n\nsplit = str:split(vals, ';');\n\nif(arr:getLength(split) == 3) {\n propertyName = split[0];\n xPathQuery = split[1];\n newValue = split[2];\n} else {\n propertyName = \"\";\n xPathQuery = \"\";\n newValue = \"\";\n}\n", + "extension": "jexl", + "putLocalsBackIntoScope": true + }, + { + "type": "nodeQuery", + "query": "${xPathQuery}", + "queryType": "xpath", + "hops": [ + { + "type": "setProperty", + "conflict": "force", + "propertyName": "${propertyName}", + "value": "newValue" + } + ] + } + ], + "iterator": "vals" + } + ], + "parameters": [ + { + "name": "inputPropertyValues", + "defaultValue": "", + "type": "file", + "evaluation": "LINES" + }, + { + "name": "inputXPath", + "defaultValue": "", + "type": "file", + "evaluation": "LINES" + } + ] +} diff --git a/src/main/frontend/model/samples/check-hardcoded-urls.json b/src/main/frontend/model/samples/check-hardcoded-urls.json new file mode 100644 index 0000000..5ac1e44 --- /dev/null +++ b/src/main/frontend/model/samples/check-hardcoded-urls.json @@ -0,0 +1,63 @@ +{ + "logLevel": "info", + "hops": [ + { + "type": "runScript", + "code": "xPathQuery = str:join([\"/jcr:root\", args.path, \"//*[jcr:contains(., '\", args.phrase, \"') and jcr:contains(., '\", args.extension, \"') ]\"]);\noutput = utils.file.txt(\"properties_containing_hardcoded_urls\");\n\n", + "extension": "jexl", + "putLocalsBackIntoScope": true + }, + { + "type": "nodeQuery", + "query": "${xPathQuery}", + "queryType": "xpath", + "hops": [ + { + "type": "each", + "expression": "node.properties", + "hops": [ + { + "type": "declare", + "declarations": { + "joinedProperty": "str:join(jcr:vals(node, property.name))" + } + }, + { + "type": "filterNode", + "expression": "str:contains(joinedProperty, args.phrase) && str:contains(joinedProperty, args.extension)", + "hops": [ + { + "type": "runScript", + "code": "output.append(property.path);\noutput.append(\"\\n\");", + "extension": "jexl", + "putLocalsBackIntoScope": true + } + ] + } + ], + "iterator": "property" + } + ] + } + ], + "parameters": [ + { + "name": "phrase", + "defaultValue": "https://www.project.ch/content/de", + "type": "text", + "evaluation": "STRING" + }, + { + "name": "extension", + "defaultValue": ".html", + "type": "text", + "evaluation": "STRING" + }, + { + "name": "path", + "defaultValue": "/content/project/de", + "type": "text", + "evaluation": "STRING" + } + ] +} diff --git a/src/main/frontend/model/samples/delete-nodes.json b/src/main/frontend/model/samples/delete-nodes.json new file mode 100644 index 0000000..c6776d5 --- /dev/null +++ b/src/main/frontend/model/samples/delete-nodes.json @@ -0,0 +1,26 @@ +{ + "logLevel": "info", + "hops": [ + { + "type": "each", + "expression": "['de', 'fr', 'it', 'en']", + "hops": [ + { + "type": "nodeQuery", + "query": "SELECT * FROM [nt:unstructured] AS s WHERE ISDESCENDANTNODE([/content/swisscom/${lang}]) AND [cq:template] = '/conf/swisscom/settings/wcm/templates/swisscom-content-page'", + "queryType": "JCR-SQL2", + "hops": [ + { + "type": "moveNode", + "conflict": "ignore", + "newName": "/dev/null" + } + ] + } + ], + "iterator": "lang", + "assumeNodes": false + } + ], + "parameters": [] +} diff --git a/src/main/frontend/model/samples/index.ts b/src/main/frontend/model/samples/index.ts index beecf48..0920d2d 100644 --- a/src/main/frontend/model/samples/index.ts +++ b/src/main/frontend/model/samples/index.ts @@ -4,6 +4,16 @@ import removeTempGulpPackages from './remove-gulp-packages.json'; import updateBuildTimestamp from './update-build-timestamp.json'; import findComponentAndPage from './find-component-and-page.json'; import createMissingJcrContentNodes from './create-missing-jcr-content-nodes.json'; +import migrateResourceType from './migrate-resource-type.json'; +import migratePageTemplate from './migrate-page-template.json'; +import batchSearchAndReplace from './batch-search-and-replace.json'; +import checkHardcodedUrls from './check-hardcoded-urls.json'; +import removeDeprecatedLegacyUrls from './remove-deprecated-legacy-urls.json'; +import deleteNodes from './delete-nodes.json'; +import renameProperty from './rename-property.json'; +import addOrReplaceProperty from './add-or-replace-property.json'; +import addNode from './add-node.json'; +import renameNode from './rename-node.json'; import { Hop, HOP_DEFINITIONS } from '../hops'; import { Script } from '../Script'; @@ -47,4 +57,44 @@ export const SAMPLES: Sample[] = [ config: createMissingJcrContentNodes as Script, label: 'Sample: Create missing jcr:content node for pages', }, + { + config: migrateResourceType as Script, + label: 'Sample: Migrate Resource Type', + }, + { + config: migratePageTemplate as Script, + label: 'Sample: Migrate Page Template', + }, + { + config: batchSearchAndReplace as Script, + label: 'Sample: Batch search and replace', + }, + { + config: checkHardcodedUrls as Script, + label: 'Sample: Check hardcoded urls', + }, + { + config: removeDeprecatedLegacyUrls as Script, + label: 'Sample: Remove deprecated legacy urls', + }, + { + config: addOrReplaceProperty as Script, + label: 'Sample: Add or replace property', + }, + { + config: renameProperty as Script, + label: 'Sample: Rename property', + }, + { + config: addNode as Script, + label: 'Sample: Add node', + }, + { + config: renameNode as Script, + label: 'Sample: Rename node', + }, + { + config: deleteNodes as Script, + label: 'Sample: Delete nodes', + }, ]; diff --git a/src/main/frontend/model/samples/migrate-page-template.json b/src/main/frontend/model/samples/migrate-page-template.json new file mode 100644 index 0000000..08370d1 --- /dev/null +++ b/src/main/frontend/model/samples/migrate-page-template.json @@ -0,0 +1,32 @@ +{ + "logLevel": "info", + "hops": [ + { + "type": "nodeQuery", + "query": "SELECT * FROM [cq:PageContent] AS page WHERE [cq:template] = \"${args.sourceTemplate}\"", + "queryType": "JCR-SQL2", + "hops": [ + { + "type": "setProperty", + "conflict": "force", + "propertyName": "cq:template", + "value": "args.destinationTemplate" + } + ] + } + ], + "parameters": [ + { + "name": "sourceTemplate", + "defaultValue": "/conf/project/settings/wcm/templates/page", + "type": "text", + "evaluation": "STRING" + }, + { + "name": "destinationTemplate", + "defaultValue": "/conf/project/settings/wcm/templates/page-new", + "type": "text", + "evaluation": "STRING" + } + ] +} diff --git a/src/main/frontend/model/samples/migrate-resource-type.json b/src/main/frontend/model/samples/migrate-resource-type.json new file mode 100644 index 0000000..2093abf --- /dev/null +++ b/src/main/frontend/model/samples/migrate-resource-type.json @@ -0,0 +1,32 @@ +{ + "logLevel": "info", + "hops": [ + { + "type": "nodeQuery", + "query": "SELECT * FROM [nt:unstructured] as component WHERE component.[sling:resourceType] = \"${args.sourceResourceType}\"", + "queryType": "JCR-SQL2", + "hops": [ + { + "type": "setProperty", + "conflict": "force", + "propertyName": "sling:resourceType", + "value": "args.destinationResourceType" + } + ] + } + ], + "parameters": [ + { + "name": "destinationResourceType", + "defaultValue": "project/components/content/accordion-new", + "type": "text", + "evaluation": "STRING" + }, + { + "name": "sourceResourceType", + "defaultValue": "project/components/content/accordion", + "type": "text", + "evaluation": "STRING" + } + ] +} diff --git a/src/main/frontend/model/samples/remove-deprecated-legacy-urls.json b/src/main/frontend/model/samples/remove-deprecated-legacy-urls.json new file mode 100644 index 0000000..c39b104 --- /dev/null +++ b/src/main/frontend/model/samples/remove-deprecated-legacy-urls.json @@ -0,0 +1,51 @@ +{ + "logLevel": "info", + "hops": [ + { + "type": "declare", + "declarations": { + "patterns": "[\"%.php%\",\"%.jsp%\"]" + } + }, + { + "type": "each", + "expression": "patterns", + "hops": [ + { + "type": "nodeQuery", + "query": "/jcr:root/content//jcr:content[jcr:like(@legacyURL,'${pattern}')]", + "queryType": "xpath", + "hops": [ + { + "type": "runScript", + "code": "legacyURLArray = jcr:vals(node, \"legacyURL\");\nfilteredLegacyURLArray = [...];", + "extension": "jexl", + "putLocalsBackIntoScope": true + }, + { + "type": "each", + "expression": "legacyURLArray", + "hops": [ + { + "type": "runScript", + "code": "extension = str:remove(pattern, \"%\");\nif(!str:endsWith(url, extension)) {\n filteredLegacyURLArray.add(url);\n}\n\n", + "extension": "jexl", + "putLocalsBackIntoScope": true + } + ], + "iterator": "url" + }, + { + "type": "setProperty", + "conflict": "force", + "propertyName": "legacyURL", + "value": "filteredLegacyURLArray" + } + ] + } + ], + "iterator": "pattern" + } + ], + "parameters": [] +} diff --git a/src/main/frontend/model/samples/rename-node.json b/src/main/frontend/model/samples/rename-node.json new file mode 100644 index 0000000..97ce0ef --- /dev/null +++ b/src/main/frontend/model/samples/rename-node.json @@ -0,0 +1,44 @@ +{ + "logLevel": "info", + "hops": [ + { + "type": "each", + "expression": "['de', 'fr', 'it', 'en']", + "hops": [ + { + "type": "nodeQuery", + "query": "/* The search query has to return the parent nodes we want to act on. */\nSELECT * FROM [nt:unstructured] AS s WHERE ISDESCENDANTNODE([/content/project/${lang}])", + "queryType": "JCR-SQL2", + "hops": [ + { + "type": "childNodes", + "namePattern": "${args.nodeOldName}", + "hops": [ + { + "type": "moveNode", + "conflict": "force", + "newName": "${args.nodeNewName}" + } + ] + } + ] + } + ], + "iterator": "lang" + } + ], + "parameters": [ + { + "name": "nodeOldName", + "defaultValue": "oldName", + "type": "text", + "evaluation": "STRING" + }, + { + "name": "nodeNewName", + "defaultValue": "newName", + "type": "text", + "evaluation": "STRING" + } + ] +} diff --git a/src/main/frontend/model/samples/rename-property.json b/src/main/frontend/model/samples/rename-property.json new file mode 100644 index 0000000..68e10af --- /dev/null +++ b/src/main/frontend/model/samples/rename-property.json @@ -0,0 +1,43 @@ +{ + "logLevel": "info", + "hops": [ + { + "type": "runScript", + "code": "xPathQuery = str:join([\"/jcr:root\", args.path, \"//*[@\", args.sourcePropertyName, \"]\"]);", + "extension": "jexl", + "putLocalsBackIntoScope": true + }, + { + "type": "nodeQuery", + "query": "${xPathQuery}", + "queryType": "xpath", + "hops": [ + { + "type": "renameProperty", + "newName": "${args.destinationPropertyName}", + "propertyName": "${args.sourcePropertyName}" + } + ] + } + ], + "parameters": [ + { + "name": "sourcePropertyName", + "defaultValue": "navTitle", + "type": "text", + "evaluation": "STRING" + }, + { + "name": "destinationPropertyName", + "defaultValue": "navTitle-new", + "type": "text", + "evaluation": "STRING" + }, + { + "name": "path", + "defaultValue": "/content/project/de", + "type": "text", + "evaluation": "STRING" + } + ] +}