Cet article fait suite au précédent post qui avait pour but de vous initier au CMS Orchard. Vous pouvez le trouver ici
1. Architecture et déclaration du Module/Feature (widget)
1.1. Qu’est-ce qu’un module
Un module est un projet ASP.NET MVC pouvant être généré via un template (Code Generation) et :
- Doit être dans le répertoire Modules d’Orchard pour être détecté – « Convention over configuration »
- Peut contenir plusieurs widgets et/ou services communs à plusieurs modules
- Peut être activé/désactivé via Admin ou CLI
- Notion de dépendance entre modules – activation automatique des dépendances
- Gestion de montée en version – Migrations
1.2. Création d’un nouveau module
Tout d’abord il faut savoir qu’Orchard intègre un terminal qui permet de gérer facilement les paramètres du CMS… [source]
Le terminal est situé ici : ~\MyOrchard\src\Orchard.Web\bin\Orchard.exe
1.2.1. Activer le module CodeGeneration
orchard> feature enable Orchard.CodeGeneration
Enabling features Orchard.CodeGeneration
Code Generation was enabled
1.2.2. Créer son module
orchard> codegen module MyWidget /IncludeInSolution:false
Creating Module MyWidget
Module MyWidget created successfully
- Répertoire MyWidget contenant le projet web du nouveau module ajouté dans MyOrchard\Modules
[
/IncludeInSolution:false
] => Ne pas inclure le projet « MyWidget » dans la solution car cette dernière comporte 77 projets. La solution « Orchard » une fois compilée, ne nécessite plus de l'être à nouveau.
1.2.3. Module manifest
Le fichier Module.txt est utilisé par Orchard pour détecter le module et permet d’activer des dépendances lors de l’activation. [source]
Dans le Dashboard d’Orchard vous devriez maintenant trouver votre module :
2. Un peu d’administration Orchard
2.1. Content Definition
Dans la partie Content Definition du DashBoard vous devriez trouver :
2.2. Création d’une page
2.2.1. Création d’un nouveau content
Ici vous verrez donc la page de garde d’Orchard présente à la racine du site. Vous pouvez donc créer un nouveau « Content ».
2 options :
- Save : sauvegarde la page mais elle reste inaccessible
- Publish now : Sauvegarde + Publication de la page. La page est disponible à l’adresse par défaut à savoir [@racine]/le_nom_de_la_page ; ou bien une adresse personnalisée dans l’option « permalink » (=> rien ne sert de mettre des majuscules, Orchard fera une passe pour tout remettre en minuscule)
2.3. Les layers
Une couche (layer) est un groupe de widgets (avec leur configuration spécifique, qui comprend leur positionnement, zone, nom et ordre) qui est activé par une règle spécifique.
Par exemple, la couche TheHomePage est activée par une règle qui sélectionne spécifiquement la page d'accueil. La couche par défaut est toujours active, peu importe quelle page est affichée. La couche authentifiée est active uniquement lorsque les utilisateurs sont identifiés.
Lorsque plus d'une couche est active sur une page donnée, tous les widgets de toutes ces couches sont affichés au même moment. Orchard les ordonne entre eux en fonction de leur position.
Ajout d’un layer [Add a new Layer…]
- Options
- Les règles de base
Layer | Rule | Description |
Default | true | Always displayed on every page. |
Authenticated | authenticated | Displayed if the user is authenticated |
Anonymous | not authenticated | Displayed if the user is anonymous. |
Disabled | false | Not displayed. This layer is provided as way to save the configuration of widgets that are not currently displayed. |
TheHomepage | url("~/") | Displayed on the home page. |
MyWidgetDemo | url("~/mywidgetdemo" | Displayed the page we’ve just created. |
[source]
2.4. Ajout de notre page dans un menu
Dans le menu navigation, ajoutez un « custom link »
N’oubliez pas de cliquer sur « Save All » pour finir.
2.5. Résultat
Affichage (vide pour le moment) de la page créée :
3. Désinstallation du Module Widget
Une désinstallation complète implique de supprimer les éléments en base de données. En voici la procédure :
- Lancez orchard.exe > package uninstall Orchard.Module.MyModuleName
- Puis ouvrez SQL Server Management Studio et supprimez les éléments associés à votre module de la façon suivante :
Supprimez les lignes correspondantes à votre module et tout sera comme neuf !
4. Injection de dépendance dans Orchard
Orchard utilise Autofac en interne comme DI Container
Il suffit d’implémenter l’interface Orchard.IDependency pour que la classe soit injectable dans une autre classe via son constructeur.
- Il existe d’autres interfaces plus spécifiques
Voir la partie suivante
Une bonne pratique est de créer des classes sous le principe du SRP (Single Responsibility Principle)
- Les classes ont chacune un but précis qui peut être réutilisable dans d’autres classes via injection
Si plusieurs classes implémentent une même interface (par exemple Iinjectable), vous pouvez injecter IEnumerable<IInjectable> (where IInjectable : IDependency) dans le constructeur pour récupérer toutes les instances en même temps.
4.1. Injection avancée
[source]
“The standard way of creating injectable dependencies in Orchard is to create an interface that derives from IDependency or one of its derived interfaces and then to implement that interface. On the consuming side, you can take a parameter of the interface type in your constructor. The application framework will discover all dependencies and will take care of instantiating and injecting instances as needed.
There are three different possible scopes for dependencies, and choosing one is done by deriving from the right interface:
– Request: a dependency instance is created for each new HTTP request and is destroyed once the request has been processed. Use this by deriving your interface from IDependency. The object should be reasonably cheap to create.
– Object: a new instance is created every single time an object takes a dependency on the interface. Instances are never shared. Use this by deriving from ITransientDependency. The objects must be extremely cheap to create.
– Shell: only one instance is created per shell/tenant. Use this by deriving from ISingletonDependency. Only use this for objects that must maintain a common state for the lifetime of the shell.”
4.2. Création d’une dépendance
SOURCE :
SOURCE :
On déclare qu’une instance implémentant l’interface ITextBuilder peut être injectée dans le constructeur d’une autre classe.
4.3. Modification du controller
SOURCE :
Le contrôleur est dépendant d’une abstraction (interface ITextBuilder) et non d’une classe concrète: c’est le paterne d’injection de dépendances.
- On peut ainsi remplacer l’implémentation de TextBuilder dès lors que la nouvelle classe implémente ITextBuilder.
- Cette paterne facilite grandement l’écriture des tests unitaires.
4.4. Refactoring de la vue du widget
Pour l’instant la vue contient un élément html script, contenant du javascript, qui sera dupliqué dans le DOM lors du rendu de plusieurs instances de notre widget sur un layer.
- Le mieux serait de bouger le JavaScript dans son propre fichier et de l’inclure à notre vue de la même façon que jQuery.
- Orchard utilise la notion de Module Resource Manifest pour définir des ressources utilisables dans notre modules ou par d’autres modules (qui serait alors notre module en dépendance dans le module manifest).
4.5. Création du fichier JavaScript widget.js
SOURCE :
On modifie légèrement le javascript pour que le setup du click handler se fasse sur une classe css au lieu d’un id.
On récupère le widget id via l’attribut id.
On récupère le controller url via un attribut data (standard html 5).
La convention est de le placer dans le répertoire Scripts du module.
4.6. Widget.css
SOURCE :
On ajoute un peu de style au label.
- La convention est de le placer dans le répertoire Styles du module
4.7. Création du ModuleRessouceManifest.cs
SOURCE :
On définit un alias pour les fichiers javascript et CSS associés au widget.
On peut voir que widget.js est dépendant de jQuery (un alias défini dans le module resource manifest de Orchard.jQuery).
- La convention est de le placer à la racine du module.
4.8. Modification de la vue
SOURCE :
On utilise les helpers d’Orchard (Script et Style) pour ajouter les scripts associés à l’alias « WidgetAlias » ainsi que leurs dépendances dans la DOM.
- Puisque une dépendance à jQuery est définie pour l’alias dans le resource manifest, le fichier javascript de jquery sera ajouté au header du DOM avant l’ajout du fichier widget.js
- « .AtHead() » spécifie que les fichier javascripts ou CSS doivent être ajoutés au header du DOM.
On ajoute une classe CSS« oc_new_module_widget » pour facilement retrouver tous les widgets dans le DOM
- Utile pour faire un setup commun à tous les widgets du même type
On ajoute un attribut data (html 5 standard) pour stocker l’url vers le controller
4.9. TEST
RECOMPILEZ et rechargez le Pools d’applications
5. Petit +
5.1. Minification des fichiers JavaScript
Installez l’extension Visual Studio Web Essentials [source]
5.2. Liens utiles
Orchard site
- http://orchardproject.net/
- En français mais moins complète: http://www.orchardproject.fr/
Orchard doc
- http://docs.orchardproject.net/
- Basic Orchard Concepts: http://docs.orchardproject.net/Documentation/Basic-Orchard-Concepts
Forums
Tutorials
- http://skywalkersoftwaredevelopment.net/blog/writing-an-orchard-webshop-module-from-scratch-part-1
- http://www.davidhayden.me/tags/orchard-tutorials
- http://skywalkersoftwaredevelopment.net/blog/a-closer-look-at-content-types-drivers-shapes-and-placement
Vidéos de présentation
Orchard Youtube channel(notamment Conférences 2013/2014)
- http://www.youtube.com/channel/UCcEaR8HfGpPwt-GqJr_h5UQ
- http://pluralsight.com/training/Courses/TableOfContents/orchard-fundamentals
- \\ilm01\Commun\RetD1_Projets\2013\13-OPENweb\Learning\Orchard\Videos
- http://docs.orchardproject.net/Documentation/Orchard-TV