Ajouter un document dans un module se fait en plusieurs étapes :
Pour initialiser la structure du document, utilisez create-document :
intsimoa@srbswebrd:~/aproject$ changedev.php create-document -h Create-document: initialize a document Usage: changedev.php create-document <moduleName> <name>
Nous allons créer le document recipe dans le module recipes :
intsimoa@srbswebrd:~/aproject$ changedev.php create-document recipes recipe == Create document == => Document recipes/recipe initialized. You must now edit /home/intsimoa/aproject/modules/recipes/persistentdocument/recipe.xml and later call add-document
Le fichier de structure du document recette (modules/recipes/persistentdocument/recipe.xml) est maintenant initialisé :
<?xml version="1.0" encoding="utf-8"?> <document xmlns="http://www.rbs.fr/schema/change-document/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.rbs.fr/schema/change-document/1.0 http://www.rbschange.fr/static/schema/change-document/1.0.xsd" model-version="1.0"> <properties> </properties> </document>
Par défaut, tous les documents héritent des propriétés du document generic/Document qui définit entre autres les propriétés :
En plus des propriétés standards, notre document recette aura les propriétés suivantes :
Soit le fichier modules/recipes/persistentdocument/recipe.xml modifié :
<document xmlns="http://www.rbs.fr/schema/change-document/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.rbs.fr/schema/change-document/1.0 http://www.rbschange.fr/static/schema/change-document/1.0.xsd" model-version="1.0"> <properties> <add name="vegetarian" type="Boolean" /> <add name="ingredients" type="XHTMLFragment"/> <add name="peopleNumber" type="Integer"/> <add name="preparation" type="XHTMLFragment"/> <add name="preparationTime" type="Integer"/> <add name="cookingTime" type="Integer"/> <add name="picture" type="modules_media/media" /> <add name="difficulty" type="Integer" from-list="recipes/difficulty"/> <add name="cost" type="Integer" from-list="recipes/cost"/> <add name="categories" type="modules_list/item" from-list="recipes/categories" max-occurs="-1" /> </properties> </document>
Remarquez l’utilisation de l’attribut max-occurs sur la propriété “categories” : valant -1, celui-ci indique que la propriété peut prendre une ou plusieurs valeurs.
Vous avez peut-être remarqué l’utilisation de l’attribut from-list sur les propriétés “difficulty”, “categories” ou “cost”. Cet attribut permet de lier une propriété à une liste du module de base “list”. Le module list centralise la gestion de liste de données.
Nous allons ici créer les listes suivantes :
Ces listes devront être crées à l’initialisation du module, nous allons donc les persister dans le fichier setup/init.xml :
<?xml version="1.0" encoding="UTF-8"?> <script> <binding fileName="modules/list/persistentdocument/import/list_binding.xml" /> <binding fileName="modules/generic/persistentdocument/import/generic_binding.xml" /> <systemfolder module="list" relatedmodule="recipes"> <staticlist listid="recipes/difficulty" label="Difficultés de recette" description="Difficultés de recette"> <staticitem label="&modules.recipes.document.recipe.difficulty.veryeasy;" value="1" /> <staticitem label="&modules.recipes.document.recipe.difficulty.easy;" value="2" /> <staticitem label="&modules.recipes.document.recipe.difficulty.medium;" value="3" /> <staticitem label="&modules.recipes.document.recipe.difficulty.hard;" value="4" /> </staticlist> <staticlist listid="recipes/cost" label="Coûts de recette" description="Coûts de recette"> <staticitem label="&modules.recipes.document.recipe.cost.cheap;" value="1" /> <staticitem label="&modules.recipes.document.recipe.cost.medium;" value="2" /> <staticitem label="&modules.recipes.document.recipe.cost.expensive;" value="3" /> </staticlist> <editablelist listid="recipes/categories" label="Catégories de recette" description="Catégories de recette"> <item label-fr="Plat" label-en="Meal" /> <item label-fr="Entrée" label-en="Appetizer" /> <item label-fr="Dessert" label-en="Dessert" /> <item label-fr="Amuse-gueule" label-en="Appetizers" /> <item label-fr="Boisson" label-en="Drink" /> <item label-fr="Sauce" label-en="Sauce" /> <item label-fr="Accompagnement" label-en="Accompaniment" /> <item label-fr="Confiserie" label-en="Sweetmeat" /> </editablelist> </systemfolder> </script>
Remarquez que listes statiques utilisent pour libellé des messages internationalisés (locales), reconnaissables au pattern &modules.XXX.YYY; (commençant par une esperluette et terminant par un point virgule) que nous définissons dans le fichier locale/document/recipe.xml :
<?xml version="1.0" encoding="utf-8"?> <localization> <!-- Difficulty list items labels --> <entity id="difficulty.veryeasy"> <locale lang="fr">Très facile</locale> <locale lang="en">Very easy</locale> </entity> <entity id="difficulty.easy"> <locale lang="fr">Facile</locale> <locale lang="en">Easy</locale> </entity> <entity id="difficulty.medium"> <locale lang="fr">Moyenne</locale> <locale lang="en">Medium</locale> </entity> <entity id="difficulty.hard"> <locale lang="fr">Difficile</locale> <locale lang="en">Hard</locale> </entity> <!-- Cost list items labels --> <entity id="cost.cheap"> <locale lang="fr">Bon marché</locale> <locale lang="en">Cheap</locale> </entity> <entity id="cost.medium"> <locale lang="fr">Moyen</locale> <locale lang="en">Medium</locale> </entity> <entity id="cost.expensive"> <locale lang="fr">Assez cher</locale> <locale lang="en">Expensive</locale> </entity> </localization>
Des locales ont été ajoutées dans le module recipes, importons les dans la base de données :
intsimoa@srbswebrd:~/aproject$ change.php compile-locales recipes == Compile locales == recipes module locales compiled == Clear webapp cache == Webapp cache directory cleared => Locales successfully compiled
Pour importer le fichier init.xml dans le module, utilisons la commande change import-data :
intsimoa@srbswebrd:~/aproject$ change.php import-data recipes init.xml == Import data recipes/init.xml == => recipes/init.xml imported
Et enfin, pour activer l’importation du fichier init.xml à l’initialisation du module, dé-commentons la bonne ligne dans le fichier setup/initData.php :
<?php /** * @package modules.recipes.setup */ class recipes_Setup extends object_InitDataSetup { public function install() { // Ligne décommentée : $this->executeModuleScript('init.xml'); } /** * @return String[] */ public function getRequiredPackages() { // Return an array of packages name if the data you are inserting in // this file depend on the data of other packages. // Example: // return array('modules_website', 'modules_users'); return array(); } }
Pour l’instant, seule la propriété label, héritée de generic/Document, est obligatoire. Mais que serait donc une recette sans ingrédients ni instructions de préparation ? De même, que voudrait dire un nombre de participant négatif ?
Pour rendre une propriété obligatoire, on agit sur l’attribut min-occurs, valant par défaut 0. Pour appliquer d’autres types de contraintes, on ajoute un élément constraints comme fils de l’élément add et on le renseigne avec des validateurs que l’on configure. Le framework Change fournit un certain nombre de validateurs (Cf. framework/validation/). Les modules peuvent également apporter leur propres validateurs ; ainsi le module media définit le validateur MimetypeValidator.
Nous utilisons ici le validateur MinValidator que nous configurons pour nous assurer que les valeurs des propriétés entières seront positives. Rajoutons également une contrainte max (MaxValidator) sur le nombre de convives pour découvrir comment cumuler des validations sur une même propriété.
Soit le fichier de structure persistentdocument/recipe.xml modifié :
<?xml version="1.0" encoding="utf-8"?> <document xmlns="http://www.rbs.fr/schema/change-document/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.rbs.fr/schema/change-document/1.0 http://www.rbschange.fr/static/schema/change-document/1.0.xsd" model-version="1.0"> <properties> <add name="vegetarian" type="Boolean" /> <add name="ingredients" type="XHTMLFragment" min-occurs="1" /> <add name="peopleNumber" type="Integer" min-occurs="1"> <constraints>min:0;max:100</constraints> </add> <add name="preparation" type="XHTMLFragment" min-occurs="1" /> <add name="preparationTime" type="Integer" min-occurs="1"> <constraints>min:0</constraints> </add> <add name="cookingTime" type="Integer" min-occurs="1"> <constraints>min:0</constraints> </add> <add name="picture" type="modules_media/media" /> <add name="difficulty" type="Integer" from-list="recipes/difficulty" min-occurs="1" /> <add name="cost" type="Integer" from-list="recipes/cost" min-occurs="1"/> <add name="categories" type="modules_list/item" from-list="recipes/categories" max-occurs="-1" /> </properties> </document>
Change permet la gestion multilingue de contenus, en particulier au niveau du document. Un document est multilingue à partir du moment où il possède au moins une propriété dite « localisée ». Ces propriétés devront alors être traduites dans la langue souhaitée.
Pour déclarer une propriété localisée, placez l’attribut localized à “true” sur la propriété concernée dans le fichier de structure.
Pour le document recipe, il paraît raisonnable de traduire les ingrédients (ingredients) et les instructions de préparation (preparation). Soit le fichier de structure persistentdocument/recipe.xml modifié :
<?xml version="1.0" encoding="utf-8"?> <document xmlns="http://www.rbs.fr/schema/change-document/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.rbs.fr/schema/change-document/1.0 http://www.rbschange.fr/static/schema/change-document/1.0.xsd" model-version="1.0" indexable="true"> <properties> ... <add name="ingredients" type="XHTMLFragment" min-occurs="1" localized="true" /> ... </add> <add name="preparation" type="XHTMLFragment" min-occurs="1" localized="true" /> ... </properties> </document>
N.B. : La propriété titre (label) est implicitement déclarée “localisée” pour tous les documents multilingues.
Le traducteur aura ainsi la possibilité de traduire le titre, les ingrédients et les instructions de préparation.
Une fois le fichier de structure correctement renseigné, il faut confirmer la structure du document à l’aide de la commande changedev.php add-document :
intsimoa@srbswebrd:~/aproject$ changedev.php add-document recipes recipe == Add document == Generating /home/intsimoa/aproject/modules/recipes/persistentdocument/recipe.class.php Generating /home/intsimoa/aproject/modules/recipes/persistentdocument/import/RecipeScriptDocumentElement.class.php Updating /home/intsimoa/aproject/modules/recipes/persistentdocument/import/recipes_binding.xml Generating /home/intsimoa/aproject/modules/recipes/locale/document/recipe.xml Generating /home/intsimoa/aproject/modules/recipes/lib/services/RecipeService.class.php Add recipe in /home/intsimoa/aproject/modules/recipes/config/rights.xml compile-locales... done compile-tags... done compile-db-schema... done clear-webapp-cache... done => Document recipe added in module recipes.
Ceci a pour effet de :
⇒ A ce stade, tout est prêt pour permettre la manipulation (par code PHP) de documents recipes/recipe.
Après confirmation de la structure d’un document, le schéma de la base de données permet le stockage des propriétés définies. Ce schéma se retrouve dans les fichiers build/<profil>/modules/<module>/dataobject/*.sql qui sont régénérés à chaque compilation des fichiers de structure (change.php compile-documents).
RBS Change ne gère pas les changements de structure automatiquement après édition manuelle des fichiers de structure. Vous devrez extraire des fichiers SQL générés les instructions nécessaires à l’altération du schéma après édition manuelle du fichier de structure.
La commande changedev.php edit-document vous permet de manipuler les fichiers de structure et le schéma de base de données en une seule opération. De plus, cette commande génère des patchs permettant à vos utilisateurs de mettre à jour correctement leurs projets avec la nouvelle version de votre module :
intsimoa@srbswebrd:~/aproject$ changedev.php edit-document -h Edit-document: edit an existing document Usage: changedev.php edit-document <moduleName> <documentName> <action> Where action in: - add-property <propertyName> <propertyType> - del-property <propertyName> - rename-property <propertyName> <newPropertyName>