XXXVI. Chapitre 36 : Le CMS October▲
On l'attendait tous et il est enfin arrivé, le premier CMS ambitieux basé sur Laravel 4. Il s'appelle October, il est en version bêta, et nous apporte un peu de fraîcheur automnale alors que l'été approche. Je me suis un peu penché dessus et je vous livre le résultat de mon exploration.
XXXVI-A. Installation d'October▲
Ça c'est tout simple, il suffit en premier d'aller sur le site :
La mise en page du site cède à la mode Bootstrap mais elle est claire, lisible et agréable. On a le choix pour aller chercher le code :
J'ai opté pour l'installer. J'ai copié le paquet dans un dossier october sur mon site local. On a des fichiers d'installation :
Il faut lancer install.php, on aboutit sur cette page :
L'installation vérifie que toutes les fonctionnalités sont satisfaisantes pour October. Dans mon cas il n'y a pas de souci, alors je poursuis en acceptant les conditions de la licence (MIT).
L'étape suivante consiste à configurer la base de données qui doit déjà exister (et oui l'installateur ne va pas jusqu'à la créer ) :
Après je me suis fait un peu engueuler parce que je n'avais pas précisé de mot de passe pour l'administrateur, mais on me l'avait pas demandé . Bon j'ai complété :
Ensuite on me demande si je veux ajouter des plugins :
Pour le moment je n'en ajoute pas pour avoir un October de base. Je passe donc cette étape et je clique sur le joli bouton « Install ! ». Puis je laisse faire :
Il suffit de quelques minutes pour que tout soit terminé. J'arrive sur cette page :
Apparemment tout s'est bien déroulé. On me demande de supprimer les fichiers qui ont servi à l'installation (bon, ils auraient pu aussi automatiser cette tâche ). Mon dossier est un peu plus garni maintenant :
L'architecture de base de Laravel a été un peu chamboulée. On se rend compte que tout devient accessible, mais c'est sans doute le prix à payer pour l'automatisation. Il faut faire confiance au .htaccess en place. On dispose encore d'Artisan, mais quand on le lance on trouve aussi quelques changements :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
Laravel Framework version 4.1.29
Usage:
[options] command [arguments]
Options:
--help -h Display this help message.
--quiet -q Do not output any message.
--verbose -v|vv|vvv Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
--version -V Display this application version.
--ansi Force ANSI output.
--no-ansi Disable ANSI output.
--no-interaction -n Do not ask any interactive question.
--env The environment the command should run under.
Available commands:
changes Display the framework change list
clear-compiled Remove the compiled class file
down Put the application into maintenance mode
dump-autoload Regenerate framework autoload files
env Display the current framework environment
help Displays help for a command
list Lists commands
migrate Run the database migrations
optimize Optimize the framework for better performance
routes List all registered routes
serve Serve the application on the PHP development server
tail Tail a log file on a remote server
tinker Interact with your application
up Bring the application out of maintenance mode
asset
asset:publish Publish a package's assets to the public directory
cache
cache:clear Flush the application cache
command
command:make Create a new Artisan command
config
config:publish Publish a package's configuration to the application
controller
controller:make Create a new resourceful controller
create
create:component Creates a new plugin component.
create:controller Creates a new controller.
create:model Creates a new model.
create:plugin Creates a new plugin.
db
db:seed Seed the database with records
key
key:generate Set the application key
migrate
migrate:install Create the migration repository
migrate:make Create a new migration file
migrate:publish Publish a package's migrations to the application
migrate:refresh Reset and re-run all migrations
migrate:reset Rollback all database migrations
migrate:rollback Rollback the last database migration
october
october:down Destroys all database tables for October and all plugins.
october:up Builds database tables for October and all plugins.
october:update Updates October CMS and all plugins, database and files.
plugin
plugin:install Adds a new plugin.
plugin:refresh Removes and re-adds an existing plugin.
plugin:remove Removes an existing plugin.
queue
queue:failed List all of the failed queue jobs
queue:failed-table Create a migration for the failed queue jobs database table
queue:flush Flush all of the failed queue jobs
queue:forget Delete a failed queue job
queue:listen Listen to a given queue
queue:retry Retry a failed queue job
queue:subscribe Subscribe a URL to an Iron.io push queue
queue:work Process the next job on a queue
session
session:table Create a migration for the session database table
view
view:publish Publish a package's views to the application
Le framework est organisé en modules :
On en trouve trois dans l'installation de base. On voit aussi la possibilité d'ajouter des plugins, on en a un de démonstration :
On trouve également un dossier pour les thèmes avec un thème de démonstration :
Un autre dossier est prêt pour les uploads (téléversements) :
XXXVI-B. Le frontend▲
L'URL de base mène sur une page de démonstration :
Là on nous explique dans un anglais impeccable comment est organisé le front-end (interface utilisateur).
XXXVI-B-1. Le layout▲
Un layout est une trame de base pour les pages. Dans la démo on n'en a qu'un :
On peut explorer le code :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
description = "Default layout"
==
<!
DOCTYPE html
>
<html>
<head>
<title>
October CMS - {{
this.page.title }}
</title>
<meta
name
=
"author"
content
=
"October CMS"
>
<meta
name
=
"viewport"
content
=
"width=device-width, initial-scale=1.0"
>
<link
rel
=
"icon"
type
=
"image/png"
href
=
"
{{
'assets/images/october.png'
|
theme }}
"
/>
{%
styles %}
<link
href
=
"
{{
[
'assets/css/theme.css'
]|
theme }}
"
rel
=
"stylesheet"
>
</head>
<body>
<!-- Header -->
<header
id
=
"layout-header"
>
<!-- Nav -->
<nav
id
=
"layout-nav"
class
=
"navbar navbar-inverse navbar-fixed-top"
role
=
"navigation"
>
<div
class
=
"container"
>
<div
class
=
"navbar-header"
>
<button
type
=
"button"
class
=
"navbar-toggle"
data-toggle
=
"collapse"
data-target
=
".navbar-main-collapse"
>
<span
class
=
"sr-only"
>
Toggle navigation</span>
<span
class
=
"icon-bar"
></span>
<span
class
=
"icon-bar"
></span>
<span
class
=
"icon-bar"
></span>
</button>
<a
class
=
"navbar-brand"
href
=
"
{{
'home'
|
page }}
"
>
October Demo</a>
</div>
<div
class
=
"collapse navbar-collapse navbar-main-collapse"
>
<ul
class
=
"nav navbar-nav"
>
<li
class
=
"
{%
if
this.page.id ==
'home'
%}
active
{%
endif
%}
"
><a
href
=
"
{{
'home'
|
page }}
"
>
Basic concepts</a></li>
<li
class
=
"
{%
if
this.page.id ==
'ajax'
%}
active
{%
endif
%}
"
><a
href
=
"
{{
'ajax'
|
page }}
"
>
AJAX framework</a></li>
<li
class
=
"
{%
if
this.page.id ==
'plugins'
%}
active
{%
endif
%}
"
><a
href
=
"
{{
'plugins'
|
page }}
"
>
Plugin components</a></li>
</ul>
</div>
</div>
</nav>
</header>
<!-- Content -->
<section
id
=
"layout-content"
>
{%
page %}
</section>
<!-- Footer -->
<footer
id
=
"layout-footer"
>
{%
partial "footer"
%}
</footer>
<!-- Scripts -->
<script
src
=
"
{{
[
'assets/javascript/jquery.js'
,
'assets/javascript/app.js'
]|
theme }}
"
></script>
{%
framework extras %}
{%
scripts %}
</body>
</html>
October utilise et étend Twig. La variable this contient un objet qui permet par exemple de récupérer l'objet page et ainsi de connaître le titre de cette page :
<title>
October CMS - {{
this.page.title }}
</title>
L'accès aux assets s'effectue ainsi :
<link
rel
=
"icon"
type
=
"image/png"
href
=
"
{{
'assets/images/october.png'
|
theme }}
"
/>
Les assets sont dans le dossier assets du thème, par exemple ici cette image :
Le filtre theme permet de générer correctement l'adresse en référant le thème en cours, par exemple dans mon cas j'obtiens :
<link
rel
=
"icon"
type
=
"image/png"
href
=
"/october/themes/demo/assets/images/october.png"
/>
On trouve la même chose pour le code CSS :
<link
href
=
"
{{
[
'assets/css/theme.css'
]|
theme }}
"
rel
=
"stylesheet"
>
Voilà ce que j'obtiens dans ma page :
<link
href
=
"/october/combine/03ccf956ac57d4075b7d6ef3e803b95d-1400759953"
rel
=
"stylesheet"
>
On trouve le fichier original ici :
Avec cet avertissement :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
/*
*
* !! WARNING !! THIS CSS FILE HAS BEEN AUTOMATICALLY GENERATED !!
*
* Any modifications made to this file will be lost next time it is generated.
* Consider modifying the 'theme.less' file found in the 'less' folder instead
* or create a new custom CSS file to override the rules in this one.
*
* !! YOU HAVE BEEN WARNED !! MODIFY THIS FILE AT YOUR OWN RISK !!
*
*/
Le fichier a été généré à partir de fichiers LESS, on les trouve dans le dossier less :
En creusant un peu on trouve Bootstrap et font-awesome dans le dossier vendor du thème de démo :
On n'est évidemment pas obligé de suivre cette organisation pour nos pages et on peut se contenter de mettre notre CSS dans le dossier.
XXXVI-B-2. Les pages▲
Un site Web est fait de pages. On retrouve ce concept dans October avec les pages. Il y a un dossier dans le thème prévu pour elles :
Pour insérer le contenu d'une page dans le layout il est prévu cette syntaxe :
{%
page %}
C'est donc ici que la page va s'insérer dans le layout.
De quoi est constituée une page ? De code HTML évidemment mais aussi d'éléments de configuration. Si on regarde la page home.htm on trouve ceci :
2.
3.
4.
title = "Demonstration"
url = "/"
layout = "default"
==
On trouve donc le titre de la page, son URL (ici l'URL de base du site), et le nom du layout. Il est assez inattendu de trouver la spécification de l'URL d'une vue dans son code, mais pourquoi pas ?
Si on regarde le menu dans le layout voici la syntaxe pour générer les liens des pages :
<li
class
=
"
{%
if
this.page.id ==
'home'
%}
active
{%
endif
%}
"
><a
href
=
"
{{
'home'
|
page }}
"
>
On utilise le filtre |page et on met le nom de la page, ici home. Dans mon cas ce code est généré :
<li
class
=
"active"
><a
href
=
"http://localhost/october"
>
Basic concepts</a></li>
XXXVI-B-3. Les partials▲
Les partials sont des morceaux de HTML qu'on peut insérer dans des pages. On les trouve dans le dossier partials :
Un bon exemple est le footer :
2.
3.
4.
5.
<div
id
=
"footer"
>
<div
class
=
"container"
>
<p
class
=
"muted credit"
>
© 2013 Alexey Bobkov &
Samuel Georges.</p>
</div>
</div>
On l'insère dans le layout avec cette syntaxe :
2.
3.
4.
<!-- Footer -->
<footer
id
=
"layout-footer"
>
{%
partial "footer"
%}
</footer>
XXXVI-B-4. Les contents blocks▲
Les contents blocks, c'est un peu comme les partials puisque c'est un morceau de page qui peut être inséré n'importe où, mais c'est leur nature qui est différente. Un partial c'est juste du HTML alors qu'un content block peut aussi être du texte ou du code Markdown qui peut être modifié de façon indépendante des pages et des layouts. On les trouve dans le dossier content :
Pour insérer un bloc dans une page c'est facile, voilà par exemple le bloc welcome.html inséré dans la page home.htm :
{%
content "welcome.htm"
%}
XXXVI-B-5. AJAX▲
October inclut un framework pour AJAX qu'on peut utiliser dans les layouts et les pages. Ce framework peut modifier une page avec des partials. Pour l'utiliser il faut le déclarer, par exemple dans le layout :
2.
3.
4.
5.
<script
src
=
"
{{
[
'assets/javascript/jquery.js'
,
'assets/javascript/app.js'
]|
theme }}
"
></script>
{%
framework extras %}
Le framework utilise jQuery, il est donc appelé juste avant.
Il y a une page de démonstration pour ce framework :
C'est une calculette simplifiée. Voilà la déclaration du formulaire :
<form
class
=
"form-inline"
data-request
=
"onTest"
data-request-update
=
"calcresult: '#result'"
>
Le traitement est assuré par la fonction PHP onTest qui a été prévue dans le même fichier. Au retour on envoie le partial calcresult dans l'id #result.
Le framework a l'air d'être assez sophistiqué, en tout cas la documentation est fournie.
XXXVI-C. Le back-end▲
Voyons maintenant le back-end (traitement d'arrière-plan) qu'on atteint avec l'URL backend. On tombe évidemment sur une page d'authentification :
Et là, oh surprise ! on me propose déjà une mise à jour :
Une bonne occasion de voir comment ça se passe… Il faut aller dans le système et les mises à jour :
Quand je clique sur le bouton j'obtiens une fenêtre :
Et la mise à jour se télécharge :
Et je passe à la version 90 :
Bon, je ne sais pas du tout ce qui a été modifié, par contre.
On trouve aussi la gestion des administrateurs :
On peut créer d'autres groupes d'administrateurs et spécifier leurs autorisations. Par contre il ne semble pas y avoir de système d'autorisation pour les utilisateurs.
On peut aussi configurer les paramètres pour l'envoi d'emails :
Dans la partie CMS on a accès aux différents constituants et on peut les modifier, en supprimer, ou en ajouter :
On peut créer des pages, y insérer des partials, des composants, changer l'URL ou la description…
L'éditeur de code est évidemment très sommaire mais convient parfaitement pour des petites modifications. Il y a deux onglets : Markup et Code. Quand du PHP est inséré dans une page, on y accède avec le deuxième onglet.
XXXVI-D. Les plugins▲
Les plugins permettent d'ajouter des fonctionnalités à October. Ils sont donc indispensables pour créer une application. Ils résident dans le dossier plugins :
On voit qu'il y a un plugin de démonstration nommé Todo List. On peut y accéder par le back-end :
Un clic sur le composant ouvre l'inspecteur qui permet de modifier les paramètres :
Et on peut l'expérimenter en front-end :
Il se contente de créer une liste de tâches qu'on entre au clavier. L'insertion dans la page est toute simple :
{%
component 'demoTodo'
%}
Tout le code se trouve dans le dossier des plugins. La documentation explique en détails comment créer un composant. Mais on peut aussi ajouter un plugin existant en allant voir dans le market :
Bon alors je me lance. Comme j'ai déploré le fait de ne pas disposer d'autorisation en front-end je sélectionne un plugin qui propose ça :
Mais je dois commencer par me créer un compte sur le site :
À ce stade on me demande aussi de créer un projet pour simplifier l'installation et la mise à jour des plugins. J'en crée donc un :
Et j'ajoute le plugin User à ce projet :
Il faut ensuite aller récupérer l'ID du projet dans le compte et attacher ce projet à l'installation :
Ensuite il faut attendre que le plugin se charge et s'installe. Je me retrouve alors avec une nouvelle fonctionnalité dans le back-end :
Je peux créer des utilisateurs, le plugin s'est correctement installé ! Je le trouve dans le dossier des plugins :
Le plugin a d'ailleurs l'air d'être plutôt bien fait. Il y a un composant account :
On va voir si ça fonctionne, je crée une page themes/demo/pages/account.htm :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
title = "Account"
url = "/account/:code?"
layout = "default"
[account]
redirect = "home"
paramCode = "code"
==
<div
class
=
"container"
>
{%
component 'account'
%}
</div>
Notez qu'on peut créer cette page directement à partir du back-end.
J'ajoute aussi un bouton dans mon layout :
2.
3.
4.
5.
6.
<div
class
=
"collapse navbar-collapse navbar-main-collapse"
>
<ul
class
=
"nav navbar-nav"
>
...
<li
class
=
"
{%
if
this.page.id ==
'plugins'
%}
active
{%
endif
%}
"
><a
href
=
"
{{
'account'
|
page }}
"
>
Compte</a></li>
</ul>
</div>
Comme ça j'ai un accès dans le menu :
Et voilà la page résultante :
Il y a aussi une page prévue pour l'oubli du mot de passe et dans le back-end on peut régler pas mal de choses. Par contre il n'a pas été prévu la localisation, donc pour passer en français c'est pas évident . Mais je voulais juste voir comment on installe et utilise un plugin.
XXXVI-E. Conclusion▲
Il y aurait encore beaucoup à dire sur ce CMS, par exemple concernant les bases de données ou les outils pour créer des pages en back-end. Tout a été bien pensé et élégamment créé. La seule question que je me pose concerne le public visé par ce CMS. Il me semble se trouver un peu à la frontière entre le spécialiste de Laravel qui pourrait préférer utiliser directement le framework sans prendre la peine de devoir passer par un apprentissage supplémentaire même si le CMS semble assez accessible, et le néophyte qui risque d'être un peu perdu lorsqu'il devra nécessairement mettre les doigts dans le cambouis.
Ce CMS mérite d'être connu et expérimenté. On va voir dans les mois à venir si la bibliothèque de plugins s'enrichit et s'il rencontre un engouement du côté des utilisateurs.