Skip to Content
MoodlePartie 15 — Projets guidés (parcours pratique)Niv. 2 — Premier plugin (local + block)

Projet Niveau 2 — Premier plugin : local_todolist + block_progressinfo

⏱️ TL;DR — Votre premier code Moodle. Vous écrivez deux plugins simples mais complets : local_todolist (une todo-list par utilisateur, avec table en base, capabilities, formulaire, CRUD et réglages) puis block_progressinfo (un bloc affichant la progression). Objectif : intégrer le contrat de structure des plugins (frankenstyle, version.php, db/, classes/), le DML, la Form API et les capabilities — la mécanique commune à tout développement Moodle.

🎯 Niveau & objectifs

  • Niveau : 2 (intermédiaire). Prérequis : Niveaux 0–1 ; instance de dev locale (Partie 4) avec mode débogage développeur et purge de caches ; bases PHP orienté objet.
  • Durée indicative : 8–14 h.
  • Vous allez pratiquer : frankenstyle, version.php, XMLDB (db/install.xml), db/access.php (capabilities), db/upgrade.php, DML ($DB), Form API (moodleform), Output API (renderer + Mustache), hook de navigation, settings.php, l’API des blocs.

📋 Cahier des charges

Contexte — Les apprenants veulent gérer leurs tâches personnelles dans Moodle, et voir leur progression d’un coup d’œil. Vous livrez deux plugins : un plugin local (fonctionnalité transverse) et un bloc (affichage contextuel).

Objectif — Deux plugins installables/désinstallables proprement, avec données persistées, permissions et interface, respectant les conventions Moodle.

Plugin 1 — local_todolist

Périmètre inclus

  1. version.php correct (component local_todolist, version YYYYMMDDXX, requires).
  2. db/install.xml : une table local_todolist (id, userid, titre, description, done, timecreated…), créée via l’éditeur XMLDB.
  3. db/access.php : au moins une capability (local/todolist:manage).
  4. Une page index.php avec le pattern sécurisé complet (require_login, context, require_capability, $PAGE, $OUTPUT).
  5. Un formulaire (classes/form/ ou moodleform) d’ajout/édition d’une tâche.
  6. Le CRUD via DML ($DB->insert_record, get_records, update_record, delete_records).
  7. Un renderer + template Mustache pour l’affichage.
  8. Une entrée dans la navigation (hook) et une page de réglages (settings.php).
  9. Une chaîne d’upgrade réelle : ajouter une colonne en version 2 (db/upgrade.php).

Plugin 2 — block_progressinfo

Périmètre inclus

  1. La classe block_progressinfo avec get_content().
  2. applicable_formats() et les capabilities de bloc (addinstance, myaddinstance).
  3. Une configuration par instance (edit_form.php).
  4. Un affichage via template Mustache, ajoutable au tableau de bord.

Périmètre exclu — Pas de module d’activité (Niveau 3), pas de web service (Niveau 4), pas de JS avancé. On reste sur local + block.

Contraintes

  • Frankenstyle respecté partout (préfixe local_todolist_ / block_progressinfo_).
  • Aucun accès direct sans le pattern de sécurité (require_login, capability, sesskey/nonce sur les actions).
  • Toute requête paramétrée passe par le DML (jamais de SQL concaténé).
  • Chaînes dans lang/en/, aucune chaîne en dur.

Livrables

  • Les deux dossiers de plugins.
  • Une note : « ce que fait chaque fichier » pour local_todolist.

✅ Critères de réussite

  • Les deux plugins s’installent (notification de mise à jour de la base) et se désinstallent proprement.
  • La table local_todolist existe (vérifiable) ; le CRUD fonctionne par utilisateur (un user ne voit que ses tâches).
  • La page respecte le pattern sécurisé ; une action sans sesskey est rejetée.
  • La chaîne d’upgrade v2 ajoute la colonne sans perdre les données.
  • Le bloc s’ajoute au tableau de bord, se configure par instance et affiche la progression.
  • Aucun message en mode débogage développeur sur les pages des plugins.

🗺️ Endroits à visiter

EndroitPourquoi y aller
Types de plugins (doc)moodledev.io/docs/apis/plugintypes Choisir local vs block en connaissance de cause
Éditeur XMLDBAdmin → Développement → Éditeur XMLDBGénérer db/install.xml sans l’écrire à la main
Mode débogage développeurAdmin → Développement → DébogageVotre console d’erreurs — activez DEVELOPER
Purge des cachesAdmin → Développement → Purger les cachesRéflexe après chaque changement de structure/lang
Code du cœur : un local_ communautairefilesystem / GitHubVoir un vrai plugin local de A à Z
Code du cœur : blocks/html, blocks/recentlyaccesseditemsblocks/Modèles de blocs simples à imiter
admin/cli/upgrade.phpterminalDéclencher l’upgrade en ligne de commande
Générateur de squelettesPlugin skeleton generator Point de départ conforme aux conventions

💡 Pour un dev React — Un plugin Moodle ressemble à un package d’un monorepo à conventions strictes : version.php = package.json, db/install.xml = une migration, db/access.php = la matrice de permissions, classes/ en autoload PSR-like, templates/*.mustache = vos composants de vue. La grande différence culturelle : on ne fait pas de SQL brut (DML obligatoire) et on ne lit pas $_GET à la main (required_param + sesskey). Ces contrats, une fois intégrés, rendent le reste mécanique.

⚠️ Piège — Après toute modification de db/install.xml, de version.php ou des fichiers de langue, incrémentez la version et purgez les caches, sinon Moodle sert une version périmée et vous débuggez un fantôme. Et n’éditez jamais la base à la main : passez par XMLDB + upgrade.

🚀 Étapes suggérées

  1. Générer le squelette local_todolist (ou créer version.php + lang/).
  2. Éditeur XMLDB → table local_todolistdb/install.xml ; installer.
  3. db/access.php : capability manage.
  4. index.php avec le pattern sécurisé ; affichage vide OK.
  5. Form API : formulaire d’ajout ; insertion DML.
  6. Liste + édition + suppression (avec sesskey).
  7. Renderer + Mustache ; entrée navigation ; settings.php.
  8. Bumper la version → db/upgrade.php ajoute une colonne.
  9. Créer block_progressinfo : get_content, edit_form, l’ajouter au dashboard.

🎁 Bonus

  • Ajoutez un privacy provider (classes/privacy/provider.php) à local_todolist (RGPD, Partie 11).
  • Ajoutez une tâche planifiée (db/tasks.php) qui nettoie les tâches terminées anciennes.
  • Ajoutez un peu de JS AMD au bloc pour cocher une tâche sans recharger.

🔗 Chapitres du cours liés


Projet suivant : Niveau 3 — Module d’activité noté (mod_simplecheck).