View Javadoc
1   /**
2    * This file Copyright (c) 2013-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.ui.framework.setup;
35  
36  import static info.magnolia.jcr.nodebuilder.Ops.*;
37  
38  import info.magnolia.i18nsystem.setup.RemoveHardcodedI18nPropertiesFromDialogsTask;
39  import info.magnolia.jcr.util.NodeTypes;
40  import info.magnolia.module.DefaultModuleVersionHandler;
41  import info.magnolia.module.InstallContext;
42  import info.magnolia.module.delta.ArrayDelegateTask;
43  import info.magnolia.module.delta.BootstrapSingleModuleResource;
44  import info.magnolia.module.delta.BootstrapSingleResource;
45  import info.magnolia.module.delta.ChangeAllPropertiesWithCertainValueTask;
46  import info.magnolia.module.delta.CheckAndModifyPropertyValueTask;
47  import info.magnolia.module.delta.DeltaBuilder;
48  import info.magnolia.module.delta.IsModuleInstalledOrRegistered;
49  import info.magnolia.module.delta.ModuleDependencyBootstrapTask;
50  import info.magnolia.module.delta.MoveNodeTask;
51  import info.magnolia.module.delta.NewPropertyTask;
52  import info.magnolia.module.delta.NodeExistsDelegateTask;
53  import info.magnolia.module.delta.OrderNodeBeforeTask;
54  import info.magnolia.module.delta.RemoveNodeTask;
55  import info.magnolia.module.delta.RenameNodesTask;
56  import info.magnolia.module.delta.SetPropertyTask;
57  import info.magnolia.module.delta.Task;
58  import info.magnolia.module.delta.ValueOfPropertyDelegateTask;
59  import info.magnolia.jcr.nodebuilder.task.ErrorHandling;
60  import info.magnolia.jcr.nodebuilder.task.NodeBuilderTask;
61  import info.magnolia.repository.RepositoryConstants;
62  import info.magnolia.ui.dialog.action.CallbackDialogActionDefinition;
63  import info.magnolia.ui.dialog.setup.migration.CheckBoxRadioControlMigrator;
64  import info.magnolia.ui.dialog.setup.migration.CheckBoxSwitchControlMigrator;
65  import info.magnolia.ui.dialog.setup.migration.ControlMigratorsRegistry;
66  import info.magnolia.ui.dialog.setup.migration.DateControlMigrator;
67  import info.magnolia.ui.dialog.setup.migration.EditCodeControlMigrator;
68  import info.magnolia.ui.dialog.setup.migration.EditControlMigrator;
69  import info.magnolia.ui.dialog.setup.migration.FckEditControlMigrator;
70  import info.magnolia.ui.dialog.setup.migration.FileControlMigrator;
71  import info.magnolia.ui.dialog.setup.migration.HiddenControlMigrator;
72  import info.magnolia.ui.dialog.setup.migration.LinkControlMigrator;
73  import info.magnolia.ui.dialog.setup.migration.MultiSelectControlMigrator;
74  import info.magnolia.ui.dialog.setup.migration.SelectControlMigrator;
75  import info.magnolia.ui.dialog.setup.migration.StaticControlMigrator;
76  import info.magnolia.ui.form.field.definition.BasicTextCodeFieldDefinition;
77  import info.magnolia.ui.form.field.definition.CodeFieldDefinition;
78  import info.magnolia.ui.form.field.definition.CompositeFieldDefinition;
79  import info.magnolia.ui.form.field.definition.MultiValueFieldDefinition;
80  import info.magnolia.ui.form.field.definition.SwitchableFieldDefinition;
81  import info.magnolia.ui.form.field.factory.BasicTextCodeFieldFactory;
82  import info.magnolia.ui.form.field.factory.CompositeFieldFactory;
83  import info.magnolia.ui.form.field.factory.MultiValueFieldFactory;
84  import info.magnolia.ui.form.field.factory.RichTextFieldFactory;
85  import info.magnolia.ui.form.field.factory.SwitchableFieldFactory;
86  import info.magnolia.ui.framework.command.CleanTempFilesCommand;
87  
88  import java.util.ArrayList;
89  import java.util.HashMap;
90  import java.util.List;
91  import java.util.Map;
92  
93  import javax.inject.Inject;
94  
95  /**
96   * Version handler for the Ui framework module.
97   */
98  public class UiFrameworkCompatibilityModuleVersionHandler extends DefaultModuleVersionHandler {
99  
100     private static final String UI_FRAMEWORK_DIALOGS = "/modules/ui-framework/dialogs";
101 
102     private static final String UI_FRAMEWORK_PATH = "/modules/ui-framework";
103 
104     static final Map<String, String> UI_FRAMEWORK_JCR_FIELD_TYPES = new HashMap<String, String>() {{
105         put("optionsField", "optionGroup");
106         put("switchableField", "switchable");
107         put("workbenchField", "workbench");
108         put("basicUploadField", "basicUpload");
109         put("twinColSelectField", "twinColSelect");
110         put("code", "code");
111         put("textField", "text");
112         put("hiddenField", "hidden");
113         put("compositeField", "composite");
114         put("linkFieldSelect", "linkFieldSelection");
115         put("dateField", "date");
116         put("checkBoxField", "checkbox");
117         put("selectField", "select");
118         put("nodeTypeField", "nodeTypeSelect");
119         put("linkField", "link");
120         put("multiField", "multiValue");
121         put("basicTextCodeField", "");
122         put("staticField", "static");
123         put("textArea", "richText");
124         put("passwordField", "password");
125     }};
126 
127     private static final class RenameLegacyI18nNodeIfExistingTask extends IsModuleInstalledOrRegistered {
128         public RenameLegacyI18nNodeIfExistingTask() {
129             super("Rename legacy i18n node", "Renames /server/i18n/authoring as authoringLegacy. Only run if adminInterface legacy module is installed.", "adminInterface", new RenameNodesTask("", "", RepositoryConstants.CONFIG, "/server/i18n", "authoring", "authoringLegacy", NodeTypes.ContentNode.NAME));
130         }
131     }
132 
133     @Inject
134     public UiFrameworkCompatibilityModuleVersionHandler(ControlMigratorsRegistry controlMigratorsRegistry) {
135         // Register control migration task.
136         controlMigratorsRegistry.register("edit", new EditControlMigrator());
137         controlMigratorsRegistry.register("fckEdit", new FckEditControlMigrator());
138         controlMigratorsRegistry.register("date", new DateControlMigrator());
139         controlMigratorsRegistry.register("select", new SelectControlMigrator());
140         controlMigratorsRegistry.register("checkbox", new CheckBoxRadioControlMigrator(true));
141         controlMigratorsRegistry.register("checkboxSwitch", new CheckBoxSwitchControlMigrator());
142         controlMigratorsRegistry.register("radio", new CheckBoxRadioControlMigrator(false));
143         controlMigratorsRegistry.register("uuidLink", new LinkControlMigrator());
144         controlMigratorsRegistry.register("link", new LinkControlMigrator());
145         controlMigratorsRegistry.register("multiselect", new MultiSelectControlMigrator(false));
146         controlMigratorsRegistry.register("file", new FileControlMigrator());
147         controlMigratorsRegistry.register("static", new StaticControlMigrator());
148         controlMigratorsRegistry.register("hidden", new HiddenControlMigrator());
149         controlMigratorsRegistry.register("editCode", new EditCodeControlMigrator());
150 
151         register(DeltaBuilder.update("5.0.1", "")
152                 .addTask(new RenameLegacyI18nNodeIfExistingTask())
153                 .addTask(new RenameNodesTask("Rename 5.0 i18n node", "Renames /server/i18n/authoring50 as authoring.", RepositoryConstants.CONFIG, "/server/i18n", "authoring50", "authoring", NodeTypes.ContentNode.NAME))
154                 .addTask(new BootstrapSingleModuleResource("Add dialogs to ui-framework", "", "config.modules.ui-framework.dialogs.xml")));
155 
156         register(DeltaBuilder.update("5.1", "")
157                 .addTask(new BootstrapSingleResource("Register WorkbenchFieldDefinition", "", "/mgnl-bootstrap/ui-framework-deprecated-fieldtypes/config.modules.ui-framework.fieldTypes.workbenchField.xml"))
158                 .addTask(new RemoveNodeTask("Remove MultiLinkField definition mapping", "", RepositoryConstants.CONFIG, "/modules/ui-framework/fieldTypes/multiLinkField"))
159                 .addTask(createNewFieldDefinition("basicTextCodeField", BasicTextCodeFieldDefinition.class.getName(), BasicTextCodeFieldFactory.class.getName()))
160                 .addTask(createNewFieldDefinition("switchableField", SwitchableFieldDefinition.class.getName(), SwitchableFieldFactory.class.getName()))
161                 .addTask(createNewFieldDefinition("multiField", MultiValueFieldDefinition.class.getName(), MultiValueFieldFactory.class.getName()))
162                 .addTask(createNewFieldDefinition("compositeField", CompositeFieldDefinition.class.getName(), CompositeFieldFactory.class.getName()))
163                 .addTask((new ReplaceMultiLinkFieldDefinitionTask("Change the MultiLinkFieldDefinition by MultiValueFieldDefinition ", "", RepositoryConstants.CONFIG, " select * from [nt:base] as t where contains(t.*,'info.magnolia.ui.form.field.definition.MultiLinkFieldDefinition') ")))
164                 .addTask((new ReplaceSaveModeTypeFieldDefinitionTask("Update field definition sub task from 'saveModeType' to 'transformerClass' ", "", RepositoryConstants.CONFIG, " select * from [nt:base] as t where name(t) = 'saveModeType' ")))
165                 .addTask(new ChangeAllPropertiesWithCertainValueTask("Change package name of CallbackDialogActionDefinition class", "", RepositoryConstants.CONFIG, "info.magnolia.ui.admincentral.dialog.action.CallbackDialogActionDefinition", CallbackDialogActionDefinition.class.getName()))
166                 .addTask((new RemoveHardcodedI18nPropertiesFromDialogsTask("ui-framework"))));
167 
168         register(DeltaBuilder.update("5.2.2", "")
169                 .addTask(new NodeExistsDelegateTask("Register WorkbenchFieldDefinition if not yet done", "", RepositoryConstants.CONFIG, "/modules/ui-framework/fieldTypes/workbenchField", null, new BootstrapSingleResource("Register WorkbenchFieldDefinition", "", "/mgnl-bootstrap/ui-framework-deprecated-fieldtypes/config.modules.ui-framework.fieldTypes.workbenchField.xml")))
170                 .addTask(new NodeExistsDelegateTask("Rename fieldType if it's misspelled", "/modules/ui-framework/fieldTypes/compositField",
171                         new MoveNodeTask("Rename misspelled fieldType", "/modules/ui-framework/fieldTypes/compositField", "/modules/ui-framework/fieldTypes/compositeField", false)
172                         ))
173                 .addTask(new NodeExistsDelegateTask("Rename command catalog if it's incorrect", "Rename command catalog to 'default' if it's incorrect", RepositoryConstants.CONFIG, "/modules/ui-framework/commands/deafult",
174                         new MoveNodeTask("Rename command catalog", "Rename command catalog to 'default'", RepositoryConstants.CONFIG, "/modules/ui-framework/commands/deafult",
175                                 "/modules/ui-framework/commands/default", false)
176                         ))
177                 .addTask(new NodeExistsDelegateTask("Bootstrap 'importZip' command it doesn't exists yet", "Bootstrap 'importZip' command it doesn't exists yet", RepositoryConstants.CONFIG, "/modules/ui-framework/commands/default/importZip", null, new BootstrapSingleModuleResource("Bootstrap 'importZip' command", "Bootstrap 'importZip' command", "config.modules.ui-framework.commands.xml"
178                         )))
179                 .addTask(new NodeExistsDelegateTask("Bootstrap 'importZip' dialog it doesn't exists yet", "Bootstrap 'importZip' dialog it doesn't exists yet", RepositoryConstants.CONFIG, "/modules/ui-framework/dialog/importZip", null,
180                         new BootstrapSingleModuleResource("Bootstrap 'importZip' dialog", "Bootstraps 'importZip' dialog.", "config.modules.ui-framework.dialogs.xml", "dialogs/importZip")))
181                 .addTask(new SetPropertyTask(RepositoryConstants.CONFIG, "/modules/ui-framework/dialogs/importZip/form/tabs/import/fields/encoding/options/utf-8", "label", "UTF-8"))
182                 .addTask(new SetPropertyTask(RepositoryConstants.CONFIG, "/modules/ui-framework/dialogs/importZip/form/tabs/import/fields/encoding/options/windows", "label", "CP437")));
183 
184         register(DeltaBuilder.update("5.3", "")
185                 .addTask(new ArrayDelegateTask("Make dialogs light", "Turns edit node name and edit folder name dialogs into light dialogs.",
186                         new NodeExistsDelegateTask("", "", RepositoryConstants.CONFIG, "/modules/ui-framework/dialogs/rename",
187                                 new NewPropertyTask("", "", RepositoryConstants.CONFIG, "/modules/ui-framework/dialogs/rename", "modalityLevel", "light")),
188                         new NodeExistsDelegateTask("", "", RepositoryConstants.CONFIG, "/modules/ui-framework/dialogs/folder",
189                                 new NewPropertyTask("", "", RepositoryConstants.CONFIG, "/modules/ui-framework/dialogs/folder", "modalityLevel", "light"))
190                         )));
191 
192         register(DeltaBuilder.update("5.4", "")
193                 .addTask(new BootstrapSingleResource("Add new code fieldType", "", "/mgnl-bootstrap/ui-framework-deprecated-fieldtypes/config.modules.ui-framework.fieldTypes.xml", "fieldTypes/code"))
194         );
195 
196         register(DeltaBuilder.update("5.4.2", "")
197                 .addTask(new NodeExistsDelegateTask("Check if path '/modules/ui-framework/dialogs/importZip/form/tabs/import/fields/name' exist.", "/modules/ui-framework/dialogs/importZip/form/tabs/import/fields/name",
198                         new ArrayDelegateTask("",
199                                 new CheckAndModifyPropertyValueTask("Add mimeType application/octet-stream that is used by google chrome for zip files.", "Add mimeType application/octet-stream that is used by google chrome for zip files.", RepositoryConstants.CONFIG, "/modules/ui-framework/dialogs/importZip/form/tabs/import/fields/name", "allowedMimeTypePattern", "application/(zip|x-zip|x-zip-compressed)", "application/(zip|x-zip|x-zip-compressed|octet-stream)")))));
200         register(DeltaBuilder.update("5.4.3", "")
201                 .addTask(new NodeExistsDelegateTask("Configure 'cleanTempFiles' command if does not exists.", "/modules/ui-framework/commands/default/cleanTempFiles", null,
202                         new BootstrapSingleModuleResource("Configure 'cleanTempFiles' command.", "", "config.modules.ui-framework.commands.xml", "commands/default/cleanTempFiles")))
203                 .addTask(new IsModuleInstalledOrRegistered("Configure 'CleanTempFiles' job - check if scheduler module is installed.", "scheduler",
204                         new NodeExistsDelegateTask("Check if 'cleanTempFiles' command was already configured.", "/modules/ui-framework/commands/default/cleanTempFiles",
205                                 new ValueOfPropertyDelegateTask("Check if 'class' property of 'cleanTempFiles' command has required value 'info.magnolia.ui.framework.command.CleanTempFilesCommand'.", "/modules/ui-framework/commands/default/cleanTempFiles", "class", CleanTempFilesCommand.class.getName(), false,
206                                         new NodeExistsDelegateTask("Configure 'CleanTempFiles' job if does not exist.", "/modules/scheduler/config/jobs/cleanTempFiles", null,
207                                                 new BootstrapSingleResource("", "Configure 'CleanTempFiles' job.", "/info/magnolia/module/ui-framework/setup/scheduler/config.modules.scheduler.config.jobs.cleanTempFiles.xml")))))));
208 
209         register(DeltaBuilder.update("5.4.4", "")
210             .addTask(new BootstrapSingleResource("Add JCR node-type selector field", "", "/mgnl-bootstrap/ui-framework-deprecated-fieldtypes/config.modules.ui-framework.fieldTypes.xml", "fieldTypes/nodeTypeField"))
211         );
212 
213         register(DeltaBuilder.update("5.4.8", "")
214                 .addTask(new IsModuleInstalledOrRegistered("Check if dam-app module is installed", "dam-app", (Task)null,
215                             new NodeExistsDelegateTask("Change AssetsEnabledRichTextFieldFactory to RichTextFieldFactory", "/modules/ui-framework/fieldTypes/textArea",
216                                 new CheckAndModifyPropertyValueTask("/modules/ui-framework/fieldTypes/textArea", "factoryClass", "info.magnolia.dam.app.ui.field.factory.AssetsEnabledRichTextFieldFactory", RichTextFieldFactory.class.getName()))))
217                 .addTask(new IsModuleInstalledOrRegistered("Check if form module is installed", "form", (Task)null,
218                             new RemoveNodeTask("Remove formStaticField", "/modules/ui-framework/fieldTypes/formStaticField")))
219         );
220         register(DeltaBuilder.update("5.5", "")
221                 .addTask(new ChangeAllPropertiesWithCertainValueTask(RepositoryConstants.CONFIG, UI_FRAMEWORK_DIALOGS, "info.magnolia.ui.admincentral.dialog.action.SaveDialogActionDefinition", info.magnolia.ui.dialog.action.SaveDialogActionDefinition.class.getName()))
222                 .addTask(new ChangeAllPropertiesWithCertainValueTask(RepositoryConstants.CONFIG, UI_FRAMEWORK_DIALOGS, "info.magnolia.ui.admincentral.dialog.action.CancelDialogActionDefinition", info.magnolia.ui.dialog.action.CancelDialogActionDefinition.class.getName()))
223         );
224 
225         register(DeltaBuilder.update("5.5.4", "")
226                 .addTask(new NodeExistsDelegateTask("Check if 'fields' exists", "/modules/ui-framework/dialogs/importZip/form/tabs/import/fields",
227                         new ArrayDelegateTask("",
228                                 new BootstrapSingleModuleResource("Add 'extractLocation' to 'importZip' dialog's 'fields'", "", "config.modules.ui-framework.dialogs.xml", "/dialogs/importZip/form/tabs/import/fields/extractLocation"),
229                                 new NodeExistsDelegateTask("Check if 'encoding' exists", "", RepositoryConstants.CONFIG, "/modules/ui-framework/dialogs/importZip/form/tabs/import/fields/encoding",
230                                         new OrderNodeBeforeTask("Move 'extractLocation' before 'encoding'", "", RepositoryConstants.CONFIG, "/modules/ui-framework/dialogs/importZip/form/tabs/import/fields/extractLocation", "encoding"))
231                         )))
232         );
233 
234         register(DeltaBuilder.update("5.7", "")
235                 .addTask(new RemoveFieldTypeDefinitionsFromJcrTask(UI_FRAMEWORK_PATH, UI_FRAMEWORK_JCR_FIELD_TYPES))
236                 .addTask(new ChangeAllPropertiesWithCertainValueTask(RepositoryConstants.CONFIG, "/modules", BasicTextCodeFieldDefinition.class.getName(), CodeFieldDefinition.class.getName()))
237         );
238     }
239 
240     @Override
241     protected List<Task> getExtraInstallTasks(InstallContext installContext) {
242         ArrayList<Task> tasks = new ArrayList<Task>();
243         tasks.add(new ModuleDependencyBootstrapTask("scheduler"));
244         return tasks;
245     }
246 
247     /**
248      * Create a new Field Definition.
249      */
250     private NodeBuilderTask createNewFieldDefinition(String fieldName, String definitionClass, String factoryClass) {
251         return new NodeBuilderTask("Add definition for the newly introduce field: " + fieldName, "", ErrorHandling.logging, RepositoryConstants.CONFIG, "/modules/ui-framework",
252                 getNode("fieldTypes").then(
253                         addNode(fieldName, NodeTypes.ContentNode.NAME),
254                         getNode(fieldName).then(
255                                 addProperty("definitionClass", definitionClass),
256                                 addProperty("factoryClass", factoryClass)
257                                 )
258                         ));
259     }
260 }