Certains des exemples que nous fournissons ci-dessous ne sont pas complets. D'emblée, nous nous en excusons, bien sûr. Mais pourquoi diable sont-ils incomplets ?
Ils sont incomplets parce que nous y travaillons en ce moment et que plutôt que de vous faire patienter jusqu'à ce qu'ils soient tous terminés, nous avons préféré vous les livrer dans l'état où ils se trouvent pour que vous puissiez vous faire une idée de ce qu'ils illustrent.
Au fur et à mesure de notre avancement, nous ferons les mises à jour idoines. Nous espérons résorber notre retard au plus vite.
LSApplication
2013-06-17LSExplorer
2013-06-16LSContentsW3C
2013-06-14prefetch
et prerender
2013-06-10LSContentsSiteManager
et
LSSiteManager
2013-05-07LSVaesoli
: Activation des
statistiques d'accès 2013-05-07title
, le paramètre heading
, le paramètre text
, le paramètre xsl
, LSRegionSubtag, Language Switchers, LSFormEnroll, LSContentsLegal, sitemap, substitution de propriétés, LSSourceFile et LSContentsSourceFile, LSContentsComments, LSContentsCharter, ... (05/11/2013)onload
et onunload
d'une page, Page settings, ... (22/09/2013)LSApplication
2013-06-17Depuis l'opus "5.4.0000"
C'est une grande évolution de Vae Soli! et elle justifie le fait de passer à
une version mineure supérieure, l'opus 5.4.0000
. Jusquà cette
nouvelle version, Vae Soli! pouvait certes générer le code nécessaire à des
interactions Ajax mais Vae Soli! ne traitait pas les requêtes Ajax faites au
serveur ! En d'autres termes, on initiait les demandes Ajax au départ
de Vae Soli! (une fois le code rapatrié dans le navigateur du visiteur) mais
on ne traitait pas les demandes sur le serveur. Cela, c'était laissé à
l'initiative du développeur qui devait lui-même réaliser le code qu'il
déposait à l'endroit qui lui convenait sur son serveur web.
À présent, Vae Soli! initie non seulement les demandes mais peut également fournir les réponses. C'est une avancée significative dans le code de notre framework.
Trois traitements de requêtes génériques ont été implémentés :
Le mécanisme mis en place laisse la porte ouverte à des implémentations inconnues de Vae Soli!. Si par exemple vous avez envie de gérer des interactions avec un module dont Vae Soli! ne connaît rien, vous pouvez indiquer à Vae Soli! que vous allez fournir le code qui sera nécessaire à son traitement, Vae Soli! le charge et l'exécute … à charge pour vous de respecter évidemment le protocole mis au point.
Mais au fond, comment ça marche ?
Tout d'abord imaginons que vous souhaitiez envoyer une requête au serveur
avec l'URL /ajax.php
(à ce stade, peu nous importe
la requête, ses paramètres, …). Sur votre serveur, si vous souhaitez
que Vae Soli! prenne cette requête en charge, vous allez devoir créer le
script /ajax.php
d'une manière bien précise. En
voici un exemple concret (et réel) :
/ajax.php --------- <?php global $__LS_IsAjax; $__LS_IsAjax = true; include( '../master.php' ); ?>
Comme vous le voyez, une variable globale est créée
($__LS_IsAjax
) et c'est cette variable globale qui sera
interrogée pour savoir si la demande concerne une requête Ajax ou non. Pour
le reste, comme pour tous les autres scripts, nous ne faisons qu'inclure le
source /../master.php
. Passons donc au /../master.php
… pour qui TOUT est inchangé
(c'était une contrainte forte de développement afin de garantir la
compatibilité ascendante de Vae Soli!) :
/../master.php -------------- <?php $szRoot = $_SERVER['DOCUMENT_ROOT']; /* Root of the site */ $szVaesoliDir = $szRoot . '/vaesoli'; /* Default Vae Soli! directory */ if ( is_dir( $szVaesoliDir ) ) /* If Vae Soli! path found */ { /* File that contains the Foundation classes */ $szFoundationClassesFile = $szVaesoliDir . '/include/LSVfc.class.php'; if ( file_exists( $szFoundationClassesFile ) ) /* If Foundation classes found */ { require_once( $szFoundationClassesFile ); /* Require these classes ONCE for all */ global $oApp; /* This makes the application a GLOBAL variable */ $szGeoramaFile = $szRoot . '/../cms/georama.xml'; /* Georama file (physical file name */ /* Create the LSApplication object */ $oApp = new LSApplication( $szRoot , /* Root of the site */ $szGeoramaFile , /* Georama of the site */ null , /* Verb */ false ); /* Do not create georama if NOT found */ $oApp->szVaesoliPath = $szVaesoliDir; /* So that LSApplication knows where Vae Soli! is installed ... relative to current site */ $oApp->Run(); /* Run application now */ } /* if ( file_exists( $szFoundationClassesFile ) ) */ } /* if ( is_dir( $szVaesoliDir ) ) */ else /* Else of ... if ( is_dir( $szVaesoliDir ) ) */ { echo "<p>Vae Soli! path NOT found</p>\n"; } /* End of ... Else of ... if ( is_dir( $szVaesoliDir ) ) */ ?>
Il est important que vous notiez plusieurs éléments à ce stade :
/../master.php
est en-dehors
de la root du site pour des questions de sécuritéLSApplication
est crééLSApplication->Run()
est appelée pour tous les scripts (Ajax ne change pas la donne)LSApplication
créé est connu sous le nom d'une variable gloabale $oApp
C'est donc dans la méthode Run()
de l'objet
LSApplication
que se fait le distinguo entre scripts de page et
scripts Ajax, sur base de la variable globale $__LS_IsAjax
!
Voyons donc dans le code de LSApplication
comment et où le
fameux distinguo est réalisé. Le tout se passe dans la méthode
Run()
comme indiqué au-dessus :
/* The __LS_IsAjax global is defined in the script to indicate that Ajax should be played back .. for example in a file that's called ajax.php */ if ( ! isset( $GLOBALS[ '__LS_IsAjax' ] ) || ! $GLOBALS[ '__LS_IsAjax' ] ) { /* DO AS USUAL */ } /* if ( ! isset( $GLOBALS[ '__LS_IsAjax' ] ) || ! $GLOBALS[ '__LS_IsAjax' ] ) */ else /* Else of ... if ( ! isset( $GLOBALS[ '__LS_IsAjax' ] ) || ! $GLOBALS[ '__LS_IsAjax' ] ) */ { $this->AjaxRun(); /* Run application as Ajax */ } /* End of ... Else of ... if ( ! isset( $GLOBALS[ '__LS_IsAjax' ] ) || ! $GLOBALS[ '__LS_IsAjax' ] ) */
Afin de simplifier l'exemple, nous avons substitué le /* DO AS USUAL
*/ au code qui s'occupe habituellement du traitement d'une page
traditionnelle et comme vous le voyez nous ne faisons qu'implémenter la
nouvelle méthode AjaxRun()
de l'objet
LSApplication
pour les appels Ajax … ce qui nous
garantit une parfaite ségrégation (encapsulation) favorisant ainsi la
rétro-compatibilité annoncée comme exigence forte. Il faut donc maintenant
se diriger vers une nouvelle méthode pour y découvrir le Graal de notre
gestion Ajax. Et bien, le Graal n'est pas encore à notre portée car nous
avons voulu établir une frontière forte entre l'objet LSApplication
et toute gestion Ajax. la méthode AjaxRun()
fera donc appel
à une nouvelle classe de Vae Soli!, la classe LSAjax
:
function AjaxRun() /*--------------*/ { $oAjax = new LSAjax( $this ); /* Create a new Ajax object (and pass it the LSApplication instance) */ $oAjax->Run(); /* Run it */ } /* End of method LSApplication.AjaxRun() ============================ */
… l'objet LSApplication
est lui-même passé au
constructeur de la classe LSAjax
. Puis … on demande un
Run()
! Dès lors, on se tourne maintenant vers la classe
LSAjax
.
Pour faire court, la méthode Run()
de LSAjax
se
contente d'extraire des paramètres passés avec l'URL (query string), puis
effectue un traitement sur base des paramètres en question, constitue une
réponse en XML et se charge de renvoyer la réponse en XML. Point à la
ligne. Il n'entre pas dans le cadre de cette petite niouze de voir le
détail des paramètres envoyés, ni de connaître le format exact de la réponse
XML renvoyée. Par contre, ce qui est intéressant c'est de savoir comment
Vae Soli! s'accomode d'appliquer le traitement qui convient à la requête.
Rien de plus simple ! Un des paramètres envoyés via la requête Ajax est
le nom du module concerné. Prenez ce nom de module au sens large, et mettez-le
à votre sauce personnelle si tel est votre besoin. De notre côté nous
avons réservé tous les noms de modules qui commençaient par ls-
:
ls-file-explorer
, ls-site-manager
,
ls-file-uploader
, …
Dans la méthode TreatRequest()
de l'objet LSAjax
,
le nom du module est utilisé pour charger le script nécessaire au
traitement. C'est ainsi que nous avons créé un source LSAjax.class.ls-file-explorer.php
, un autre appelé LSAjax.class.ls-file-uploader.php
, et un autre encore
LSAjax.class.ls-site-manager.php
. C'est dans ces
fichiers que se trouve le code nécessaire au traitement de toutes les
interactions Ajax indispensables à ces trois modules (qui partagent
d'ailleurs une intimité assez forte puisque le Site Manager fait appel au
File Explorer qui lui-même fait appel au File Uploader).
Les fichiers en question sont cherchés dans la root de Vae Soli! ou dans le
répertoire où les plugins sont déposés. Bientôt, nous chercherons également
le module dans un répertoire (ou une série de répertoires) paramétrable.
Quoi qu'il en soit, ceci garantit donc que tout nouveau module, y compris
les vôtres, peuvent être pris en compte sans changer quoi que ce soit à
l'architecture choisie. Si vous souhaitez créer une interaction pour un
module de facturation par exemple, rien ne vous empêche de créer le fichier
LSAjax.class.me-invoicing.php
, de respecter le
protocole d'échange entre votre code et Vae Soli! et le tour est joué !
C'est donc un choix particulièrement flexible qui s'accommode assez bien du
slogan OSF [1] .
Il est temps maintenant de voir dans le détail comment cela se fait.
Pour l'instant, les paramètres sont tous envoyés sous forme de GET. Plus
loin, nous verrons que dans certains cas vous pouvez aussi les attendre en
POST. Le début de la méthode Run()
se charge de l'extraction
des paramètres :
$iArgCount = count( $_GET ); /* Number of parameters sent in the URL */ $szDomain = isset( $_GET['domain'] ) ? trim( $_GET['domain'] ) : ''; /* Domain name we're busy with */ $szModule = isset( $_GET['module'] ) ? trim( $_GET['module'] ) : ''; /* Module we're in ('site-manager') */ $szAction = isset( $_GET['action'] ) ? trim( $_GET['action'] ) : ''; /* Action to be carried on */ $szLang = isset( $_GET['lang' ] ) ? $_GET['lang' ] : 'fr';/* Language of the the request */ $szID1 = isset( $_GET['id1' ] ) ? $_GET['id1' ] : ''; /* Main ID */ $szID2 = isset( $_GET['id2' ] ) ? $_GET['id2' ] : ''; /* Secondary ID */ $szID3 = isset( $_GET['id3' ] ) ? $_GET['id3' ] : ''; /* Ternary ID */ $iRetCode = RET_CODE_SERVICE_UNAVAILABLE; /* Default return code */ $szMsg = 'Service unavailable'; /* Default message */ $aErrors = array(); /* Some errors */ $szPayload = ''; /* Payload in XML format */ $szCargo = ''; /* Additional data ... specific to each request */ $szCargo2 = ''; /* Additional data ... specific to each request */ $szCargo3 = ''; /* Additional data ... specific to each request */
Ensuite la méthode Run()
invoque la méthode TreatRequest()
:
$this->TreatRequest( $szDomain, $szModule, $szAction, $szLang, $szID1,$szID2,$szID3, $szPayload, $iRetCode, $szMsg, $szCargo,$szCargo2,$szCargo3 );
… qui reçoit tous ces paramètres sous forme de références de telle
sorte qu'il lui soit possible de modifier la valeur desdits paramètres après
avoir effectué son travail. Une fois son travail effectué, il suffira de
constituer la réponse (en XML) et de la renvoyer au navigateur du
visiteur. Mais nous n'en sommes pas encore là ! Que fait donc la
fameuse méthode TreatRequest()
? C'est simple puisqu'elle
se contente d'inclure le code de traitement qui convient à chaque module.
Voilà ce qu'elle fait…
01 ... $szFile = FIL_AddBS( str_replace( '\\','/',VAESOLI_PLUGINS ),'/' ) . 02 ... basename( __FILE__,'php' ) . $szModule . '.php'; 03 ... 04 ... if ( FIL_Exists( $szFile ) ) /* Locate the necessary file in the plugins directory first */ 05 ... { 06 ... require_once( $szFile ); /* Require the file if it exists */ 07 ... } /* if ( FIL_Exists( $szFile ) ) */ 08 ... else /* Else of ... if ( FIL_Exists( $szFile ) ) */ 09 ... { 10 ... /* Locate the file in the path of Vae Soli! */ 11 ... $szFile = FIL_AddBS( str_replace( '\\','/',VAESOLI_PATH ),'/' ) . 12 ... basename( __FILE__,'php' ) . $szModule . '.php'; 13 ... if ( FIL_Exists( $szFile ) ) /* Locate the necessary file in the include directory */ 14 ... { 15 ... require_once( $szFile ); /* Require the file if it exists */ 16 ... } /* End of ... Else of ... if ( FIL_Exists( $szFile ) ) */ 17 ... else /* Else of ... if ( FIL_Exists( $szFile ) ) */ 18 ... { 19 ... $szPayload = 'A server file could NOT be found'; 20 ... $szMsg = basename( $szFile ) . ' not found'; 21 ... $iRetCode = RET_CODE_NOT_IMPLEMENTED; 22 ... } /* End of ... Else of ... if ( FIL_Exists( $szFile ) ) */ 23 ... } /* Else of ... if ( FIL_Exists( $szFile ) ) */
En ligne 01, on constitue le nom du script à charger et on va le chercher
dans le répertoire des plugins de Vae Soli! (et cela avant même d'aller
chercher le même module dans le répertoire d'include de Vae Soli! parce que
nous considérons que les plugins ont la priorité sur le code standard de
Vae Soli! !). Donc … si la root du site web est
'C:\sites\vaesoli\docs'
et que Vae Soli! est installé dans le
sous-répertoire 'vaesoli'
de la root du site et que le module dont il faut
assurer le traitement est ls-file-explorer
, on va chercher le
fichier suivant : 'C:\sites\vaesoli\docs\vaesoli\include\..\plugins\LSAjax.class.ls-file-explorer.php'
.
Si le fichier est trouvé (ligne 04) on l'inclut (ligne 06). Si le fichier en
question n'est pas trouvé, on continue avec la ligne 11 en constituant le
même nom de fichier mais cette fois-ci placé dans le répertoire de Vae Soli! :
'C:\sites\vaesoli\docs\vaesoli\include\LSAjax.class.ls-file-explorer.php'
.
Si là encore le fichier n'est pas trouvé, c'est que nous avons un problème et
qu'aucun code n'est fourni pour s'occuper de l'interaction Ajax. Dans ce cas,
nous indiquons que le problème a été détecté et préparons ce qui est nécessaire
pour retourner cette information au navigateur du visiteur (lignes 19, 20 et 21).
Prenons le cas où tout s'est bien déroulé (toutes les variables passées à
TreatRequest
ont été mises à jour par le code dont on a réalisé
l'inclusion), il suffira alors à la classe LSAjax
de concaténer
toutes les variables sous la forme d'un XML. C'est exactement ce dont
s'occupe la méthode CreateResponse()
de
LSAjax
:
function CreateResponse( $szContent , $szModule , $szAction , $szLang , $szMsg , $iRetCode , $aErrors , $szPayload , $szCargo , $szCargo2 , $szCargo3 ) /*---------------------------------*/ { $szRetVal = ''; /* Return value of the method */ // Don't put the response in CDATA section! // If you do ... please be aware of the fact that a CDATA // section MAY NOT include another CDATA section. // As sometimes the payload is a simple XML extract // it can contain CDATA sections ... which will create // a conflict with the outer CDATA section created // in this XML. That's the reason why we need to avoid // it. $szRetVal .= "<?xml version=\"1.0\" encoding=\"iso-8859-15\" standalone=\"yes\"?>\n"; $szRetVal .= "<Vaesoli xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"; $szRetVal .= " xmlns:xi=\"http://www.w3.org/2001/XInclude\"\n"; $szRetVal .= " xmlns:vae=\"urn:lato-sensu-management/Vaesoli\">\n"; $szRetVal .= " <ReturnCode>{$iRetCode}</ReturnCode>\n"; $szRetVal .= " <Module><![CDATA[{$szModule}]]></Module>\n"; $szRetVal .= " <Request><![CDATA[{$szAction}]]></Request>\n"; $szRetVal .= " <Message lang=\"{$szLang}\"><![CDATA[{$szMsg}]]></Message>\n"; $szRetVal .= " <Errors lang=\"{$szLang}>\"><![CDATA[" . $this->ReportErrors( $aErrors ) . "]]></Errors>\n"; $szRetVal .= " <Response>{$szPayload}</Response>\n"; $szRetVal .= " <Cargo><![CDATA[{$szCargo}]]></Cargo>\n"; $szRetVal .= " <Cargo2><![CDATA[{$szCargo2}]]></Cargo2>\n"; $szRetVal .= " <Cargo3><![CDATA[{$szCargo3}]]></Cargo3>\n"; $szRetVal .= "</Vaesoli>\n"; return ( $szRetVal ); /* Return result to caller */ } /* End of method LSAjax.CreateResponse() ============================ */
Au bout du compte, vous voyez qu'un XML est généré … dont ce sera la
responsabilité de la méthode SendResponse()
de s'occuper pour
la renvoyer au navigateur du client :
function SendResponse( $szXML ) /*---------------------------*/ { echo $szXML; } /* End of method LSAjax.SendResponse() ============================== */
Ooops … encore un mot pour vous dire qu'avant de faire tous ces
traitements, tout au départ de la méthode Run()
, on a pris soin
d'activer un output buffer (ob_start()
) et
qu'on a déjà généré un header (HTTP response header) de type XML
(header( "Content-Type: text/xml; charset=iso-8859-15" )
). Le
reste est affaire de récupération du buffer d'output et de son utilisation
dans la réponse fournie au final.
LSExplorer
2013-06-16Depuis l'opus "5.3.0003"
Une des classes sur lequelles nous avons passé beaucoup de temps est la
classe LSExplorer
qui permet d'afficher un File
Explorer un peu à la mode du Norton Commander, et plus tard du Total
Commander.
Depuis 1987, nous n'avons cessé d'utiliser le Norton Commander dans l'environnement DOS, puis plus tard, dans l'environnement Windows. Au final, nous avons conçu notre propre "Commander" dans la collection «Je Gère …» avec le «Je Gère … Mon PC» [2] (pour le monde DOS) et avons finalement collaboré à la version Thaïlandaise de Total Commander.
Ici, il a s'agit de donner accès aux fonctionnalités de base de ce genre
d'interface via le web. C'est la naissance du File
Explorer avec la classe LSExplorer
de Vae Soli!. Encore
une petite mise au point : cette interface n'est pas neuve car déjà en
2006 une classe Vae Soli! existait pour ce faire. Nous venons de la
documenter et de la parfaire pour enfin la publier de manière à ce qu'elle
puisse servir dans de multiples environnements web. Voici comment
l'utiliser :
$oExplorer = new LSExplorer( null , /* Left panel directory (null = domain root) */ null , /* Right panel directory (null = domain root) */ "FILE_EXPLORER", /* LSExplorer ID */ true , /* 2 panels */ $this->oPage , /* Page we're on */ '/ajax.php' ); /* URL for Ajax calls */ echo $oExplorer->Render();
Notez que le fichier /ajax.php
est créé
automatiquement par la classe LSBuilder
. Ce fichier est
quasiment similaire à tout fichier créé dans la root d'un site : il
inclut le fichier /master.php
. En voici le
code :
ajax.php -------- <?php global $__LS_IsAjax; $__LS_IsAjax = true; include( '../master.php' ); ?>
L'existence de la globale $__LS_IsAjax définie à true
permet
d'activer les routines Ajax standards fournies par Vae Soli!. La méthode
Run()
de l'objet LSApplication
tient compte de
l'existence de cette variable pour activer les routines Ajax :
if ( ! isset( $GLOBALS[ '__LS_IsAjax' ] ) || ! $GLOBALS[ '__LS_IsAjax' ] ) { … code habituel du Run() } else { $this->AjaxRun(); /* Run application as Ajax */ }
À son tour la méthode AjaxRun()
prend dès lors le contrôle.
Elle crée une instance de la classe LSAjax
qui comporte toute
l'intelligence nécessaire au traitement des appels Ajax.
Depuis l'opus "5.3.0003"
En vue de se protéger contre des attaques de tous poils, et particulièrement contre les attaques de type XSS [3] , le W3C et les créateurs de navigateurs se sont mis d'accord pour utiliser des mécanismes de politique de contenus. Il s'agit en l'occurrence de vérifier que les contenus qui doivent être affichés proviennent de sources fiables.
Pour Vae Soli! il s'agit de rendre disponible le mécanisme mis au point
par les autorités compétentes afin de pouvoir garantir l'application
de sources fiables. Avec la version 5.3.0003
c'est chose
faite. Comment faire ? Il suffit de mettre un paramètre de page
comme l'illustre le code suivant :
<LSContentSecurityPolicy><![CDATA[script-src 'self' https://apis.google.com]]></LSContentSecurityPolicy>
Et voilà le resultat dans les headers HTTP de la réponse fournie :
HTTP/1.1 200 OK Date: Sat, 15 Jun 2013 11:15:56 GMT Server: Apache/2.2.11 (Win32) PHP/5.3.5 X-Powered-By: PHP/5.3.5 Expires: Sat, 29 Jun 2013 12:11:19 +0000 Cache-Control: max-age=1212923 Content-Security-Policy: script-src 'self' https://apis.google.com X-WebKit-CSP: script-src 'self' https://apis.google.com X-Content-Security-Policy: script-src 'self' https://apis.google.com Content-Encoding: gzip Vary: Accept-Encoding Content-Length: 7564 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text/html
Vous pouvez obtenir plus d'infos sur le sujet du Content Security Policy en vous rendant sur le site de HTML5 Rocks.
LSContentsW3C
2013-06-14Depuis l'opus "5.0.0007"
Cette île permet d'obtenir une petite icône W3C comme l'illustre la capture d'écran suivante :
Comment amener ceci dans votre page à l'endroit souhaité ? Il suffit de
créer une île LSContentsW3C
comme le code ci-dessous vous y
engage :
<Island id="validate" active="yes" class="LSContentsW3C"> <param name="validate"><![CDATA[true]]></param> <param name="with-div"><![CDATA[false]]></param> </Island>
Ce que cette définition XML nous enseigne c'est que l'île est insérée sans
être elle-même à l'origine d'une nouvelle division (with-div =
false
) et qu'un clic entretient un véritable lien de validation
(validate = true
).
Bien que cette île soit documentée de manière tardive, elle existe depuis le 04/02/2010. Elle vient de faire l'objet d'une publication dans le documentation de Vae Soli!, documentation qui ne fait que s'allonger.
prefetch
et prerender
2013-06-10Depuis l'opus "5.3.0003"
Tout démarre d'une nouvelle spécification HTML5, finalement pas si nouvelle que cela mais qui ne se fraye un chemin dans les différentes solutions d'optimisation de performance que maintenant.
L'idée est simple et part d'un constat limpide : quand un utilisateur visite une page donnée, les chances qu'il visite une autre page bien précise sont élevées. C'est le cas d'un didacticiel par exemple (tutorial) ou encore le cas d'un article découpé en plusieurs pages. Les exemples sont nombreux où l'utlisateur a pas mal de chances de vouloir requérir la page 3 alors qu'il est en train de lire la page 2.
Disons-le tout de suite, ce n'est finalement qu'assez récemment que Vae Soli! a offert la possibilité de définir des pages à multiples contenus paginés.
L'usage que nous en faisons est plutôt limité mais il est particulièrement efficace, notamment dans des contextes mobiles (smartphone, tablette, …) où la bande passante peut-être considérablement limitée. Dans ces cas, il est très utile effectivement de découper un contenu afin de le rendre disponible morceau par morceau, à la demande. C'est le cas de la présente page !
L'implémentation de contenus multiples dans Vae Soli! va jusqu'à gérer une table des matières (à la demande) et l'insertion automatique des liens "précédent" et "suivant" en bas de page.
Vae Soli! 5.3.0002
va jusqu'à générer des liens avant-arrière
(<link rel="prev" ...> et <link
rel="next" …>
) pour une prise en compte SEO
optimale. Le navigateur peut aussi tenir compte de ces liens pour gérer
l'activation du contenu suivant (ou précédent) au grand bénéfice de
l'utilisateur (c'est en tout cas le cas d'Opera qui reste notre navigateur
favori).
Aujourd'hui, Vae Soli! 5.3.0003
va encore plus loin en
générant, s'il le faut, des liens de prefetch et même de
prerendering. Le résultat peut être impressionnant dans
la sensation de performance car en effet de telles pages sont chargées en
arrière-plan (par exemple pendant que le visiteur lit la première partie de
l'article, on précharge la deuxième partie) et lorsqu'elles sont demandées
réellement par l'utilisateur, elles se chargent en un rien de temps. Bien
entendu, cela dépend de l'implémentation qui en est faite dans les
navigateurs (et ce n'est d'ailleurs pas encore le cas d'Opera —
Grrrr !). Parfait ! Comment faire ? Rien de plus simple; voyez
la définition du contenu de la présente page :
<Island id="contents" active="yes" class="LSContents" lupdate="auto"> <param name="snippet"><![CDATA[/snippets/blue-deco.html]]></param> <param name="paginate"><![CDATA[true]]></param> <param name="toc"><![CDATA[true]]></param> <param name="autotoc"><![CDATA[h2]]></param> <param name="page"><![CDATA[0]]></param> <param name="storage" browsertype="browser"><![CDATA[ %iles%/{auto}-21.php (* Statisti … [*ref=stats-analytics*] *); %iles%/{auto}-20.php (* LSTag, … [*ref=multi-credentials*] *); %iles%/{auto}-19.php (* Tour d'h … [*ref=filters*] *); %iles%/{auto}-18.php (* Messages … [*ref=LSServiceMessage*] *); %iles%/{auto}-17.php (* Accès … [*ref=LSExpirationHeader*] *); %iles%/{auto}-16.php (* Messages … [*ref=service-message*] *); %iles%/{auto}-15.php (* Config Ap… [*ref=lsform*] *); %iles%/{auto}-14.php (* LSContent… [*ref=lsbooking*] *); %iles%/{auto}-13.php (* LSTag('im… [*ref=lstag-img*] *); %iles%/{auto}-12.php (* LSGeo, LS… [*ref=lsgeo*] *); %iles%/{auto}-11.php (* LSCache, … [*ref=lscache*] *); %iles%/{auto}-10.php (* Check Spa… [*ref=spamhaus-check*] *); %iles%/{auto}-9.php (* Campagnes… [*ref=add-campaign*] *); %iles%/{auto}-8.php (* Debugging… [*ref=page-debug*] *); %iles%/{auto}-7.php (* LSCursor:… [*ref=cursor*] *); %iles%/{auto}-6.php (* LSForm, L… [*ref=forms*] *); %iles%/{auto}-5.php (* LSContent… [*ref=bus-coord*] *); %iles%/{auto}-4.php (* Galerie a… [*ref=thumbnails*] *); %iles%/{auto}-3.php (* îles pr … [*ref=pre-text*] *); %iles%/{auto}-2.php (* LSContent… [*ref=remind-pw*] *); %iles%/{auto}-1.php (* Dat… [*ref=pubdate-expiry*] *)]]></param> <param name="next-prefetch"><![CDATA[true]]></param> <param name="prev-prefetch"><![CDATA[true]]></param> </Island>
On ne peut plus simple et cela a pour effet de générer les instructions de prerender correctes dnas le HTML de la page…
<link rel="prefetch" href="/samples.php?page=1" /> <link rel="prefetch" href="/samples.php?page=3" />
… étant entendu que nous nous trouverions sur la page #2 !
LSContentsSiteManager
et
LSSiteManager
2013-05-07Depuis l'opus "5.3.0002"
La classe LSContentsSiteManager
est la classe qui, rendue sous
forme d'île de contenu, permet d'afficher un gestionnaire de site
(LSSiteManager
). Ces classes sont encore en construction au
moment où nous écrivons ces lignes. En voici cependant une documentation
succincte et quelques illustrations extraites d'un site de test.
Tout d'abord il vous faut une page de gestion de votre site. Cela peut
se faire de la manière suivante (copie de ce que la classe LSBuilder
a généré automatiquement) :
<Land id="/sitemgr.php" group="main" creationdate="20121120" lupdate="now-2" sm="true" onfail="/login.php" href="%geo-path%/{land->id}.pdef.xml"> </Land>
Vous distinguez clairement que si la page n'est pas révélée de manière
correcte, on file vers la page de /login.php
. C'est entièrement
normal : il faut avoir certains droits pour avoir accès à la gestion de
site (onfail="/login.php"
).
Par ailleurs on indique à Vae Soli! que CETTE page est celle qui
donne accès à la gestion de site : sm="true"
.
C'est indispensable parce qu'avec le Site Manager il est possible de
suspendre le site c'est-à-dire le rendre inaccessible au public. Oui mais
… si vous le rendez inacessible au public il le sera donc aussi pour
vous. Dès lors il vous sera impossible … d'avoir accès au Site
Manager. Embêtant : vous êtes capable d'arrêter votre site mais pas de
le redémarrer ! Ouais, sauf que même si le site est arrêté vous
continuerez à avoir accès à la page marquée comme celle qui offre les
services de gestion de site, soit le fameux
sm="true"
.
Ensuite, il s'agit de définir la page elle-même. Dans l'exemple ci-dessus,
la définition de la page est maintenue dans le fichier %geo-path%/{land->id}.pdef.xml
. %geo-
path%
est une variable géorama qui sera résolue selon la définition
que vous lui aurez donnée. Imaginons pour l'exemple que cette variable
vaille "/config/
". Par contre la macro
"{land->id}
" est transformée par le nom de la page, ici
sitemgr
. On arrive dès lors à trouver notre définition de page
dans le fichier /config/sitemgr.pdef.xml
. Voyons
donc une définition possible de cette page :
<?xml version="1.0" encoding="iso-8859-1"?> <Land xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:html="http://www.w3.org/1999/xhtml"> <Description title="Gestion de votre site" h1="Gestion de votre site"> <ExtendedDesc><![CDATA[Tous les outils qui vous permettent de gérér votre site]]></ExtendedDesc> <Rights><![CDATA[Tous droits réservés sur toutes les pages de notre site web]]></Rights> </Description> <Defaults> <Settings> <LSGuid><![CDATA[LS-952c2ec3-798a-4e52-9002-6691a6225a81]]></LSGuid> <LSKeyword><![CDATA[site-manager]]></LSKeyword> <LSExpirationHeader><![CDATA[access plus 30 minutes]]></LSExpirationHeader> </Settings> </Defaults> <Contents id="contents"> <Archipelago id="body" active="yes" category="Q-body"> <Island id="site-manager" active="yes" class="LSContentsSiteManager" /> </Archipelago> </Contents> </Land>
Et voilà ! Votre page de gestion de site est créée. Le reste c'est l'affaire de Vae Soli!.
Voyons maintenant de quoi cette page se compose. Attention, nous le répétons, ce sont des notes préliminaires. Il se pourrait donc que tout ne se présente pas exactement de cette manière dans la version que vous utilisez.
Vae Soli!, opus 5.3.0000
, dispose d'un Site Manager très
amélioré par rapport aux versions antérieures.
Fabuleux … mais toujours pas fini ! Pourtant, avant de pouvoir rendre publique la suite Quitus [4] nous serons bien obligés de terminer ce travail car sans lui, comment les clients vont-ils contrôler l'ensemble de leur site avec la simplicité de la collection « Je Gère… » ?
Alors, pour vous mettre l'eau à la bouche, voici déjà quelques captures
d'écran de ce sacré Site Manager (prises sur un site réel … généré
au départ de la classe LSBuilder
[5] et qui nous permet de vérifier le
bon fonctionnement du Site Manager sur un site complètement à la main
d'un client).
La table des matières représente un moyen simple de se rendre à n'importe quelle section du Site Manager en un seul clic. Ne vous fiez pas entièrement à la liste des sections qui s'y trouvent référencées pour l'instant : cette liste évoluera simultanément à notre travail sur le Site Manager.
Voici une vue partielle des sections en question (la liste est en réalité plus allongée et référence toutes les sections mentionnées dans la table des matières). Par défaut, chaque section est pliée (collapsed) comme vous le montre la capture d'écran ci-dessous :
Le petit bouton Home (qui représente une maison) permet de remonter directement à la table des matières : vous pouvez donc passer de la table des matières à une section et d'une section à la table des matières.
Comme son nom l'indique, la section Start / Stop permet l'arrêt et le redémarrage d'un site web. À vrai dire ce n'est pas tant le serveur web qui est stoppé mais plutôt Vae Soli!.
Le Start et Stop du serveur se contrôlent par la présence (ou l'absence) du
fichier halt.sem
[6] dans la racine du site.
Si ce fichier est présent, le site est arrêté (sauf quelques pages qui continuent
à être servies, dont la page qui contient le Site Manager, pour des raisons
évidentes). Si ce fichier est absent, le site fonctionne tout naturellement
ce qui veut donc dire que Vae Soli! traite les requêtes comme si de rien n'était.
Le fichier halt.sem
doit contenir l'adresse vers
laquelle il faut brancher l'exécution du site (l'URL de substitution).
Quatre cas distincts ont été programmés jusqu'à présent dans la classe
LSSiteManager
:
Dans l'illustration qui suit, on remarque tout de suite l'interrupteur (ici au vert, ce qui
indique que Vae Soli! n'est pas à l'arrêt … toutes les pages du site sont servies
normalement). Un clic sur ce bouton et le serveur ('fin … Vae Soli! !) se met
à l'arrêt : toutes les requêtes sont alors dirigées vers l'URL indiquée dans le type de
stop sélectionné (stopped
dans le cas de la capture d'écran et donc ici l'URL
/stopped.html
).
Ensuite vient la section STATISTICS / ANALYTICS. Cette section ne contient PAS encore tout le matériel suffisant pour être parfaitement exploitable mais voilà justement la section sur laquelle les développeurs de Vae Soli! travaillent à l'heure où nous écrivons ces lignes. C'est avec la présente section qu'un utilisateur pourra savoir combien de fois a été vue telle et telle page de son site, les dates d'accès, le type de browser utilisé (mobile, desktop, ...), les adresses IP des visiteurs, les referers, etc.
Comme pour le démarrage / arrêt de votre site, c'est un gros interrupteur qui vous permet d'indiquer si oui ou non les "analytics / stats" doivent être pris en compte par Vae Soli! :
Il s'agit de pouvoir contrôler les fichiers robots.txt
et sitemap.xml
.
Cette section est entièrement bouclée ! En voici les captures d'écran :
Vous pouvez :
robots.txt
robots.txt
robots.txt
robots.txt
(une fois que vous l'avez édité)
En ce qui concerne le sitemap.xml
, vous pouvez
supprimer le fichier ou le créer. Vous ne pouvez pas l'éditer (ni donc le
sauver). Le sitemap.xml
est généré automatiquement
sur base des indications fournies dans votre géorama. La génération est
entièrement réalisée par la classe LSXMLSitemap
qui, pour la
circonstance, a fait l'objet d'une revue de code assez sévère.
Quand le géorama est composé on retrouve souvent des parties identiques.
Pensez par exemple à l'endroit où est stocké le contenu physique de chaque
île (ce qui sera vraiment affiché sur la page web visitée par les
internautes) : /islands
par exemple. Il peut alors être
intéressant de passer par des variables, des variables uniquement connues
du géorama, pour faire référence à ces endroits de stockage souvent
identiques car le seul changement de la variable impacte la totalité du
géorama ce qui évite de nombreuses erreurs.
La présente section vous permet de définir la valeur de chaque variable et aussi de supprimer ou même créer de nouvelles variables. Attention, des variables peuvent faire appel à des variables et il en ressort donc que leur ordre est important. C'est la raison pour laquelle vous bénéficier de glisser / déposer (drag and drop).
Vous pouvez :
C'est une bonne pratique que de mettre vos images dans un répertoire
"images" de votre site. Par défaut, la classe LSBuilder
crée le répertoire /images
dans la racine de votre site.
C'est une autre bonne pratique que de mettre vos media (audio et video) dans
le répertoire "media" de votre site. Par défaut, la classe
LSBuilder
crée le répertoire /media
dans la
racine de votre site.
Dès lors, le Site Manager regarde si de tels répertoires existent et vous propose, en visualisation seulement, la liste des fichiers qui sont stockés dans ces deux répertoires. Voici un exemple d'une liste de fichiers inclus dans ces deux répertoires :
Vous pouvez cliquer sur le nom de chaque fichier pour le visualiser. Voici des exemples de visualisation de fichiers "image", "video" et même audio :
Un site est entièrement déterminé par un UNIQUE fichier, le géorama. Le
géorama est la carte exhaustive du site. C'est dans le géorama que sont
recensées toutes les pages qui composent le site. En
général, le géorama est stocké dans un fichier qui s'appelle georama.xml
mais c'est configurable.
Comme un site peut être important (nombreuses pages), le fichier du géorama peut alors être assez dodu. C'est la raison pour laquelle le géorama est alors découpé en plusieurs fichiers physiques différents plus petits. La liste qui suit vous donne une indication précieuse sur la liste des fichiers qui composent le géorama. Vous pouvez visualiser chaque fichier.
Une substitution c'est la possibilité de transformer une chaîne de caractères en une autre chaîne de caractères. Par exemple la chaîne '{{{COMPANY}}}' est transformée en 'Lato Sensu Management'. Les substitutions sont exécutées AVANT de rendre la page finale au visiteur qui la demande.
Autre exemple : '{{{ADDRESS}}}' est transformé en 'Rue Bois des Mazuis, 47 — 5070 Vitrival — Belgique' … ce qui est, vous en conviendrez, beaucoup plus court.
Un autre avantage des substitutions est que chaque substitution est définie à une seule place. Une modification à un seul endroit se répercute à chaque endroit où la substitution est utilisée. Pensez par exemple à un changement d'adresse … pas besoin de regarder chaque page de votre site pour savoir où il faut modifier ladite adresse !
Mais ce n'est pas tout car en effet les substitutions peuvent être variables en fonction de la langue de votre site. Vous pouvez ainsi indiquer que la forme courte de votre forme légale est 'SPRL' en français, mais 'BVBA' en néerlandais ! Et ce n'est pas fini, car vous pouvez composer des substitutions qui sont applicables de date à date (publication/expiration), ou même des substitutions variables comme '{{{year()}}}' par exemple, etc., etc.
La présente section vous propose donc de gérer vos substitutions : ce n'est pas rien !
La section des substitutions dans le Site Manager s'est considérablement enrichie mais pour autant, elle n'est pas encore opérationnelle en ce sens qu'elle ne permet PAS encore de :
Pour que nous puissions avancer en cette matière il nous faut réfléchir à la manière la plus simple de réaliser ces opérations (la difficulté réside en ceci que chaque substitution peut avoir différentes valeurs qui elles dépendent des attributs qu'on y met; par exemple la forme juridique est SPRL en français (l'attribut) et BVBA en flamand). L'équipe de Lato Sensu Management se donne un peu de temps pour cette partie.
Voici néanmoins une première vision de la partie réservées aux substitutions. La flèche blanche vous indique 1 substitution ({articles}) qui possède 2 valeurs (Articles et Artikelen, cerclés de bleu). Nous avons cerclé en orange les 2 attributs associés à la valeur "Artikelen" (l'attribut "bizarre" est un simple test et n'a aucune valeur fonctionnelle).
Plus bas dans la capture d'écran nous avons entouré de rouge des substitutions
variables : une substitution variable est une substitution qui implique
l'exécution de code PHP (que l'on reconnaît au fait que la valeur de la
substitution commence par ".php=
").
C'est probablement la section la plus importante du Site Manager. Au moment
où nous écrivons ces lignes, cette section n'est pas terminée. Aussi nous
livrons-vous une vue en avant-phase de ce que cette section permettra. Bien
entendu, il sera question de pouvoir ajouter, supprimer et modifier les
pages de votre site web. La question la plus épineuse concerne, vous vous
en doutez, l'édition d'une page qui est un énorme chantier en cours (classe
LSPageEditor
).
Entretemps, nous avons déjà fortement avancé sur cette partie et par exemple il est permis de demander un scoring de page[7] :
Un dernier mot avant de clôturer ce billet [8] car on ne pouvait tout de même pas passer sous silence le File Explorer.
Grâce à cette section vous allez pouvoir uploader, downloader, transférer, supprimer, recopier vos fichiers sur votre serveur web … dans les limites de vos droits. Pour l'instant, seul l'affichage de deux répertoires fonctionne et l'équipe de Lato Sensu Management travaille à programmer les opérations sur fichiers exposées ci-avant.
… mais déjà, que pouvons-nous en retirer ?
Vous voyez clairement que vous disposez de deux panneaux : un à gauche, un à droite. En cliquant sur les noms des répertoires vous pourrez vous déplacer dans les répertoires de votre serveur. Vous pourrez sélectionner des fichiers et les copier d'un panneau à l'autre. Vous pourrez aussi les supprimer. Pour l'heure, ces opérations ne sont pas fonctionnelles. Il nous faut (re-)construire les routines javascript et ajax qui les permettront.
LSVaesoli
: Activation des
statistiques d'accès 2013-05-07Depuis l'opus "5.3.0000"
L'opus 5.3.0000
de Vae Soli! permet d'activer des statistiques
d'accès. Le LSSiteManager
permet de les analyser. Voici comment !
Tout commence par la prise en note des paramètres LSIsStats
et
LSStatsLog
. Voici un extrait du defaults.xml
:
<LSIsStats><![CDATA[true]]></LSIsStats> <LSStatsLog><![CDATA[/../logs/analytics.log]]></LSStatsLog>
Ce que ces deux lignes de configuration indiquent à Vae Soli! c'est que les
statistiques d'accès doivent être activées et qu'elles doivent être sauvées
dans le fichier /../logs/analytics.log
. Les
statistiques peuvent ensuite être consultées grâce au Site Manager, section
"Analytics".
Depuis l'opus "5.3.0000"
Comme exposé avant, vous pouvez donc bénéficier de statistiques d'accès de base. Ces statistiques sont générées par Vae Soli! chaque fois qu'un visiteur accède à une page sous le contrôle de Vae Soli!. Ces statistiques ne se substituent en rien à des statistiques générales telles qu'élaborées par les serveurs HTTP (IIS, Apache, …).
Et voilà bien une question intéressante. Il n'est absolument pas douteux qu'un programmeur/développeur, un webmaster, un technicien ont besoin de statistiques détaillées. Il leur est indispensable de pouvoir disposer d'informations sur toutes les requêtes qui aboutissent en erreur, par exemple. Mais ce genre de besoin n'a que très peu de choses en commun avec le besoin de Monsieur ou Madame Toutlemonde. Ce qui a un intérêt pour eux c'est de savoir combien de fois la page XXX a été vue entre telle et telle date, par qui, pendant combien de temps, …. De telles informations sont certes disponibles dans les logs des serveurs mais elles sont un peu noyées dans toutes les autres infos disponibles.
Pour répondre au besoin des Toutlemonde, Vae Soli! fournit ses propres statistiques ! C'est de ces statistiques dont nous parlons ici. On fait fi des erreurs 404 (par exemple), on fait fi des accès aux ressources statiques (les images, les vidéos, …), on fait fi … de tout ce qui n'est pas une page renseignée dans le géorama ! Maintenant que le décor est planté voyons quelles infos Vae Soli! stocke.
Le stockage des infos se fait dans un fichier plat, le fichier qui est
renseigné dans le paramètre LSStatsLog
.
<LSIsStats><![CDATA[true]]></LSIsStats> <LSStatsLog><![CDATA[/../logs/analytics.log]]></LSStatsLog>
Le stockage lui-même correspond à un serialize()
d'un tableau.
Le tableau est composé par la méthode Stats
de l'objet
LSPage
. En voici le code (à l'heure où nous écrivons ces lignes) :
$aAnalytics['Page'] = array( 'Now' => time() , 'URL' => $this->Self , 'GUID' => $this->szGuid, 'Query' => isset( $_SERVER['QUERY_STRING'] ) ? $_SERVER['QUERY_STRING'] : null, 'Language' => $this->szLanguage ); $aAnalytics['User'] = $oUser; $aAnalytics['IP'] = $_SERVER['REMOTE_ADDR']; $aAnalytics['Browser'] = $oBrowser; $aAnalytics['Protocol'] = isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : null; $aAnalytics['Request'] = $aRequest; $aAnalytics['Trip'] = isset( $_SESSION['Trip'] ) ? $_SESSION['Trip'] : null; $oTracer->Trace( serialize( $aAnalytics ),0 );
L'information de page comprend est un tableau associatif :
['Now']
['URL']
['GUID']
['Query']
['Language']
L'information utilisateur est un objet LSAnayticsUser
qui possède les propriétés suivantes :
szUserAccount
: compte utilisateurszFirstname
: prénom de l'utilisateurszLastname
: nom de l'utilisateurszEmail
: email de l'utilisateurszCompany
: société de l'utilisateurszUserID
: User ID de l'utilisateurszGUID
: GUID de l'utilisateuriLogin
: UTC de login de l'utilisateurszGroups
: groupes auquels l'utilisateur appartientszRelations
: relations entretenues avec l'utilisateurszCountry
: pays de l'utilisateur[1] … Open, simple, fast
[2] … La collection «Je Gère …» est une collection de programmes commercialisée par la société FastWrite et ensuite co-éditée par les sociétés FastWrite et Hachette/Marabout. La collection originelle comportait 24 titres dont le fameux «Je Gère … Mon PC»
[3] … Le cross-site scripting (abrégé XSS), est un type de faille de sécurité des sites web permettant d'injecter du contenu dans une page, permettant ainsi de provoquer des actions sur les navigateurs web visitant la page. Plus d'infos sur Wikipedia.
[4] … Quitus est une suite entreprise, fondée sur Vae Soli! mais qui, au contraire de notre framework, n'est pas gratuite ni même livrée en Open Source
[5] … La classe LSBuilder
évolue de manière complètement parallèle aux classes LSContentsSiteManager
et LSSiteManager
. Plus d'infos sur le sujet dans les news à venir
[6] … L'extension sem veut dire semaphore
[7] … Le scoring d'une page permet de juger la pertinence des éléments présents dans la page pour décrire le sujet dont elle parle. C'est une pièce maîtresse de toute stratégie de placement correct (à défaut d'être parfait) dans les moteurs de recherche.
[8] … Nous savons que nous n'avons pas couvert l'ensemble des sections du Site Manager … mais cela viendra plus tard