Aller au contenu

Hooks & Filtres

ArtisanCMS intègre un système de hooks et filtres inspiré de WordPress, permettant aux développeurs d’étendre le comportement du CMS de manière découplée. Ce mécanisme repose sur le HookManager (app/CMS/HookManager.php) et la facade CMS pour un accès simplifié.

Le système distingue deux types de hooks :

  • Actions : exécutent des callbacks lorsqu’un événement survient (notifications, logs, traitements secondaires).
  • Filtres : modifient une valeur en la passant à travers une chaîne de callbacks avant de la retourner.

Chaque hook est enregistré avec une priorité (entier). Plus le nombre est bas, plus le callback s’exécute tôt. La priorité par défaut est 10.

Les actions permettent de réagir à un événement sans modifier la donnée source.

use App\Facades\CMS;
// Envoyer un email lorsqu'un contenu est publié
CMS::addAction('content.published', function ($content) {
Mail::to($content->author->email)->send(new ContentPublishedMail($content));
}, priority: 10);
// Logger l'activation d'un plugin
CMS::addAction('plugin.activated', function ($plugin) {
Log::info("Plugin activé : {$plugin->name}");
}, priority: 5);

Utilisez doAction pour déclencher tous les callbacks enregistrés sur un événement donné.

// Dans un contrôleur ou un service
CMS::doAction('content.published', $page);
// Avec plusieurs arguments
CMS::doAction('content.saving', $content, $request);

Les filtres transforment une valeur avant qu’elle ne soit utilisée.

// Mettre le titre en majuscules
CMS::addFilter('content.title', function ($title) {
return strtoupper($title);
}, priority: 20);
// Ajouter un préfixe aux slugs
CMS::addFilter('content.slug', function ($slug, $content) {
if ($content->type === 'article') {
return "blog/{$slug}";
}
return $slug;
}, priority: 15);
// Récupérer le titre filtré
$title = CMS::applyFilter('content.title', $page->title);
// Filtre avec contexte supplémentaire
$slug = CMS::applyFilter('content.slug', $page->slug, $page);

ArtisanCMS fournit de nombreux hooks prêts à l’emploi.

HookDescriptionArguments
content.savingAvant la sauvegarde d’un contenu$content, $request
content.savedAprès la sauvegarde d’un contenu$content
content.publishingAvant la publication$content
content.publishedAprès la publication$content
content.deletingAvant la suppression$content
theme.renderingAvant le rendu du thème$theme, $data
theme.activatedAprès activation d’un thème$theme
plugin.activatingAvant activation d’un plugin$plugin
plugin.activatedAprès activation d’un plugin$plugin
plugin.deactivatedAprès désactivation d’un plugin$plugin
user.registeredAprès inscription d’un utilisateur$user
media.uploadedAprès l’upload d’un média$media
HookDescriptionValeur
content.titleFiltre le titre affichéstring $title
content.bodyFiltre le corps du contenustring $body
content.excerptFiltre l’extraitstring $excerpt
content.metaFiltre les métadonnées SEOarray $meta
admin.menuModifie le menu d’administrationarray $menuItems
admin.dashboard.widgetsModifie les widgets du tableau de bordarray $widgets

Les callbacks sont exécutés dans l’ordre croissant de priorité.

// S'exécute en premier (priorité basse = haute importance)
CMS::addFilter('content.title', fn($t) => trim($t), priority: 1);
// S'exécute en second
CMS::addFilter('content.title', fn($t) => ucfirst($t), priority: 10);
// S'exécute en dernier
CMS::addFilter('content.title', fn($t) => $t . ' | Mon Site', priority: 99);

Pour un usage avancé, vous pouvez injecter le HookManager directement.

use App\CMS\HookManager;
class MyService
{
public function __construct(private HookManager $hooks) {}
public function process(): void
{
$this->hooks->addAction('content.saved', [$this, 'onContentSaved']);
}
public function onContentSaved($content): void
{
// Traitement personnalisé
}
}
  • Nommez vos hooks avec un namespace pour éviter les collisions : monplugin.content.saved.
  • Utilisez des priorités explicites plutôt que la valeur par défaut pour garantir l’ordre d’exécution.
  • Gardez les callbacks légers : déléguez les traitements lourds à des jobs en file d’attente.
  • Documentez vos hooks personnalisés pour les autres développeurs de plugins.