diff --git a/config/alfresco/messages/patch-service.properties b/config/alfresco/messages/patch-service.properties
index bf73490d1b..1370e1cccb 100644
--- a/config/alfresco/messages/patch-service.properties
+++ b/config/alfresco/messages/patch-service.properties
@@ -82,3 +82,6 @@ patch.systemWorkflowFolder.result.created=Created system workflow container {0}.
patch.rssTemplatesFolder.description=Ensures the existence of the 'RSS Templates' folder.
patch.rssTemplatesFolder.result.exists=The RSS Templates folder already exists: {0}
patch.rssTemplatesFolder.result.created=The RSS Templates folder was successfully created: {0}
+
+patch.uifacetsAspectRemovalPatch.description=Removes the incorrectly applied uifacets aspect from presentation template files.
+patch.uifacetsAspectRemovalPatch.updated=Successfully removed the uifacets aspect from {0} presentation template files.
diff --git a/config/alfresco/patch/patch-services-context.xml b/config/alfresco/patch/patch-services-context.xml
index 20cd126753..17c6e55e8a 100644
--- a/config/alfresco/patch/patch-services-context.xml
+++ b/config/alfresco/patch/patch-services-context.xml
@@ -410,4 +410,19 @@
+
+ * This uses the bootstrap importer to get the paths to look for.
+ *
+ * @author Kevin Roast
+ */
+public class UIFacetsAspectRemovalPatch extends AbstractPatch
+{
+ private static final String MSG_UPDATED = "patch.uifacetsAspectRemovalPatch.updated";
+
+ public static final String PROPERTY_COMPANY_HOME_CHILDNAME = "spaces.company_home.childname";
+ public static final String PROPERTY_DICTIONARY_CHILDNAME = "spaces.dictionary.childname";
+ public static final String PROPERTY_TEMPLATES_CHILDNAME = "spaces.templates.content.childname";
+
+ private ImporterBootstrap importerBootstrap;
+ private MessageSource messageSource;
+
+ protected Properties configuration;
+ protected NodeRef templatesNodeRef;
+
+ public void setImporterBootstrap(ImporterBootstrap importerBootstrap)
+ {
+ this.importerBootstrap = importerBootstrap;
+ }
+
+ public void setMessageSource(MessageSource messageSource)
+ {
+ this.messageSource = messageSource;
+ }
+
+ /**
+ * Ensure that required properties have been set
+ */
+ protected void checkRequiredProperties() throws Exception
+ {
+ checkPropertyNotNull(importerBootstrap, "importerBootstrap");
+ checkPropertyNotNull(messageSource, "messageSource");
+ }
+
+ /**
+ * Extracts pertinent references and properties that are common to execution
+ * of this and derived patches.
+ *
+ * @return the number of updated template files
+ */
+ protected int removeAspectFromTemplates() throws Exception
+ {
+ // get the node store that we must work against
+ StoreRef storeRef = importerBootstrap.getStoreRef();
+ if (storeRef == null)
+ {
+ throw new PatchException("Bootstrap store has not been set");
+ }
+ NodeRef storeRootNodeRef = nodeService.getRootNode(storeRef);
+
+ this.configuration = importerBootstrap.getConfiguration();
+
+ // get the association names that form the path
+ String companyHomeChildName = configuration.getProperty(PROPERTY_COMPANY_HOME_CHILDNAME);
+ if (companyHomeChildName == null || companyHomeChildName.length() == 0)
+ {
+ throw new PatchException("Bootstrap property '" + PROPERTY_COMPANY_HOME_CHILDNAME + "' is not present");
+ }
+ String dictionaryChildName = configuration.getProperty(PROPERTY_DICTIONARY_CHILDNAME);
+ if (dictionaryChildName == null || dictionaryChildName.length() == 0)
+ {
+ throw new PatchException("Bootstrap property '" + PROPERTY_DICTIONARY_CHILDNAME + "' is not present");
+ }
+ String templatesChildName = configuration.getProperty(PROPERTY_TEMPLATES_CHILDNAME);
+ if (templatesChildName == null || templatesChildName.length() == 0)
+ {
+ throw new PatchException("Bootstrap property '" + PROPERTY_TEMPLATES_CHILDNAME + "' is not present");
+ }
+
+ // build the search string to get the email templates node
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("/").append(companyHomeChildName)
+ .append("/").append(dictionaryChildName)
+ .append("/").append(templatesChildName)
+ .append("//*[subtypeOf('cm:content')]");
+ String xpath = sb.toString();
+
+ // get the template content nodes
+ int updated = 0;
+ List