Aller au contenu

Créer un plugin

ArtisanCMS dispose d’une architecture de plugins permettant d’étendre les fonctionnalités du CMS. Ce guide couvre la création d’un plugin de A à Z.

La commande cms:plugin:create génère l’ensemble de la structure du plugin.

Fenêtre de terminal
php artisan cms:plugin:create

L’assistant interactif vous demande le nom, le slug, la description et l’auteur du plugin. Les fichiers sont générés dans content/plugins/.

content/plugins/my-plugin/
├── artisan-plugin.json # Manifest du plugin
├── src/
│ └── MyPluginServiceProvider.php # Point d'entrée
├── database/
│ └── migrations/ # Migrations spécifiques
├── routes/
│ └── admin.php # Routes d'administration
├── resources/
│ └── js/Pages/ # Pages Inertia (React)
├── config/
│ └── settings.php # Configuration par défaut
└── README.md

Le manifest décrit les métadonnées et les dépendances du plugin.

{
"name": "Mon Plugin",
"slug": "my-plugin",
"version": "1.0.0",
"description": "Description de mon plugin",
"author": {
"name": "John Doe",
"email": "john@example.com"
},
"url": "https://example.com/my-plugin",
"min_cms_version": "1.0.0",
"dependencies": []
}
ChampTypeDescription
namestringNom d’affichage du plugin
slugstringIdentifiant unique (kebab-case)
versionstringVersion SemVer
min_cms_versionstringVersion minimale d’ArtisanCMS requise
dependenciesarrayListe des slugs de plugins requis

Le ServiceProvider est le point d’entrée de votre plugin. Il enregistre les services, les routes et les hooks.

<?php
namespace Plugins\MyPlugin;
use Illuminate\Support\ServiceProvider;
use App\CMS\Traits\ReadsPluginSettings;
class MyPluginServiceProvider extends ServiceProvider
{
use ReadsPluginSettings;
protected string $pluginSlug = 'my-plugin';
public function register(): void
{
// Enregistrer vos services dans le conteneur
$this->app->singleton(MyService::class, function () {
return new MyService($this->getPluginSettings());
});
}
public function boot(): void
{
// Charger les migrations
$this->loadMigrationsFrom(__DIR__ . '/../database/migrations');
// Charger les routes
$this->loadRoutesFrom(__DIR__ . '/../routes/admin.php');
// Enregistrer des hooks
\CMS::addAction('content.saved', function ($content) {
app(MyService::class)->handleContentSaved($content);
});
// Enregistrer des blocs personnalisés
\CMS::addBlock('my-plugin/custom-block', [
'name' => 'Mon Bloc',
'category' => 'content',
'component' => 'MyPluginBlock',
]);
}
}

Ce trait permet d’accéder aux paramètres configurés par l’utilisateur pour votre plugin.

use App\CMS\Traits\ReadsPluginSettings;
class MyPluginServiceProvider extends ServiceProvider
{
use ReadsPluginSettings;
protected string $pluginSlug = 'my-plugin';
public function boot(): void
{
$apiKey = $this->getPluginSetting('api_key');
$allSettings = $this->getPluginSettings();
}
}

Définissez vos routes dans routes/admin.php. Elles sont automatiquement préfixées et protégées par le middleware d’administration.

<?php
use Illuminate\Support\Facades\Route;
use Inertia\Inertia;
Route::prefix('admin/plugins/my-plugin')->middleware(['web', 'auth', 'admin'])->group(function () {
Route::get('/', function () {
return Inertia::render('Plugins/MyPlugin/Index', [
'settings' => app(MyService::class)->getSettings(),
]);
})->name('plugins.my-plugin.index');
Route::post('/settings', [MyPluginController::class, 'updateSettings'])
->name('plugins.my-plugin.settings.update');
});

Créez vos composants React dans resources/js/Pages/.

resources/js/Pages/Plugins/MyPlugin/Index.tsx
import React from 'react';
import { Head, useForm } from '@inertiajs/react';
import AdminLayout from '@/Layouts/AdminLayout';
export default function MyPluginIndex({ settings }) {
const { data, setData, post } = useForm({
api_key: settings.api_key || '',
});
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
post(route('plugins.my-plugin.settings.update'));
};
return (
<AdminLayout>
<Head title="Mon Plugin" />
<form onSubmit={handleSubmit}>
<input
value={data.api_key}
onChange={e => setData('api_key', e.target.value)}
/>
<button type="submit">Enregistrer</button>
</form>
</AdminLayout>
);
}

Placez vos migrations dans database/migrations/. Préfixez vos tables avec le slug du plugin pour éviter les conflits.

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('cms_my_plugin_items', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->json('data')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('cms_my_plugin_items');
}
};
ÉvénementHookDescription
Activationplugin.activatingAvant activation, permet de vérifier les prérequis
Activéplugin.activatedAprès activation, exécuter les initialisations
Désactivationplugin.deactivatedNettoyage des ressources temporaires

Créez vos tests dans un dossier tests/ à la racine du plugin.

use Tests\TestCase;
class MyPluginTest extends TestCase
{
public function test_plugin_activates_successfully(): void
{
$this->artisan('cms:plugin:activate', ['slug' => 'my-plugin'])
->assertExitCode(0);
}
}

Exécutez les tests avec php artisan test --filter=MyPlugin.