View Javadoc
1   /**
2    * This file Copyright (c) 2012-2018 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.module.googlesitemap.setup;
35  
36  import info.magnolia.cms.security.Permission;
37  import info.magnolia.jcr.util.NodeTypes;
38  import info.magnolia.jcr.util.NodeUtil;
39  import info.magnolia.jcr.util.PropertyUtil;
40  import info.magnolia.module.DefaultModuleVersionHandler;
41  import info.magnolia.module.InstallContext;
42  import info.magnolia.module.delta.AddPermissionTask;
43  import info.magnolia.module.delta.ArrayDelegateTask;
44  import info.magnolia.module.delta.BootstrapSingleModuleResource;
45  import info.magnolia.module.delta.BootstrapSingleResource;
46  import info.magnolia.module.delta.BootstrapSingleResourceAndOrderBefore;
47  import info.magnolia.module.delta.CheckAndModifyPartOfPropertyValueTask;
48  import info.magnolia.module.delta.CheckAndModifyPropertyValueTask;
49  import info.magnolia.module.delta.CheckOrCreatePropertyTask;
50  import info.magnolia.module.delta.DeltaBuilder;
51  import info.magnolia.module.delta.NewPropertyTask;
52  import info.magnolia.module.delta.NodeExistsDelegateTask;
53  import info.magnolia.module.delta.NodeVisitorTask;
54  import info.magnolia.module.delta.OrderNodeAfterTask;
55  import info.magnolia.module.delta.OrderNodeBeforeTask;
56  import info.magnolia.module.delta.PartialBootstrapTask;
57  import info.magnolia.module.delta.PropertyExistsDelegateTask;
58  import info.magnolia.module.delta.RemoveNodeTask;
59  import info.magnolia.module.delta.RemovePropertiesTask;
60  import info.magnolia.module.delta.RemovePropertyTask;
61  import info.magnolia.module.delta.SetPropertyTask;
62  import info.magnolia.module.delta.SetupModuleRepositoriesTask;
63  import info.magnolia.module.delta.Task;
64  import info.magnolia.module.googlesitemap.GoogleSiteMapConfiguration;
65  import info.magnolia.module.googlesitemap.app.field.transformer.SiteMapTransformer;
66  import info.magnolia.module.googlesitemap.app.subapp.sitemapdetail.contentviews.formatter.FolderNameColumnFormatter;
67  import info.magnolia.module.googlesitemap.config.mapping.SiteMapVirtualUriMapping;
68  import info.magnolia.module.googlesitemap.setup.for2_1.Register21NodeTypeTask;
69  import info.magnolia.module.googlesitemap.setup.for2_1.RenameSiteMapeSitePagesPropertyName;
70  import info.magnolia.module.googlesitemap.setup.for2_1.UpdatePropertyNamesAndNodeStructure;
71  import info.magnolia.module.googlesitemap.setup.migration.Removei18nKeysInSiteMapMigrationTask;
72  import info.magnolia.module.googlesitemap.setup.migration.SiteMapDefinitionMigrationTask;
73  import info.magnolia.module.googlesitemap.setup.migration.SiteMapDialogMigrationTask;
74  import info.magnolia.repository.RepositoryConstants;
75  import info.magnolia.ui.contentapp.ContentApp;
76  import info.magnolia.ui.contentapp.setup.for5_3.ContentAppMigrationTask;
77  import info.magnolia.ui.framework.setup.AddIsPublishedRuleToAllDeactivateActionsTask;
78  import info.magnolia.ui.framework.setup.SetWritePermissionForActionsTask;
79  import info.magnolia.virtualuri.setup.delta.VirtualUriMappingUpdateTask;
80  
81  import java.util.ArrayList;
82  import java.util.Arrays;
83  import java.util.List;
84  
85  import javax.jcr.Node;
86  import javax.jcr.RepositoryException;
87  
88  import org.apache.commons.lang3.StringUtils;
89  
90  import com.google.common.collect.ImmutableMap;
91  
92  /**
93   * Default version handler.
94   */
95  public class GoogleSiteMapVersionHandler extends DefaultModuleVersionHandler {
96  
97      protected static final String GOOGLESITEMAP_APP_BROWSER_ACTIONS = "/modules/google-sitemap/apps/siteMaps/subApps/browser/actions/";
98      protected static final String GOOGLESITEMAP_APP_PAGES_ACTIONS = "/modules/google-sitemap/apps/siteMaps/subApps/pages/actions/";
99      protected static final String GOOGLESITEMAP_APP_VIRTUALURI_ACTIONS = "/modules/google-sitemap/apps/siteMaps/subApps/virtualURI/actions/";
100 
101     public GoogleSiteMapVersionHandler() {
102         register(DeltaBuilder.update("1.2.1", "")
103                 .addTask(new RemoveNodeTask("Obsolete folder: templates", "Templates folder has to be removed", "config", "/modules/google-sitemap/templates"))
104                 .addTask(new RemoveNodeTask("Obsolete folder: dialog", "Dialogs folder has to be removed", "config", "/modules/google-sitemap/dialogs"))
105                 .addTask(new RemoveNodeTask("Obsolete SiteMap site sample definition", "", "website", "google-sitemap"))
106                 .addTask(new BootstrapSingleModuleResource("SiteMap new Config", "Setup Config", "config.modules.google-sitemap.config.xml"))
107                 .addTask(new BootstrapSingleModuleResource("SiteMap new Template", "Setup Template", "config.modules.google-sitemap.templates.xml")));
108 
109         register(DeltaBuilder.update("2.0", "")
110                 .addTask(new SiteMapDefinitionMigrationTask("Migrate M4.5 site map definition into the new App", "", RepositoryConstants.WEBSITE, "/"))
111                 .addTask(new SiteMapDialogMigrationTask("Migrate M4.5 dialog definition", "Create the new M5 dialog definition. Add actions, tabs and fields definition", "google-sitemap"))
112                 .addTask(new BootstrapSingleResourceAndOrderBefore("Bootstrap tab", "Bootstrap  site map properties tab",
113                         "/mgnl-bootstrap/google-sitemap/dialogs/config.modules.google-sitemap.dialogs.components.content.siteComponentTab.form.tabs.siteMap.xml", "tabSites"))
114                 .addTask(new BootstrapSingleModuleResource("SiteMap app", "Add SiteMap app", "app/config.modules.google-sitemap.apps.xml"))
115                 .addTask(new BootstrapSingleModuleResource("SiteMap app App Launcher", "Add SiteMap app to App Launcher", "app/config.modules.ui-admincentral.config.appLauncherLayout.groups.manage.apps.siteMaps.xml"))
116                 .addTask(new BootstrapSingleModuleResource("Field Types", "Install new field types", "fieldtypes/config.modules.google-sitemap.fieldTypes.xml"))
117                 .addTask(new BootstrapSingleModuleResource("Repository Mapping", "Add Google SiteMap worksapce mapping", "config/config.server.URI2RepositoryMapping.mappings.sitemaps.xml"))
118                 .addTask(new BootstrapSingleResource("Virtual URI Mapping", "Add Google SiteMap virtual URI mapping", "/mgnl-bootstrap-prior-2_5/config.modules.google-sitemap.virtualURIMapping.xml"))
119                 .addTask(new SetupModuleRepositoriesTask())
120                 .addTask(new AddPermissionTask("Anonymous permissions for the new workspace", "", "anonymous", "googleSitemaps", "/", Permission.READ, true))
121 
122                 .addTask(new NewPropertyTask("Add default value transformer", "Set a transformer that display the default field value in case the stored value is null", RepositoryConstants.CONFIG, "/modules/google-sitemap/dialogs/generic/controls/googleSiteMapTab/form/tabs/tabGoogleSitemapProps/fields/googleSitemapPriority", "transformerClass", SiteMapTransformer.class.getName()))
123                 .addTask(new NewPropertyTask("Add default value transformer", "Set a transformer that display the default field value in case the stored value is null", RepositoryConstants.CONFIG, "/modules/google-sitemap/dialogs/generic/controls/googleSiteMapTab/form/tabs/tabGoogleSitemapProps/fields/googleSitemapChangefreq", "transformerClass", SiteMapTransformer.class.getName()))
124                 .addTask(new NewPropertyTask("Add default value transformer", "Set a transformer that display the default field value in case the stored value is null", RepositoryConstants.CONFIG, "/modules/google-sitemap/dialogs/generic/controls/googleVirtualUriMapTab/form/tabs/tabGoogleSitemapProps/fields/googleSitemapPriority", "transformerClass", SiteMapTransformer.class.getName()))
125                 .addTask(new NewPropertyTask("Add default value transformer", "Set a transformer that display the default field value in case the stored value is null", RepositoryConstants.CONFIG, "/modules/google-sitemap/dialogs/generic/controls/googleVirtualUriMapTab/form/tabs/tabGoogleSitemapProps/fields/googleSitemapChangefreq", "transformerClass", SiteMapTransformer.class.getName()))
126 
127                 .addTask(new NodeExistsDelegateTask("Remove area definition from the pages templates", "Remove areas definition in /modules/google-sitemap/templates/pages/siteMapsConfiguration/areas", RepositoryConstants.CONFIG, "/modules/google-sitemap/templates/pages/siteMapsConfiguration/areas",
128                         new RemoveNodeTask("", "", RepositoryConstants.CONFIG, "/modules/google-sitemap/templates/pages/siteMapsConfiguration/areas")))
129                 .addTask(new NodeExistsDelegateTask("Remove components definition from templates", "Remove areas definition in /modules/google-sitemap/templates/components", RepositoryConstants.CONFIG, "/modules/google-sitemap/templates/components",
130                         new RemoveNodeTask("", "", RepositoryConstants.CONFIG, "/modules/google-sitemap/templates/components")))
131 
132                 .addTask(new Removei18nKeysInSiteMapMigrationTask("google-sitemap", "Remove M4.5 i18n support"))
133                 .addTask(new NodeExistsDelegateTask("Reorder Sitemaps in MANAGE group", "This reorders the Sitemaps app before Configuration in the Manage group of the applauncher.", RepositoryConstants.CONFIG, "/modules/ui-admincentral/config/appLauncherLayout/groups/manage/apps/configuration",
134                         new OrderNodeBeforeTask("", "", RepositoryConstants.CONFIG, "/modules/ui-admincentral/config/appLauncherLayout/groups/manage/apps/siteMaps", "configuration")))
135                 .addTask(new CheckAndModifyPropertyValueTask("Set Page template not visible", "", RepositoryConstants.CONFIG, "/modules/google-sitemap/templates/pages/siteMapsConfiguration", "visible", "true", "false")));
136 
137         register(DeltaBuilder.update("2.0.1", "")
138                 .addTask(new RemoveNodeTask("Remove dialog", "Remove obsolete dialog.", RepositoryConstants.CONFIG, "/modules/google-sitemap/dialogs/pages"))
139                 .addTask(new ArrayDelegateTask("Rename property", "Rename property [workspace] to [targetWorkspace].",
140                         new RemovePropertyTask("", "", RepositoryConstants.CONFIG, "/modules/google-sitemap/dialogs/components/content/siteComponentTab/form/tabs/tabSites/fields/sites/field", "workspace"),
141                         new SetPropertyTask("", RepositoryConstants.CONFIG, "/modules/google-sitemap/dialogs/components/content/siteComponentTab/form/tabs/tabSites/fields/sites/field", "targetWorkspace", RepositoryConstants.WEBSITE)))
142                 .addTask(new RemovePropertyTask("Remove unused property", "Remove unused property called identifier.", RepositoryConstants.CONFIG, "/modules/google-sitemap/dialogs/components/content/siteComponentTab/form/tabs/tabSites/fields/sites/field", "identifier"))
143                 .addTask(new RemovePropertyTask("Remove unused property", "Remove unused property called dialog.", RepositoryConstants.CONFIG, "/modules/google-sitemap/templates/pages/siteMapsConfiguration", "dialog"))
144                 .addTask(new RemovePropertyTask("Remove unused property", "Remove unused property called sitemapType.", RepositoryConstants.CONFIG, "/modules/google-sitemap/templates/pages/siteMapsConfiguration", "sitemapType"))
145                 );
146         register(DeltaBuilder.update("2.1", "")
147                 .addTask(new ContentAppMigrationTask("/modules/google-sitemap")));
148 
149         register(DeltaBuilder.update("2.2", "")
150                 .addTask(new Register21NodeTypeTask("Register new nodeType definition", "", GoogleSiteMapConfiguration.WORKSPACE, Arrays.asList(NodeTypes.Page.NAME)))
151                 .addTask(new RenameSiteMapeSitePagesPropertyName("Rename Sitemap Website properties", "", RepositoryConstants.WEBSITE))
152                 .addTask(new UpdatePropertyNamesAndNodeStructure("Rename Sitemap properties", ""))
153                 .addTask(new NodeExistsDelegateTask("Bootstrap new siteMap dialogs definition", "", RepositoryConstants.CONFIG, "/modules/google-sitemap/dialogs/components/content/siteComponentTab/form/tabs/siteMap",
154                         new ArrayDelegateTask("",
155                                 new RemoveNodeTask("", "/modules/google-sitemap/dialogs/components/content/siteComponentTab/form/tabs/siteMap"),
156                                 new BootstrapSingleModuleResource("", "", "dialogs/config.modules.google-sitemap.dialogs.components.content.siteComponentTab.form.tabs.siteMap.xml")
157                                 )))
158                 .addTask(new NodeExistsDelegateTask("Bootstrap new tabSites dialogs definition", "", RepositoryConstants.CONFIG, "/modules/google-sitemap/dialogs/components/content/siteComponentTab/form/tabs/tabSites",
159                         new ArrayDelegateTask("",
160                                 new RemoveNodeTask("", "/modules/google-sitemap/dialogs/components/content/siteComponentTab/form/tabs/tabSites"),
161                                 new BootstrapSingleModuleResource("", "", "dialogs/config.modules.google-sitemap.dialogs.components.content.siteComponentTab.form.tabs.tabSites.xml")
162                                 )))
163                 .addTask(new NodeExistsDelegateTask("Bootstrap new generic dialogs definition", "", RepositoryConstants.CONFIG, "/modules/google-sitemap/dialogs/generic",
164                         new ArrayDelegateTask("",
165                                 new RemoveNodeTask("", "/modules/google-sitemap/dialogs/generic"),
166                                 new BootstrapSingleModuleResource("", "", "dialogs/config.modules.google-sitemap.dialogs.generic.xml")
167                                 )))
168                 .addTask(new BootstrapSingleModuleResource("Bootstrap new tabDefaultValue dialogs definition", "", "dialogs/config.modules.google-sitemap.dialogs.components.content.siteComponentTab.form.tabs.tabDefaultValue.xml"))
169                 .addTask(new OrderNodeAfterTask("order tabs", "/modules/google-sitemap/dialogs/components/content/siteComponentTab/form/tabs/tabSites", "siteMap"))
170                 .addTask(new OrderNodeAfterTask("order tabs", "/modules/google-sitemap/dialogs/components/content/siteComponentTab/form/tabs/tabDefaultValue", "tabSites"))
171                 .addTask(new CheckAndModifyPropertyValueTask("/modules/google-sitemap/apps/siteMaps/subApps/browser/workbench/contentViews/list/columns/name", "propertyName", "displayName", "mgnl:googleSiteMapDisplayName"))
172                 .addTask(new CheckAndModifyPropertyValueTask("/modules/google-sitemap/apps/siteMaps/subApps/browser/workbench/contentViews/list/columns/name", "formatterClass", "info.magnolia.module.googlesitemap.app.subapp.sitemapdetail.formatter.FolderNameColumnFormatter", FolderNameColumnFormatter.class.getName()))
173                 .addTask(new CheckAndModifyPropertyValueTask("/modules/google-sitemap/apps/siteMaps", "appClass", "info.magnolia.module.googlesitemap.app.GoogleSiteMapApp", ContentApp.class.getName()))
174 
175                 .addTask(new NodeExistsDelegateTask("Bootstrap new sub app Pages definition", "", RepositoryConstants.CONFIG, "/modules/google-sitemap/apps/siteMaps/subApps/pages",
176                         new ArrayDelegateTask("",
177                                 new RemoveNodeTask("", "/modules/google-sitemap/apps/siteMaps/subApps/pages"),
178                                 new PartialBootstrapTask("", "/mgnl-bootstrap/google-sitemap/app/config.modules.google-sitemap.apps.xml", "/apps/siteMaps/subApps/pages"),
179                                 new OrderNodeAfterTask("order tabs", "/modules/google-sitemap/apps/siteMaps/subApps/pages", "browser")
180                                 )))
181 
182                 .addTask(new NodeExistsDelegateTask("Bootstrap new sub app VirtualUri definition", "", RepositoryConstants.CONFIG, "/modules/google-sitemap/apps/siteMaps/subApps/virtualURI",
183                         new ArrayDelegateTask("",
184                                 new RemoveNodeTask("", "/modules/google-sitemap/apps/siteMaps/subApps/virtualURI"),
185                                 new PartialBootstrapTask("", "/mgnl-bootstrap/google-sitemap/app/config.modules.google-sitemap.apps.xml", "/apps/siteMaps/subApps/virtualURI"),
186                                 new OrderNodeAfterTask("order tabs", "/modules/google-sitemap/apps/siteMaps/subApps/virtualURI", "pages")
187                                 )))
188                 .addTask(new SetWritePermissionForActionsTask(GOOGLESITEMAP_APP_BROWSER_ACTIONS, new String[]{"addFolder", "editFolder", "addSiteMap", "delete", "editSiteMap", "import", "restorePreviousVersion", "confirmDeleteSiteMap", "editSiteEntries", "editVirtualUris", "activate", "deactivate", "activateDeleted"}))
189                 .addTask(new SetWritePermissionForActionsTask(GOOGLESITEMAP_APP_PAGES_ACTIONS, new String[]{"editSitemapEntry"}))
190                 .addTask(new SetWritePermissionForActionsTask(GOOGLESITEMAP_APP_VIRTUALURI_ACTIONS, new String[]{"editSitemapEntry"}))
191                 .addTask(new BootstrapSingleModuleResource("Bootstrap new config values", "", "config.modules.google-sitemap.config.xml"))
192                 .addTask(new PartialBootstrapTask("", "/mgnl-bootstrap/google-sitemap/fieldtypes/config.modules.google-sitemap.fieldTypes.xml", "/fieldTypes/siteMapSelect")));
193 
194         register(DeltaBuilder.update("2.2.2", "")
195                 .addTask(new AddIsPublishedRuleToAllDeactivateActionsTask("", "/modules/google-sitemap/apps/"))
196                 );
197 
198         register(DeltaBuilder.update("2.2.3", "")
199                 .addTask(new PropertyExistsDelegateTask("Add property catalog to deactivate action if not existing", "", RepositoryConstants.CONFIG, "/modules/google-sitemap/apps/siteMaps/subApps/browser/actions/deactivate", "catalog", null,
200                         new NewPropertyTask("", "", RepositoryConstants.CONFIG, "/modules/google-sitemap/apps/siteMaps/subApps/browser/actions/deactivate", "catalog", "website")))
201                 );
202 
203         register(DeltaBuilder.update("2.3.3", "")
204                 .addTask(new RemovePropertyTask("Remove unnecessary 'hidden' property", "/modules/google-sitemap/dialogs/components/content/siteComponentTab/form/tabs/siteMap/fields/template", "hidden"))
205                 .addTask(new NodeVisitorTask("Update all broken 'mgnl:template' properties",
206                         "Sitemaps with property 'mgnl:template' set to 'GoogleSiteMap' will be updated to 'google-sitemap:pages/siteMapsConfiguration'",
207                         GoogleSiteMapConfiguration.WORKSPACE, "/") {
208                     @Override
209                     protected boolean nodeMatches(Node node) {
210                         return !StringUtils.startsWith(NodeUtil.getPathIfPossible(node), "/jcr:system") &&
211                                 StringUtils.equals(PropertyUtil.getString(node, NodeTypes.Renderable.TEMPLATE), "GoogleSiteMap");
212                     }
213 
214                     @Override
215                     protected void operateOnNode(InstallContext installContext, Node node) {
216                         try {
217                             node.setProperty(NodeTypes.Renderable.TEMPLATE, "google-sitemap:pages/siteMapsConfiguration");
218                         } catch (RepositoryException e) {
219                             installContext.error(String.format("Error updating '%s' property of node '%s'", NodeTypes.Renderable.TEMPLATE, NodeUtil.getPathIfPossible(node)), e);
220                         }
221                     }
222                 })
223                 );
224 
225         register(DeltaBuilder.update("2.3.4", "")
226                 .addTask(new BootstrapSingleModuleResource("Sitemap dialog main tab", "Make 'standard' the default sitemap type",
227                         "dialogs/config.modules.google-sitemap.dialogs.components.content.siteComponentTab.form.tabs.siteMap.xml"))
228                 .addTask(new BootstrapSingleModuleResource("Add sitemap renderer", "This one sets the correct content type 'application/xml'", "config.modules.google-sitemap.renderers.sitemap.xml"))
229                 .addTask(new CheckAndModifyPropertyValueTask("Update siteMap template to use sitemap renderer", "This will make sure the correct content type is set", "config", "/modules/google-sitemap/templates/pages/siteMapsConfiguration", "renderType", "freemarker", "sitemap"))
230                 );
231 
232         register(DeltaBuilder.update("2.4.1", "")
233                 .addTask(new ArrayDelegateTask("Remove legacy properties",
234                         new RemovePropertiesTask("", RepositoryConstants.CONFIG, Arrays.asList(
235                                 "/modules/google-sitemap/apps/siteMaps/subApps/browser/actions/export/extends",
236                                 "/modules/google-sitemap/apps/siteMaps/subApps/browser/actions/editSiteMap/nodeType",
237                                 "/modules/google-sitemap/dialogs/components/content/siteComponentTab/form/tabs/tabSites/fields/mgnl:googleSiteMapPages/chooseOnClick"), false),
238                         new CheckOrCreatePropertyTask("", "/modules/google-sitemap/apps/siteMaps/subApps/browser/actions/export", "icon", "icon-export"),
239                         // replace colons with dashes in fields' node names and add new name property instead.
240                         new NodeVisitorTask("", "", RepositoryConstants.CONFIG, "/modules/google-sitemap/dialogs/components/content/siteComponentTab/form/tabs") {
241                     @Override
242                     protected boolean nodeMatches(Node node) {
243                         return StringUtils.startsWith(NodeUtil.getName(node), "mgnl:");
244                     }
245 
246                     @Override
247                     protected void operateOnNode(InstallContext installContext, Node node) {
248                         try {
249                             node.setProperty("name", node.getName());
250                             NodeUtil.renameNode(node, node.getName().replaceAll(":", "-"));
251                         } catch (RepositoryException e) {
252                             installContext.error(String.format("Error updating '%s' property of node '%s'", NodeTypes.Renderable.TEMPLATE, NodeUtil.getPathIfPossible(node)), e);
253                         }
254                     }
255                 }))
256                 );
257         register(DeltaBuilder.update("2.4.2", "")
258                 .addTask(new NodeExistsDelegateTask("Change URI to repository mapping to end with slash", "", RepositoryConstants.CONFIG, "/server/URI2RepositoryMapping/mappings/sitemaps",
259                         new CheckAndModifyPartOfPropertyValueTask("", "", RepositoryConstants.CONFIG, "/server/URI2RepositoryMapping/mappings/sitemaps", "URIPrefix", "/sitemaps", "/sitemaps/"))));
260         register(DeltaBuilder.update("2.4.3", "")
261                 .addTask(new NodeExistsDelegateTask("Show edit icon on tab of pages sub app", "", RepositoryConstants.CONFIG, "/modules/google-sitemap/apps/siteMaps/subApps/pages",
262                         new SetPropertyTask("Set icon for pages sub app", RepositoryConstants.CONFIG, "/modules/google-sitemap/apps/siteMaps/subApps/pages", "icon", "icon-edit")))
263                 .addTask(new NodeExistsDelegateTask("Show edit icon on tab of virtual uri sub app", "", RepositoryConstants.CONFIG, "/modules/google-sitemap/apps/siteMaps/subApps/virtualURI",
264                         new SetPropertyTask("Set icon for virtual uri sub app", RepositoryConstants.CONFIG, "/modules/google-sitemap/apps/siteMaps/subApps/virtualURI", "icon", "icon-edit"))));
265         register(DeltaBuilder.update("2.5", "")
266                 .addTask(new VirtualUriMappingUpdateTask("Update virtualUriMappings", "google-sitemap", ImmutableMap.of(
267                         "info.magnolia.module.googlesitemap.config.SiteMapVirtualUriMapping", SiteMapVirtualUriMapping.class))));
268         register(DeltaBuilder.update("2.5.1", "")
269                 .addTask(new RemovePropertyTask("Remove deprecated i18nBasename property", "/modules/google-sitemap/templates/pages/siteMapsConfiguration", "i18nBasename"))
270         );
271     }
272 
273     /**
274      * Export the FTL to the Resource folder menu from the Admin central.
275      */
276     @Override
277     protected List<Task> getExtraInstallTasks(InstallContext ctx) {
278         final List<Task> tasks = new ArrayList<Task>();
279         tasks.add(new AddPermissionTask("Anonymous permissions for the new workspace", "", "anonymous", "googleSitemaps", "/", Permission.READ, true));
280         tasks.add(new NodeExistsDelegateTask("Reorder Sitemaps in MANAGE group", "This reorders the Sitemaps app before Configuration in the Manage group of the applauncher.", RepositoryConstants.CONFIG, "/modules/ui-admincentral/config/appLauncherLayout/groups/manage/apps/configuration",
281                 new OrderNodeBeforeTask("", "", RepositoryConstants.CONFIG, "/modules/ui-admincentral/config/appLauncherLayout/groups/manage/apps/siteMaps", "configuration")));
282         tasks.add(new Register21NodeTypeTask("Register new nodeType definition", "", GoogleSiteMapConfiguration.WORKSPACE, Arrays.asList(NodeTypes.Page.NAME)));
283         return tasks;
284     }
285 }