Autant le premier article de la série était tout public, autant celui-là est principalement dédié aux développeurs de plugins.
Dotclear 2.2 introduit de nouveaux mécanismes au niveau des urlhandlers, afin de faciliter la vie des plugineurs.
Nouveaux behaviors
De nouveaux behaviors ont été ajoutés à bas niveau dans la gestion des urlHandlers, ils sont au nombre de 3 : urlHandlerBeforeGetData, urlHandlerBeforeSearchCount et urlHandlerGetArgsDocument.
- urlHandleBeforeGetData est appelé juste avant de servir un fichier de template. Il permet notamment de changer au dernier moment le fichier à livrer.
Exemple pratique basé sur l'astuce de Pep pour servir un template personnalisé pour une catégorie donnée. Le code à produire devient grandement réduit, et évite de réécrire du code du core :
$core->addBehavior('urlHandlerBeforeGetData',array('myBehaviors','beforeGetData'));
class myBehaviors
{
public static function beforeGetData($_ctx)
{
global $core;
if ($_ctx->current_tpl == "category.html") {
$tpl = 'category-'.$_ctx->categories->cat_id.'.html';
if ($core->tpl->getFilePath($tpl)) {
$_ctx->current_tpl = $tpl;
}
}
}
}
Le handler en question récupère le contexte en paramètre, et il peut le modifier à sa guise. Dans notre cas, si category-<id_cat>.html existe, alors il est servi en lieu et place de category.html
- urlHandlerBeforeSearchCount permet d'agir avant d'afficher le nombre de résultats dans la page search.html. avec dotclear 2.1.7, il n'était pas possible de modifier la requête de comptage des billets correspondant à la recherche. Le behavior prend en paramètre le tableau de paramètres ($params) qui sera transmis à la requête getPosts
- urlHandlerGetArgsDocument permet de modifier les arguments avant l'appel du handler. Le behavior prend en paramètre l'urlHandler courant, dont on peut réaffecter les attributs. On peut imaginer par exemple un plugin extraierait des informations supplémentaires à la fin de l'url d'un billet (ex: /fr, /page/xxx si le plugin gère la pagination de billet), et qui restaurerait l'url attendue par l'urlhandler, ni vu, ni connu.
Gestion des pages d'erreur
Avec dotclear 2.1.7, il n'était pas possible de gérer des pages d'erreurs particulières, en dehors d'une modification de la page 404.html : lorsqu'un urlHandler ne savait pas quoi faire de l'url entrée, ou détectait qu'elle correspondait à une page inexistante, il renvoyait vers la dcUrlHandler::p404(), et rien n'était interceptable à ce niveau-là.
doclear 2.2 introduit une gestion des pages d'erreurs, par le biais la méthode "registerError" ajoutée à clearbricks:
class urlHandler
{
...
public function registerError($handler){}
...
}
Désormais, lorsqu'un urlHandler ne sait pas servir une page donnée (ex: page non trouvée, erreur de traitement, ...), plutôt que de rappeler dcUrlHandler::p404, il lui suffit de lever une exception, avec pour code le code d'erreur http voulu. Pour garder une compatibilité avec les anciens plugins, l'ancienne méthode dcUrlHandler::p404 a été modifiée comme suit :
public static function p404()
{
throw new Exception ("Page not found",404);
}
A ce niveau-là, doclear intercepte l'exception, et déroule les handlers d'erreur un par un (dernier enregistré, premier servi), jusqu'à ce qu'un handler d'erreur lui indique qu'il a traité la page. En dernier recours, c'est le le handler d'erreur par défaut de dotclear qui sert la page, en l'occurrence l'ancien p404.
Au niveau du plugin, pour enregistrer un nouvel errorHandler, ça se passera au niveau du _public.php :
$core->url->registerError(array('myPublicBehaviors','error'));
class myPublicBehaviors
{
public static function error($args,$type,$e) {
// exemple de filtrage pour une erreur 404
if ($e->getCode() == 404) {
if (iCanHandleErrorAndServePage) {
// Traitement spécifiques, et renvoi de la page
return true;
}
}
}
Les paramètres transmis au handler sont :
- $args contient les arguments transmis à l'urlHandler initial
- $type contient le type d'urlHandler appelé ('post', 'category', 'archive', ...). Il correspond au type enregistré lors de l'appel à $core->url->register
- $e contient l'exception levée
Si l'errorHandler retourne true, dotclear arrête de parcourir les errorHandlers et considère le traitement comme OK. Sinon il passe par le handler suivant.
Si vous voulez voir une mise en pratique de ce nouveau mécanisme d'errorHandler, allez faire un tour du coté du plugin meuh, qui intercepte les erreurs pour voir dans une table d'alias si un billet n'avait pas l'url donnée auparavant.