<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet title="XSL formatting" type="text/xsl" href="https://dotclear.watch/feed/rss2/xslt" ?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>DotclearWatch / Blog - Mot-clé - theme</title>
    <link>https://dotclear.watch/</link>
    <atom:link href="https://dotclear.watch/feed/tag/theme/rss2" rel="self" type="application/rss+xml" />
    <description>Suivez l'évolution du moteur de blogs Dotclear.</description>
    <language>fr</language>
    <pubDate>Mon, 06 Apr 2026 09:30:20 +0200</pubDate>
    <copyright>Tous droits réservés © Jean-Christian Denis</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>Dotclear</generator>
          <item>
        <title>[2.36] Mode dévelopement pour l'éditeur de thème</title>
        <link>https://dotclear.watch/Billet/%5B2.36%5D-Mode-d%C3%A9velopement-pour-l-%C3%A9diteur-de-th%C3%A8me</link>
        <guid isPermaLink="false">urn:md5:2c74075a43fed6497e4a5ed6a7e86d56</guid>
        <pubDate>Tue, 19 Aug 2025 11:34:00 +0200</pubDate>
        <dc:creator>Jean-Christian Denis</dc:creator>
                  <category>2.36</category>
                          <category>2.36</category>
                  <category>behavior</category>
                  <category>thème</category>
                <description>&lt;p&gt;Dotclear 2.35 introduisait une nouvelle gestion de &lt;a href=&quot;https://open-time.net/post/2025/06/29/Adapter-un-theme-pour-Dotclear-235&quot; hreflang=&quot;fr&quot; title=&quot;Adapter un thème pour Dotclear 2.35 - sur Open-Time&quot;&gt;surcharge de thèmes&lt;/a&gt;, et dans le version 2.36 une option de &lt;a href=&quot;https://open-time.net/post/2025/08/19/La-nouvelle-gestion-des-themes - sur Open-Time&quot; hreflang=&quot;fr&quot; title=&quot;La nouvelle gestion des thèmes&quot;&gt;mode de dévelopement&lt;/a&gt; fait son appartition dans l'éditeur de thème.&lt;/p&gt; &lt;p&gt;&lt;a class=&quot;ref-post&quot; href=&quot;https://dotclear.watch/Billet/2.36&quot; title=&quot;Article rédigé pour Dotclear 2.36&quot;&gt;&lt;img alt=&quot;badge Dotclear 2.36&quot; src=&quot;https://img.shields.io/badge/Dotclear-2.36-blue?style=for-the-badge&quot; /&gt; &lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Le nouveau behavior&amp;nbsp;&lt;strong&gt;themeEditorDevMode&lt;/strong&gt;, si il retourne vrai, permet de modifier sur place les fichiers d'un thème dans l'éditeur de thème.&lt;/p&gt;

&lt;p&gt;Il suffit de l'activer en appelant le beharvior comme suit :&lt;/p&gt;

&lt;pre&gt;
&lt;code class=&quot;language-php&quot;&gt;App::behavior()-&amp;gt;addBehavior('themeEditorDevMode', fn(): bool =&amp;gt; true);&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Un message apparaitra lors de la modification d'un thème.&lt;br /&gt;
&lt;br /&gt;
&lt;a class=&quot;media-link media-center&quot; href=&quot;https://dotclear.watch/public/2.36/dc_2.36_themeeditordevmode.png&quot; title=&quot;Ouvrir le média&quot;&gt;&lt;img alt=&quot;2.36 Theme editor dev mode&quot; class=&quot;media&quot; src=&quot;https://dotclear.watch/public/2.36/.dc_2.36_themeeditordevmode_m.png&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
Le plugin &lt;strong&gt;tidyAdmin &lt;/strong&gt;dans sa version pour Dotclear 2.36 propose une option pour faire cela depuis l'interface utilisateur.&lt;/p&gt;</description>
        
                  <comments>https://dotclear.watch/Billet/%5B2.36%5D-Mode-d%C3%A9velopement-pour-l-%C3%A9diteur-de-th%C3%A8me#comment-form</comments>
          <wfw:comment>https://dotclear.watch/Billet/%5B2.36%5D-Mode-d%C3%A9velopement-pour-l-%C3%A9diteur-de-th%C3%A8me#comment-form</wfw:comment>
          <wfw:commentRss>https://dotclear.watch/feed/atom/comments/432</wfw:commentRss>
              </item>
          <item>
        <title>Le plugin Uninstaller</title>
        <link>https://dotclear.watch/Billet/Le-plugin-Uninstaller</link>
        <guid isPermaLink="false">urn:md5:55fb5b47a5cfa50068daecfa0e19133e</guid>
        <pubDate>Tue, 22 Aug 2023 12:00:00 +0200</pubDate>
        <dc:creator>Jean-Christian Denis</dc:creator>
                  <category>Articles</category>
                          <category>2.28</category>
                  <category>module</category>
                  <category>plugin</category>
                  <category>suppression</category>
                  <category>theme</category>
                <description>&lt;p&gt;La prochaine version 2.28 de Dotclear embarque un nouveau plugin nommé Uninstaller.&lt;/p&gt; &lt;h5&gt;But&lt;/h5&gt;

&lt;p&gt;Le gestionnaire de modules, incorporé au core de Dotclear et servant à la gestion des thèmes et plugins, permet d'installer des modules avec une gestion des actions liées à l'installation à travers le fichier &lt;strong&gt;src/Install.php&lt;/strong&gt; et sa classe idoine, mais lorsqu'il s'agit de désinstaller des plugins ou thèmes, la seule action effectuée est la suppression des fichiers du module.  À aucun moment on ne tient compte de ce que le module a pu ajouter dans les paramètres, les tables, le cache, etc...&lt;br /&gt;
&lt;br /&gt;
Ce manque est désormais comblé par le plugin &lt;strong&gt;Uninstaller&lt;/strong&gt; qui va permettre d'affiner la désinstallation d'un module, en proposant des outils préétablis de suppressions. Il y a deux points de départ de ces désinstallations, soit depuis le gestionnaire de plugins|thèmes avec un bouton &lt;strong&gt;Désinstallation&lt;/strong&gt; qui donnera le choix au super admin de supprimer telle ou telle partie du module, soit directement lors de l'action de suppression d'un module auquel cas des actions définies par le module lui-même seront effectuées directement sans demande de confirmation.&lt;br /&gt;&lt;/p&gt;&lt;a href=&quot;https://dotclear.watch/public/Articles/sshot-uninstaller-01.jpg&quot; title=&quot;Plugin Uninstaller, août 2023&quot;&gt;&lt;figure class=&quot;media-center&quot;&gt;&lt;img src=&quot;https://dotclear.watch/public/Articles/.sshot-uninstaller-01_m.jpg&quot; alt=&quot;Plugin Uninstaller, août 2023&quot; title=&quot;Plugin Uninstaller, août 2023&quot; /&gt;&lt;figcaption&gt;Interface utilisateur du plugin Uninstaller&lt;/figcaption&gt;&lt;/figure&gt;&lt;/a&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h5&gt;Actions&lt;/h5&gt;

&lt;p&gt;Une tâche (Cleaner) permet d'effectuer une action ciblée, les groupes et tâches prédéfinis sont les suivants :&lt;br /&gt;
&lt;strong&gt;Caches :&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;caches.delete&lt;/code&gt; : Effacer le répertoire de caches créé par le module,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;caches.empty&lt;/code&gt; : Vider le répertoire de caches créé par le module,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Logs :&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;logs.delete_all&lt;/code&gt; : Effacer les logs créés par le module,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Plugins :&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;plugins.delete&lt;/code&gt; : Effacer les fichiers du plugins,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Preferences :&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;preferences.delete_global&lt;/code&gt; : Effacer les préférences pour les utilisateurs créées par le module,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;preferences.delete_local&lt;/code&gt; : Effacer les préférences globales créées par le module,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;preferences.delete_all&lt;/code&gt; : Effacer les préférences globales et utilisateurs créées par le module,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;preferences.delete_related&lt;/code&gt; : Effacer une préférence ciblée créé par le module,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Settings :&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;settings.delete_global&lt;/code&gt; : Effacer les préférences pour les blogs créées par le module,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;settings.delete_local&lt;/code&gt; : Effacer les préférences globales créées par le module,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;settings.delete_all&lt;/code&gt; : Effacer les préférences globales et blogs créées par le module,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;settings.delete_related&lt;/code&gt; : Effacer une préférence ciblée créé par le module,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tables :&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tables.delete&lt;/code&gt; : Supprimer une table créée par le module,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tables.empty&lt;/code&gt; : Vider une table créée par le module,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Themes :&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;themes.delete&lt;/code&gt; : Effacer les fichiers du thème,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Vars :&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;vars.delete&lt;/code&gt; : Effacer ou vider le sous répertoire de DC_VAR créé par le module,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Versions :&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;versions.delete&lt;/code&gt; : Supprimer le numéro de version du module ne base&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Intégration&lt;/h5&gt;

&lt;p&gt;Pour utiliser les fonctions de désinstallation prédéfinis, il suffit d'ajouter un fichier &lt;strong&gt;src\Uninstall.php&lt;/strong&gt; contenant sa classe idoine Uninstall dans le module. Le plugin Uninstaller saura trouver et utiliser ce fichier sans déclaration supplémentaire.&lt;br /&gt;
La méthode &lt;strong&gt;addUserAction&lt;/strong&gt; va ajouter une action avec demande de confirmation tandis que la méthode &lt;strong&gt;addDirectAction&lt;/strong&gt; ajoutera une action directe lors de la suppression d'un module.
Exemple complet de fichier :&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
declare(strict_types=1);

namespace Dotclear\Theme\monTheme;

use Dotclear\App;
use Dotclear\Core\Process;
use Dotclear\Plugin\Uninstaller\Uninstaller;

class Uninstall extends Process
{
    public static function init(): bool
    {
        return self::status(My::checkContext(My::UNINSTALL));
    }

    public static function process(): bool
    {
        // Par sécurtié, on vérifie l&amp;#039;existence du plugin Uninstaller, même si c&amp;#039;est lui qui a dû appeler ce script
        if (!self::status() || !App::plugins()-&amp;gt;moduleExists(&amp;#039;Uninstaller&amp;#039;)) {
            return false;
        }

        // On récupère l&amp;#039;instance singleton de Uninstaller
        Uninstaller::instance()
            // Action utilisateur pour effacer les paramètres aillant l&amp;#039;espace de nom du module
            -&amp;gt;addUserAction(
                &amp;#039;settings&amp;#039;,
                &amp;#039;delete_all&amp;#039;,
                My::id()
            )
            // Action utilisateur pour effacer les fichiers du module
            -&amp;gt;addUserAction(
                &amp;#039;plugins&amp;#039;,
                &amp;#039;delete&amp;#039;,
                My::id()
            )
            // Action utilisateur pour effacer le numéro de version en base du module
            -&amp;gt;addUserAction(
                &amp;#039;versions&amp;#039;,
                &amp;#039;delete&amp;#039;,
                My::id()
            )
            // Action directe pour effacer les fichiers du module
            -&amp;gt;addDirectAction(
                &amp;#039;plugins&amp;#039;,
                &amp;#039;delete&amp;#039;,
                My::id()
            )
            // Action directe pour effacer le numéro de version en base du module
            -&amp;gt;addDirectAction(
                &amp;#039;versions&amp;#039;,
                &amp;#039;delete&amp;#039;,
                My::id()
            )
        ;

        // aucune action spécifique, on retourne donc false
        return false;
    }
}&lt;/code&gt;&lt;/pre&gt;

&lt;h5&gt;Extensions&lt;/h5&gt;

&lt;p&gt;Il est possible d'aller plus loin en ajoutant des actions spécifiques qui n'existent pas dans la livraison du plugin Uninstaller.&lt;br /&gt;
Pour des actions avec confirmation utilisateur on va simplement compléter la classe précédente comme suit :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;?php
declare(strict_types=1);

namespace Dotclear\Theme\monTheme;

use Dotclear\App;
use Dotclear\Core\Process;
use Dotclear\Helper\Html\Form\Para;
use Dotclear\Helper\Html\Form\Checkbox;
use Dotclear\Helper\Html\Form\Label;
use Dotclear\Plugin\Uninstaller\Uninstaller;

class Uninstall extends Process
{
    public static function init(): bool
    {
        return self::status(My::checkContext(My::UNINSTALL));
    }

    public static function process(): bool
    {
        // Par sécurtié, on vérifie l&amp;#039;existence du plugin Uninstaller, même si c&amp;#039;est lui qui a dû appeler ce script
        if (!self::status() || !App::plugins()-&amp;gt;moduleExists(&amp;#039;Uninstaller&amp;#039;)) {
            return false;
        }

        // ... ici les actions prédéfinies utilisateur et directes ne sont pas affichées cf exemple ci-dessus

        if (!empty($_POST[&amp;#039;mon_action_perso&amp;#039;]) {

            // Ici on exécute la tâche de supprimer la choucroute

        }

        // on retourne true pour indiquer qu&amp;#039;on a un formulaire
        return true;
    }

    public static function render(): void
    {
        if (!self::status()) {
            return;
        }

        // On affiche le formulaire spécial
        echo (new Para())
            -&amp;gt;items([
                (new Checkbox(&amp;#039;mon_action_perso&amp;#039;, true))
                    -&amp;gt;value(1),
                (new Label(&amp;#039;supprimer la choucroute&amp;#039;, Label::OUTSIDE_LABEL_AFTER))
                    -&amp;gt;for(&amp;#039;mon_action_perso&amp;#039;)
                    -&amp;gt;class(&amp;#039;classic&amp;#039;),
            ])
            -&amp;gt;render(); 
    }
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Il est possible d'aller encore plus loin pour créer des actions spécifiques plus poussées, il faut alors créer un Cleaner et le déclarer de la même manière que ceux du plugin Uninstaller. Voir les fichiers &lt;strong&gt;Prepend.php&lt;/strong&gt; pour la déclaration d'un Cleaner et le répertoire &lt;strong&gt;/src/Task&lt;/strong&gt; pour des exemples de tâches.&lt;br /&gt;&lt;/p&gt;

&lt;h5&gt;NOTE&lt;/h5&gt;

&lt;p&gt;Pour des raisons techniques les actions directes ne sont pas effectuées sur les modules installés en double, et ce même si le bouton &lt;q&gt;Désinstaller&lt;/q&gt; est présent.&lt;br /&gt;
&lt;br /&gt;
Les informations distillées ici sont non exhaustives et pourront être complétées à l'avenir, elles ont été écrites d'après la version 2.28 de Dotclear.&lt;br /&gt;&lt;/p&gt;</description>
        
                  <comments>https://dotclear.watch/Billet/Le-plugin-Uninstaller#comment-form</comments>
          <wfw:comment>https://dotclear.watch/Billet/Le-plugin-Uninstaller#comment-form</wfw:comment>
          <wfw:commentRss>https://dotclear.watch/feed/atom/comments/46</wfw:commentRss>
              </item>
          <item>
        <title>Fichier Install d'un module</title>
        <link>https://dotclear.watch/Billet/Fichier-Install-d-un-module</link>
        <guid isPermaLink="false">urn:md5:374cf218364b206c7b7fe9a6bba42317</guid>
        <pubDate>Sun, 16 Jul 2023 20:51:00 +0100</pubDate>
        <dc:creator>Jean-Christian Denis</dc:creator>
                  <category>2.27</category>
                          <category>2.27</category>
                  <category>admin</category>
                  <category>install</category>
                  <category>module</category>
                  <category>plugin</category>
                  <category>structure</category>
                  <category>theme</category>
                  <category>update</category>
                <description>&lt;p&gt;Le fichier &lt;strong&gt;Install.php&lt;/strong&gt;, placé dans &lt;a href=&quot;https://dotclear.watch/Billet/Structure-d-un-module&quot;&gt;le dossier src&lt;/a&gt; du module, permet d'effectuer ses opérations d'installation et de mise à jour.&lt;/p&gt; &lt;p&gt;Le fichier &lt;strong&gt;Install.php&lt;/strong&gt; fait partie du processus reconnu par le gestionnaire de modules, il est donc automatiquement pris en compte coté admin si il existe.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Il est placé dans le sous dossier &lt;code&gt;src&lt;/code&gt; du module,&lt;/li&gt;
&lt;li&gt;Il contient une classe du nom de &lt;code&gt;Install&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Il est dans l'espace de nom PHP &lt;code&gt;Dotclear\Plugin\monPlugin&lt;/code&gt; ou &lt;code&gt;Dotclear\Theme\monTheme&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;La classe doit étendre &lt;a href=&quot;https://dotclear.watch/Billet/La-class-Process&quot;&gt;la classe Process&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;Seules les méthodes &lt;code&gt;init()&lt;/code&gt; et &lt;code&gt;process()&lt;/code&gt; sont utilisées,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ce fichier est chargé en préambule de la page d'accueil de l'admin, de la page de gestion de l'apparence du blog, et de la page de gestion des plugins. Généralement il permet d'enregistrer des paramètres, de créer des tables, etc.&lt;br /&gt;
La méthode &lt;code&gt;init()&lt;/code&gt; de la classe &lt;strong&gt;doit&lt;/strong&gt; vérifier que la version installée n'existe pas ou qu'elle est à mettre à jour, elle doit renvoyer &lt;code&gt;false&lt;/code&gt; si il n'y a pas besoin d'effectuer ces opérations d'installation / mise à jour. Pour aider, &lt;a href=&quot;https://dotclear.watch/Billet/Les-classes-de-module-My&quot;&gt;la classe My&lt;/a&gt; embarque un contexte qui permet cela &lt;code&gt;My::checkContext(My::INSTALL)&lt;/code&gt;.&lt;br /&gt;
&lt;br /&gt;
Exemple du plugin blogroll de la distribution qui ajoute une table à la base de données :&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
declare(strict_types=1);

namespace Dotclear\Plugin\blogroll;

use dcCore;
use Dotclear\Core\Process;
use Dotclear\Database\Structure;
use initBlogroll;

class Install extends Process
{
    public static function init(): bool
    {
        return self::status(My::checkContext(My::INSTALL));
    }

    public static function process(): bool
    {
        if (!self::status()) {
            return false;
        }

        $schema = new Structure(dcCore::app()-&amp;gt;con, dcCore::app()-&amp;gt;prefix);

        $schema-&amp;gt;{initBlogroll::LINK_TABLE_NAME}
            -&amp;gt;link_id(&amp;#039;bigint&amp;#039;, 0, false)
            -&amp;gt;blog_id(&amp;#039;varchar&amp;#039;, 32, false)
            -&amp;gt;link_href(&amp;#039;varchar&amp;#039;, 255, false)
            -&amp;gt;link_title(&amp;#039;varchar&amp;#039;, 255, false)
            -&amp;gt;link_desc(&amp;#039;varchar&amp;#039;, 255, true)
            -&amp;gt;link_lang(&amp;#039;varchar&amp;#039;, 5, true)
            -&amp;gt;link_xfn(&amp;#039;varchar&amp;#039;, 255, true)
            -&amp;gt;link_position(&amp;#039;integer&amp;#039;, 0, false, 0)

            -&amp;gt;primary(&amp;#039;pk_link&amp;#039;, &amp;#039;link_id&amp;#039;)
            -&amp;gt;index(&amp;#039;idx_link_blog_id&amp;#039;, &amp;#039;btree&amp;#039;, &amp;#039;blog_id&amp;#039;)
            -&amp;gt;reference(&amp;#039;fk_link_blog&amp;#039;, &amp;#039;blog_id&amp;#039;, &amp;#039;blog&amp;#039;, &amp;#039;blog_id&amp;#039;, &amp;#039;cascade&amp;#039;, &amp;#039;cascade&amp;#039;)
        ;

        (new Structure(dcCore::app()-&amp;gt;con, dcCore::app()-&amp;gt;prefix))-&amp;gt;synchronize($schema);

        return true;
    }
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;
&lt;em&gt;&lt;q&gt;Le contenu de ce document a été écrit suivant le code de la version 2.27 de Dotclear.&lt;/q&gt;&lt;/em&gt;&lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Fichier Config d'un module</title>
        <link>https://dotclear.watch/Billet/Fichier-Config-d-un-module</link>
        <guid isPermaLink="false">urn:md5:996cf791be01db13a047003087fe99f3</guid>
        <pubDate>Sun, 16 Jul 2023 14:03:00 +0100</pubDate>
        <dc:creator>Jean-Christian Denis</dc:creator>
                  <category>2.27</category>
                          <category>2.27</category>
                  <category>admin</category>
                  <category>backend</category>
                  <category>config</category>
                  <category>module</category>
                  <category>plugin</category>
                  <category>structure</category>
                  <category>theme</category>
                <description>&lt;p&gt;Le fichier &lt;strong&gt;Config.php&lt;/strong&gt;, placé dans &lt;a href=&quot;https://dotclear.watch/Billet/Structure-d-un-module&quot;&gt;le dossier src&lt;/a&gt; du module, simplifie la gestion de sa configuration.&lt;/p&gt; &lt;p&gt;Le fichier &lt;strong&gt;Config.php&lt;/strong&gt; fait partie du processus reconnu par le gestionnaire de modules, il est donc automatiquement pris en compte dans l'administration si il existe.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Il est placé dans le sous dossier &lt;code&gt;src&lt;/code&gt; du module,&lt;/li&gt;
&lt;li&gt;Il contient une classe du nom de &lt;code&gt;Config&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Il est dans l'espace de nom PHP &lt;code&gt;Dotclear\Plugin\monPlugin&lt;/code&gt; ou &lt;code&gt;Dotclear\Theme\monTheme&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;La classe doit étendre &lt;a href=&quot;https://dotclear.watch/Billet/La-class-Process&quot;&gt;la classe Process&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;Les 3 méthodes &lt;code&gt;init()&lt;/code&gt; et &lt;code&gt;process()&lt;/code&gt; et &lt;code&gt;render()&lt;/code&gt; sont utilisées,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cette classe simplifie la gestion de la configuration d'un module dans le sens où la partie construction de la page est déjà effectuée par le gestionnaire de modules. Seul le traitement des valeurs et le contenu du formulaire sont à la charge de la classe Config. Un lien vers cette page sera ajouté à la liste de plugins ou sur les thèmes de la page de gestion d'apparence du blog. Un lien sera également ajouté en bas de page principale de gestion du plugin si elle existe.&lt;br /&gt;
&lt;br /&gt;
Exemple complet du fichier config du thème customCSS de la distribution :&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
namespace Dotclear\Theme\customCSS;

use dcCore;
use Dotclear\Core\Backend\Notices;
use Dotclear\Core\Process;
use Dotclear\Helper\File\Path;
use Dotclear\Helper\Html\Html;
use Dotclear\Helper\L10n;
use Exception;
use form;

class Config extends Process
{
    public static function init(): bool
    {
        if (My::checkContext(My::CONFIG)) {
            My::l10n(&amp;#039;main&amp;#039;);
            dcCore::app()-&amp;gt;admin-&amp;gt;css_file = Path::real(dcCore::app()-&amp;gt;blog-&amp;gt;public_path) . &amp;#039;/custom_style.css&amp;#039;;

            if (!is_file(dcCore::app()-&amp;gt;admin-&amp;gt;css_file) &amp;amp;&amp;amp; !is_writable(dirname(dcCore::app()-&amp;gt;admin-&amp;gt;css_file))) {
                throw new Exception(
                    sprintf(
                        __(&amp;#039;File %s does not exist and directory %s is not writable.&amp;#039;),
                        dcCore::app()-&amp;gt;admin-&amp;gt;css_file,
                        dirname(dcCore::app()-&amp;gt;admin-&amp;gt;css_file)
                    )
                );
            }
            self::status(true);
        }

        return self::status();
    }

    public static function process(): bool
    {
        if (!self::status()) {
            return false;
        }

        if (isset($_POST[&amp;#039;css&amp;#039;])) {
            @$fp = fopen(dcCore::app()-&amp;gt;admin-&amp;gt;css_file, &amp;#039;wb&amp;#039;);
            fwrite($fp, $_POST[&amp;#039;css&amp;#039;]);
            fclose($fp);

            Notices::message(__(&amp;#039;Style sheet upgraded.&amp;#039;), true, true);
        }

        return true;
    }

    public static function render(): void
    {
        if (!self::status()) {
            return;
        }

        $css_content = is_file(dcCore::app()-&amp;gt;admin-&amp;gt;css_file) ? file_get_contents(dcCore::app()-&amp;gt;admin-&amp;gt;css_file) : &amp;#039;&amp;#039;;

        echo
        &amp;#039;&amp;lt;p class=&amp;quot;area&amp;quot;&amp;gt;&amp;lt;label&amp;gt;&amp;#039; . __(&amp;#039;Style sheet:&amp;#039;) . &amp;#039;&amp;lt;/label&amp;gt; &amp;#039; .
        form::textarea(&amp;#039;css&amp;#039;, 60, 20, Html::escapeHTML($css_content)) . &amp;#039;&amp;lt;/p&amp;gt;&amp;#039;;
    }
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;
&lt;em&gt;&lt;q&gt;Le contenu de ce document a été écrit suivant le code de la version 2.27 de Dotclear.&lt;/q&gt;&lt;/em&gt;&lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Fichier Frontend d'un module</title>
        <link>https://dotclear.watch/Billet/Fichier-Frontend-d-un-module</link>
        <guid isPermaLink="false">urn:md5:bc70744ae6bb3074af21de368e3b26fd</guid>
        <pubDate>Sun, 16 Jul 2023 13:48:00 +0100</pubDate>
        <dc:creator>Jean-Christian Denis</dc:creator>
                  <category>2.27</category>
                          <category>2.27</category>
                  <category>frontend</category>
                  <category>module</category>
                  <category>plugin</category>
                  <category>public</category>
                  <category>structure</category>
                  <category>theme</category>
                <description>&lt;p&gt;Le fichier &lt;strong&gt;Frontend.php&lt;/strong&gt;, placé dans &lt;a href=&quot;https://dotclear.watch/Billet/Structure-d-un-module&quot;&gt;le dossier src&lt;/a&gt; du module, permet de préparer le nécessaire à son fonctionnement en partie public.&lt;/p&gt; &lt;p&gt;Le fichier &lt;strong&gt;Frontend.php&lt;/strong&gt; fait partie du processus reconnu par le gestionnaire de modules, il est donc automatiquement pris en compte coté public si il existe.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Il est placé dans le sous dossier &lt;code&gt;src&lt;/code&gt; du module,&lt;/li&gt;
&lt;li&gt;Il contient une classe du nom de &lt;code&gt;Frontend&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Il est dans l'espace de nom PHP &lt;code&gt;Dotclear\Plugin\monPlugin&lt;/code&gt; ou &lt;code&gt;Dotclear\Theme\monTheme&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;La classe doit étendre &lt;a href=&quot;https://dotclear.watch/Billet/La-class-Process&quot;&gt;la classe Process&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;Seules les méthodes &lt;code&gt;init()&lt;/code&gt; et &lt;code&gt;process()&lt;/code&gt; sont utilisées,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Généralement cette classe est utilisée pour préparer des variables nécessaires au fonctionnement du module, déclarer ses templates, ajouter ses behaviors, pour la partie publique des blogs.&lt;br /&gt;
&lt;br /&gt;
Exemple du fichier Frontend.php du plugin &lt;strong&gt;blogroll&lt;/strong&gt; de la distribution :&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
declare(strict_types=1);

namespace Dotclear\Plugin\blogroll;

use dcCore;
use Dotclear\Core\Process;

class Frontend extends Process
{
    public static function init(): bool
    {
        return self::status(My::checkContext(My::FRONTEND));
    }

    public static function process(): bool
    {
        if (!self::status()) {
            return false;
        }

        dcCore::app()-&amp;gt;tpl-&amp;gt;addValue(&amp;#039;Blogroll&amp;#039;, [FrontendTemplate::class, &amp;#039;blogroll&amp;#039;]);
        dcCore::app()-&amp;gt;tpl-&amp;gt;addValue(&amp;#039;BlogrollXbelLink&amp;#039;, [FrontendTemplate::class, &amp;#039;blogrollXbelLink&amp;#039;]);

        dcCore::app()-&amp;gt;addBehaviors([
            &amp;#039;initWidgets&amp;#039;        =&amp;gt; [Widgets::class, &amp;#039;initWidgets&amp;#039;],
            &amp;#039;initDefaultWidgets&amp;#039; =&amp;gt; [Widgets::class, &amp;#039;initDefaultWidgets&amp;#039;],
        ]);

        return true;
    }
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;
&lt;em&gt;&lt;q&gt;Le contenu de ce document a été écrit suivant le code de la version 2.27 de Dotclear.&lt;/q&gt;&lt;/em&gt;&lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Fichier Backend d'un module</title>
        <link>https://dotclear.watch/Billet/Fichier-Backend-d-un-module</link>
        <guid isPermaLink="false">urn:md5:fa3c0167756c3590593aa2a46afc6459</guid>
        <pubDate>Sun, 16 Jul 2023 13:36:00 +0100</pubDate>
        <dc:creator>Jean-Christian Denis</dc:creator>
                  <category>2.27</category>
                          <category>2.27</category>
                  <category>admin</category>
                  <category>backend</category>
                  <category>module</category>
                  <category>plugin</category>
                  <category>structure</category>
                  <category>theme</category>
                <description>&lt;p&gt;Le fichier &lt;strong&gt;Backend.php&lt;/strong&gt;, placé dans &lt;a href=&quot;https://dotclear.watch/Billet/Structure-d-un-module&quot;&gt;le dossier src&lt;/a&gt; du module, permet de préparer le nécessaire à son fonctionnement pour sa partie administration.&lt;/p&gt; &lt;p&gt;Le fichier &lt;strong&gt;Backend.php&lt;/strong&gt; fait partie du processus reconnu par le gestionnaire de modules, il est donc automatiquement pris en compte dans l'administration si il existe.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Il est placé dans le sous dossier &lt;code&gt;src&lt;/code&gt; du module,&lt;/li&gt;
&lt;li&gt;Il contient une classe du nom de &lt;code&gt;Backend&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Il est dans l'espace de nom PHP &lt;code&gt;Dotclear\Plugin\monPlugin&lt;/code&gt; ou &lt;code&gt;Dotclear\Theme\monTheme&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;La classe doit étendre &lt;a href=&quot;https://dotclear.watch/Billet/La-class-Process&quot;&gt;la classe Process&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;Seules les méthodes &lt;code&gt;init()&lt;/code&gt; et &lt;code&gt;process()&lt;/code&gt; sont utilisées,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Généralement cette classe est utilisée pour préparer des variables nécessaires au fonctionnement du module, ajouter ses menus, favoris, behaviors, pour la partie administration des blogs.&lt;br /&gt;
&lt;br /&gt;
Exemple du fichier Backend.php du plugin &lt;strong&gt;aboutConfig&lt;/strong&gt; de la distribution :&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
declare(strict_types=1);

namespace Dotclear\Plugin\aboutConfig;

use Dotclear\Core\Backend\Menus;
use Dotclear\Core\Process;

class Backend extends Process
{
    public static function init(): bool
    {
        return self::status(My::checkContext(My::BACKEND));
    }

    public static function process(): bool
    {
        if (self::status()) {
            My::addBackendMenuItem(Menus::MENU_SYSTEM);
        }

        return self::status();
    }
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;
&lt;em&gt;&lt;q&gt;Le contenu de ce document a été écrit suivant le code de la version 2.27 de Dotclear.&lt;/q&gt;&lt;/em&gt;&lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Fichier Prepend d'un module</title>
        <link>https://dotclear.watch/Billet/Fichier-Prepend-d-un-module</link>
        <guid isPermaLink="false">urn:md5:35e77dec2b2fe2b2ee0241ae66d0a41c</guid>
        <pubDate>Sun, 16 Jul 2023 10:38:00 +0100</pubDate>
        <dc:creator>Jean-Christian Denis</dc:creator>
                  <category>2.27</category>
                          <category>2.27</category>
                  <category>admin</category>
                  <category>module</category>
                  <category>plugin</category>
                  <category>prepend</category>
                  <category>public</category>
                  <category>structure</category>
                  <category>theme</category>
                <description>&lt;p&gt;Le fichier &lt;strong&gt;Prepend.php&lt;/strong&gt;, placé dans &lt;a href=&quot;https://dotclear.watch/Billet/Structure-d-un-module&quot;&gt;le dossier src&lt;/a&gt; du module, permet de préparer le nécessaire à son fonctionnement.&lt;/p&gt; &lt;p&gt;Le fichier &lt;strong&gt;Prepend.php&lt;/strong&gt; fait partie du processus reconnu par le gestionnaire de modules, il est donc automatiquement pris en compte si il existe.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Il est placé dans le sous dossier &lt;code&gt;src&lt;/code&gt; du module,&lt;/li&gt;
&lt;li&gt;Il contient une classe du nom de &lt;code&gt;Prepend&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Il est dans l'espace de nom PHP &lt;code&gt;Dotclear\Plugin\monPlugin&lt;/code&gt; ou &lt;code&gt;Dotclear\Theme\monTheme&lt;/code&gt;,,&lt;/li&gt;
&lt;li&gt;La classe doit étendre &lt;a href=&quot;https://dotclear.watch/Billet/La-class-Process&quot;&gt;la classe Process&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;Seuls les méthodes &lt;code&gt;init()&lt;/code&gt; et &lt;code&gt;process()&lt;/code&gt; sont utilisées,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Généralement cette classe est utilisée pour préparer des variables nécessaires au fonctionnement global du module ou pour ajouter des behaviors, à la fois coté admin &lt;strong&gt;et&lt;/strong&gt; coté public. Si ces définitions sont propres à l'admin ou au public, il faut utiliser les fichiers Backend.php ou Frontend.php.&lt;br /&gt;
&lt;br /&gt;
Exemple du fichier Prepend.php du plugin &lt;strong&gt;blogroll&lt;/strong&gt; de la distribution :&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
declare(strict_types=1);

namespace Dotclear\Plugin\blogroll;

use dcCore;
use Dotclear\Core\Process;

class Prepend extends Process
{
    public static function init(): bool
    {
        return self::status(My::checkContext(My::PREPEND));
    }

    public static function process(): bool
    {
        if (!self::status()) {
            return false;
        }

        dcCore::app()-&amp;gt;url-&amp;gt;register(&amp;#039;xbel&amp;#039;, &amp;#039;xbel&amp;#039;, &amp;#039;^xbel(?:\/?)$&amp;#039;, [FrontendUrl::class, &amp;#039;xbel&amp;#039;]);

        return true;
    }
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;
&lt;em&gt;&lt;q&gt;Le contenu de ce document a été écrit suivant le code de la version 2.27 de Dotclear.&lt;/q&gt;&lt;/em&gt;&lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Fichier de dépôt tiers</title>
        <link>https://dotclear.watch/Billet/Fichier-de-d%C3%A9p%C3%B4t-tiers</link>
        <guid isPermaLink="false">urn:md5:863e109677409c77fbe94c8592ae92d0</guid>
        <pubDate>Fri, 14 Jul 2023 20:25:00 +0100</pubDate>
        <dc:creator>Jean-Christian Denis</dc:creator>
                  <category>2.27</category>
                          <category>2.27</category>
                  <category>depot</category>
                  <category>module</category>
                  <category>plug</category>
                  <category>repository</category>
                  <category>theme</category>
                <description>&lt;p&gt;Depuis quelques versions le gestionnaire de modules de Dotclear supporte les dépôts tiers. Le fichier dcstore.xml se trouvant à la &lt;a href=&quot;https://dotclear.watch/Billet/Structure-d-un-module&quot;&gt;racine du module&lt;/a&gt; permet de définir ce dépôt.&lt;/p&gt; &lt;p&gt;En réalité l'emplacement de ce fichier n'est pas dans le module mais là où est hébergé le dépôt tiers ! Par commodité et comme souvent le dépôt tiers est un dépôt github en le plaçant dans le module, le développeur garantit qu'il sera présent sur son dépôt.&lt;br /&gt;
L'emplacement final de ce fichier est renseigné dans le &lt;a href=&quot;https://dotclear.watch/Billet/Fichier-de-d%C3%A9finition-d-un-module&quot;&gt;fichier de définition du module&lt;/a&gt; dans le paramètre &lt;code&gt;'repository'&lt;/code&gt;.&lt;br /&gt;
Son contenu est écrit en xml et est calqué sur le &lt;a href=&quot;https://dotaddict.org&quot; hreflang=&quot;fr&quot; title=&quot;Dotaddict&quot;&gt;dépôt officiel Dotaddict.org&lt;/a&gt;. Voici l'exemple du plugin tweakStore :&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-xml&quot;&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;
&amp;lt;modules xmlns:da=&amp;quot;http://dotaddict.org/da/&amp;quot;&amp;gt;
  &amp;lt;module id=&amp;quot;tweakStores&amp;quot;&amp;gt;
    &amp;lt;name&amp;gt;Tweak stores&amp;lt;/name&amp;gt;
    &amp;lt;version&amp;gt;0.8&amp;lt;/version&amp;gt;
    &amp;lt;author&amp;gt;Jean-Christian Denis and Contributors&amp;lt;/author&amp;gt;
    &amp;lt;desc&amp;gt;Helper to manage external repositories&amp;lt;/desc&amp;gt;
    &amp;lt;file&amp;gt;https://github.com/JcDenis/tweakStores/releases/download/v0.8/plugin-tweakStores.zip&amp;lt;/file&amp;gt;
    &amp;lt;da:dcmin&amp;gt;2.26&amp;lt;/da:dcmin&amp;gt;
    &amp;lt;da:details&amp;gt;https://plugins.dotaddict.org/dc2/details/tweakStores&amp;lt;/da:details&amp;gt;
    &amp;lt;da:support&amp;gt;https://github.com/JcDenis/tweakStores&amp;lt;/da:support&amp;gt;
  &amp;lt;/module&amp;gt;
&amp;lt;/modules&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Pas besoin d'explication sur son contenu, il reprend en grande partie les informations présentes dans define.php du module en ajoutant le lien vers le fichier Zip du module.&lt;br /&gt;
&lt;em&gt;N.D.L.R : En théorie un fichier de dépôt tiers pourrait contenir les informations de plusieurs modules, en pratique, je n'ai pas testé.&lt;/em&gt;&lt;br /&gt;
&lt;br /&gt;
Il existe &lt;a href=&quot;https://plugins.dotaddict.org/dc2/details/tweakStores&quot; hreflang=&quot;fr&quot; title=&quot;Plugin tweakStores&quot;&gt;des plugins&lt;/a&gt; qui permettent de créer automatiquement ce fichier et également &lt;a href=&quot;https://open-time.net/post/2023/05/25/One-click-only&quot; hreflang=&quot;fr&quot; title=&quot;One click only - Open Time&quot;&gt;des scripts&lt;/a&gt;. (Liens non exhaustifs à titre d'exemple.)&lt;br /&gt;
&lt;br /&gt;
&lt;em&gt;&lt;q&gt;Le contenu de ce document a été écrit suivant le code de la version 2.27 de Dotclear.&lt;/q&gt;&lt;/em&gt;&lt;/p&gt;</description>
        
                  <comments>https://dotclear.watch/Billet/Fichier-de-d%C3%A9p%C3%B4t-tiers#comment-form</comments>
          <wfw:comment>https://dotclear.watch/Billet/Fichier-de-d%C3%A9p%C3%B4t-tiers#comment-form</wfw:comment>
          <wfw:commentRss>https://dotclear.watch/feed/atom/comments/50</wfw:commentRss>
              </item>
          <item>
        <title>Fichier init d'un module</title>
        <link>https://dotclear.watch/Billet/Fichier-init-d-un-module</link>
        <guid isPermaLink="false">urn:md5:7edc6ffa28c9cee7ae40435284934ed9</guid>
        <pubDate>Fri, 14 Jul 2023 19:54:00 +0100</pubDate>
        <dc:creator>Jean-Christian Denis</dc:creator>
                  <category>2.27</category>
                          <category>2.27</category>
                  <category>init</category>
                  <category>module</category>
                  <category>plugin</category>
                  <category>theme</category>
                <description>&lt;p&gt;Le fichier &lt;code&gt;_init.php&lt;/code&gt; d'un module permet principalement d'initialiser des constantes sans même que le module soit chargé. Ce fichier se place à la &lt;a href=&quot;https://dotclear.watch/Billet/Structure-d-un-module&quot;&gt;racine du module&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Le rôle de ce fichier est de pouvoir charger des constantes avant même que le module soit chargé afin de partager avec d'autres modules certaines valeurs et ceci même si le module est désactivé.&lt;br /&gt;
Ce fonctionnement est spécial et ce fichier ne doit contenir que le minimum d'informations qui devront si possible ne pas changer à chaque version du module. &lt;em&gt;(Sinon tout l'intérêt de ce fichier est perdu.)&lt;/em&gt;&lt;br /&gt;
Généralement la classe contenue dans ce fichier permet de définir des noms de permissions ou de tables.&lt;br /&gt;
Exemple tiré du plugin &lt;strong&gt;blogroll&lt;/strong&gt; de la distribution :&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
// aucun espace de nom PHP n&amp;#039;est déclaré

// Cette classe sera accessible à tous les autres modules
class initBlogroll
{
    // On définit le nom de la permission liée à blogroll
    public const PERMISSION_BLOGROLL = &amp;#039;blogroll&amp;#039;;

    // On définit le nom de la table de base de données de blogroll
    public const LINK_TABLE_NAME = &amp;#039;link&amp;#039;;
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Il est recommandé de garder des noms de classe et de constantes dans le style de l'exemple ci-dessus.&lt;br /&gt;
Cette classe va permettre par exemple au plugin blogroll lui même de définir ses permissions dans son &lt;a href=&quot;https://dotclear.watch/Billet/Fichier-de-d%C3%A9finition-d-un-module&quot;&gt;fichier de définition&lt;/a&gt; :&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
 
$this-&amp;gt;registerModule(
    // ...
    [
        &amp;#039;permissions&amp;#039; =&amp;gt; dcCore::app()-&amp;gt;auth-&amp;gt;makePermissions([
            initBlogroll::PERMISSION_BLOGROLL,
        ]),
        &amp;#039;type&amp;#039;        =&amp;gt; &amp;#039;plugin&amp;#039;,
    ]
);&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;
&lt;em&gt;&lt;q&gt;Le contenu de ce document a été écrit suivant le code de la version 2.27 de Dotclear.&lt;/q&gt;&lt;/em&gt;&lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Les classes de module My</title>
        <link>https://dotclear.watch/Billet/Les-classes-de-module-My</link>
        <guid isPermaLink="false">urn:md5:56d4aa0e1641bb124a2682004f6231c5</guid>
        <pubDate>Fri, 14 Jul 2023 10:27:00 +0100</pubDate>
        <dc:creator>Jean-Christian Denis</dc:creator>
                  <category>2.27</category>
                          <category>2.27</category>
                  <category>module</category>
                  <category>my</category>
                  <category>plugin</category>
                  <category>theme</category>
                <description>&lt;p&gt;Dotclear &lt;a href=&quot;https://dotclear.watch/Billet/Release-2.27&quot;&gt;version 2.27&lt;/a&gt; propose pour les plugins et thèmes des classes d'aide pour simplifier l'écriture du code.&lt;/p&gt; &lt;p&gt;Deux classes My (qui étendent une troisième commune nommé &lt;code&gt;MyModule&lt;/code&gt;) sont disponibles, &lt;code&gt;MyPlugin&lt;/code&gt; pour les plugins et &lt;code&gt;MyTheme&lt;/code&gt; pour les thèmes, elle fournissent des méthodes statiques qui vont simplifier l'écriture des modules.&lt;/p&gt;

&lt;h5&gt;Inclusion&lt;/h5&gt;

&lt;p&gt;Pour les utiliser il suffit d'inclure dans le dossier &lt;code&gt;src&lt;/code&gt; du module un fichier My.php avec le contenu suivant :&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
/**
 * Mettre ici les informations de licence.
 */
declare(strict_types=1);

namespace Dotclear\Plugin\monPlugin;

use Dotclear\Module\MyPlugin;

class My extends MyPlugin
{
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A adapter pour un thème. Il possible d'ajouter ses propres méthodes à cette classe tant que ça n'interfère pas avec celles de MyPlugin, MyTheme et MyModule.&lt;br /&gt;&lt;/p&gt;

&lt;h5&gt;Utilisation&lt;/h5&gt;

&lt;p&gt;Ensuite il sera possible d'utiliser toutes les méthodes de MyPlugin (MyTheme) dans les classes du plugin (thème).&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
namespace Dotclear\Plugin\monPlugin;

use Dotclear\Core\Process;
use Dotclear\Core\Backend\Page;

// Page principale de gestion du plugin
class Manage extends Process
{
    public static function init(): bool
    {
        // On vérifie que l&amp;#039;utilisateur à le droit d&amp;#039;exercer dans ce contexte
        return self::status(My::checkContext(My::MANAGE));
    }

    public static function process(): bool
    {
        if (!empty($_POST[&amp;#039;step&amp;#039;])) {
            // ...

            // On redirige la page à l&amp;#039;aide de My
            My::redirect([&amp;#039;step&amp;#039; =&amp;gt; 2]);
        }
    }

    public static function render(): void
    {
        // On utilise la classe My pour trouver le nom du plugin et des fichiers
        Page::openModule(
            My::name(),
            My::cssLoad(&amp;#039;backend&amp;#039;)
        );
    }
}&lt;/code&gt;&lt;/pre&gt;

&lt;h5&gt;Méthodes&lt;/h5&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;My::define()&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;protected static function define(): dcModuleDefine&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Cette méthode renvoie l'instance de définition du module.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;&lt;code&gt;My::checkContext()&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;protected static function checkContext(int $context): bool&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Cette méthode permet de vérifier que l'utilisateur à le droit d'exercer dans un certain contexte, elle renvoie &lt;strong&gt;true&lt;/strong&gt; si l'utilisateur à assez de droits, &lt;strong&gt;false&lt;/strong&gt; sinon. Elle prend en paramètre le contexte qui doit être vérifier. La liste des contextes prédéfinis est disponible dans les constantes de la classe My :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;0&lt;/strong&gt; : &lt;code&gt;INSTALL&lt;/code&gt; : Install context&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;1&lt;/strong&gt; : &lt;code&gt;PREPEND&lt;/code&gt; : Prepend context&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2&lt;/strong&gt; : &lt;code&gt;FRONTEND&lt;/code&gt; : Frontend context&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;3&lt;/strong&gt; : &lt;code&gt;BACKEND&lt;/code&gt; : Backend context (usually when the connected user may access at least one functionnality of this module)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;4&lt;/strong&gt; : &lt;code&gt;MANAGE &lt;/code&gt; : Manage context (main page of module)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;5&lt;/strong&gt; : &lt;code&gt;CONFIG&lt;/code&gt; : Config context (config page of module)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;6&lt;/strong&gt; : &lt;code&gt;MENU&lt;/code&gt; : Menu context (adding a admin menu item)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;7&lt;/strong&gt; : &lt;code&gt;WIDGETS&lt;/code&gt; : Widgets context (managing blog's widgets)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;8&lt;/strong&gt; : &lt;code&gt;UNINSTALL&lt;/code&gt; : Uninstall context (réservé pour le plugin Uninstaller)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br /&gt;
&lt;strong&gt;&lt;code&gt;My::checkCustomContext()&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;protected static function checkCustomContext(int $context): ?bool&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Cette méthode est appelée en début de la méthode précédente &lt;strong&gt;checkContext&lt;/strong&gt; et peut être réécrite dans la classe &lt;strong&gt;My&lt;/strong&gt; du module si on en a besoin. Elle permet d'utiliser ses propres droits, ou de modifier des droits de contexte de la méthode précédente. Si &lt;strong&gt;checkCustomContext()&lt;/strong&gt; renvoie &lt;strong&gt;null&lt;/strong&gt; alors les contextes de la classe précédente seront testés.&lt;br /&gt;
Exemple avec le fichiers &lt;strong&gt;My&lt;/strong&gt; du plugin &lt;strong&gt;userPrefs&lt;/strong&gt; de la distribution :&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
declare(strict_types=1);

namespace Dotclear\Plugin\userPref;

use dcCore;
use Dotclear\Module\MyPlugin;

class My extends MyPlugin
{
    protected static function checkCustomContext(int $context): ?bool
    {
        // allways limit to super admin
        return defined(&amp;#039;DC_CONTEXT_ADMIN&amp;#039;)
            &amp;amp;&amp;amp; dcCore::app()-&amp;gt;auth-&amp;gt;isSuperAdmin();
    }
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;
&lt;strong&gt;&lt;code&gt;My::path()&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;public static function My::path(): string&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Cette méthode renvoie le chemin du dossier du module.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;&lt;code&gt;My::id()&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;protected static function My::id(): string&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Cette méthode renvoie l'identifiant du module.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;&lt;code&gt;My::name()&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;protected static function My::name(): string&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Cette méthode renvoie le nom traduit du module.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;&lt;code&gt;My::settings()&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;public static function settings(): ?dcNamespace&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Cette méthode renvoie l'instance de l'espace de paramètres du module. Le module &lt;strong&gt;doit&lt;/strong&gt; utiliser son ID comme nom d'espace de paramètre pour pouvoir utiliser cette méthode.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;&lt;code&gt;My::prefs()&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;public static function prefs(): ?dcWorkspace&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Cette méthode renvoie l'instance de l'espace de préférences du module. Le module &lt;strong&gt;doit&lt;/strong&gt; utiliser son ID comme nom d'espace de préférences pour pouvoir utiliser cette méthode.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;&lt;code&gt;My::l10n()&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;public static function l10n(string $process): void&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Cette méthode charge les locales du module pour un process donné (main, public, plugin, etc...).&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;&lt;code&gt;My::fileURL()&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;public static function fileURL(string $resource, bool $frontend = false): string&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Cette méthode retourne l'URL d'un fichier de module. Cette méthode tient compte du contexte courant (admin, public). Pour forcer le retour de l'URL public dans le contexte admin, il suffit de mettre le paramètre &lt;code&gt;$frontend&lt;/code&gt; à &lt;code&gt;true&lt;/code&gt;.&lt;br /&gt;
A noter que pour les thèmes, cette méthode renvoie toujours l'URL publique.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;&lt;code&gt;My::cssLoad()&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;public static function cssLoad(string $resource, string $media = &amp;#039;screen&amp;#039;, ?string $version = &amp;#039;&amp;#039;): string&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Cette méthode retourne le code HTML pour inclure un fichier CSS &lt;code&gt;$resource&lt;/code&gt; du module.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Si le paramètre &lt;code&gt;$resource&lt;/code&gt; ne commence pas par un &lt;code&gt;/&lt;/code&gt; le fichier sera cherché dans le sous dossier &lt;code&gt;css&lt;/code&gt; du module,&lt;/li&gt;
&lt;li&gt;Si l'extension du fichier n'est pas incluse à &lt;code&gt;$resource&lt;/code&gt;, elle sera ajoutée,&lt;/li&gt;
&lt;li&gt;Le type de &lt;code&gt;$media&lt;/code&gt; peut-être précisé, par défaut ce sera &lt;code&gt;screen&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Un numéro de &lt;code&gt;version&lt;/code&gt; peut-être ajouté à la fin de l'url de ressource (gestion de cache)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;// Renvoie le code pour le fichier .../monPlugin/css/frontend.css
My::cssload(&amp;#039;frontend&amp;#039;);
// Renvoie le code pour le fichier .../monPlugin/style.css
My::cssLoad(&amp;#039;/style.css&amp;#039;);&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;
&lt;strong&gt;&lt;code&gt;My::jsLoad()&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;public static function jsLoad(string $resource, ?string $version = &amp;#039;&amp;#039;, bool $module = false): string&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Tout comme &lt;code&gt;My::cssLoad()&lt;/code&gt; cette méthode renvoie le code HTML pour ajouter un fichier JS du module. Le paramètre &lt;code&gt;$module&lt;/code&gt; si il est à &lt;strong&gt;true&lt;/strong&gt; permet de charger &lt;code&gt;$resource&lt;/code&gt; comme un module JS.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;&lt;code&gt;My::addBackendMenuItem()&lt;/code&gt;&lt;/strong&gt; (plugins uniquement)&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;public static function addBackendMenuItem(string $menu = Menus::MENU_PLUGINS, array $params = [], string $scheme = &amp;#039;(&amp;amp;.*)?$&amp;#039;, ?string $id = null): void&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Cette méthode permet d'ajouter rapidement le module aux menus de l'administration.&lt;br /&gt;
Le menu est à choisir parmi ceux définis dans les constantes de &lt;code&gt;Dotclear\Core\Backend\Menus&lt;/code&gt; et par défaut celui des plugins :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Menus::MENU_BLOG&lt;/code&gt; =&amp;gt; 'Blog',&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Menus::MENU_SYSTEM&lt;/code&gt; =&amp;gt; 'System',&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Menus::MENU_PLUGINS&lt;/code&gt; =&amp;gt; 'Plugins',&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Les paramètres :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;$params&lt;/code&gt; sert à ajouter des paramètres à l'URL du menu,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$scheme&lt;/code&gt; permet de personnaliser la surbrillance du menu,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$id&lt;/code&gt; permet de spécifier un id pour l’icône de tableau de bord (Utile aux behaviors).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br /&gt;
&lt;strong&gt;&lt;code&gt;My::icons()&lt;/code&gt;&lt;/strong&gt; (plugins uniquement)&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;public static function icons(string $suffix = &amp;#039;&amp;#039;): array&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Cette méthode renvoie un tableau des chemins complets vers les icônes du modules.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;&lt;code&gt;My::manageURL()&lt;/code&gt;&lt;/strong&gt; (plugins uniquement)&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;public static function manageUrl(array $params = [], string $separator = &amp;#039;&amp;amp;&amp;#039;): string&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Cette méthode renvoie l'URL de la page principale de gestion du module. Des paramètres spéciaux peuvent être ajoutés avec &lt;code&gt;$params&lt;/code&gt;, et le séparateur des paramètres peut être modifié avec le paramètre &lt;code&gt;$separator&lt;/code&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;&lt;code&gt;My::redirect()&lt;/code&gt;&lt;/strong&gt; (plugins uniquement)&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;public static function redirect(array $params = [], string $suffix = &amp;#039;&amp;#039;): void&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Cette méthode effectue une redirection en prenant l'URL de base du module, à laquelle il est possible d'ajouter des paramètres &lt;code&gt;$params&lt;/code&gt;. Le paramètre &lt;code&gt;$suffix&lt;/code&gt; permet d'ajouter par exemple le renvoi vers un onglet spécifique.&lt;br /&gt;
&lt;br /&gt;
&lt;em&gt;&lt;q&gt;Le contenu de ce document a été écrit suivant le code de la version 2.27 de Dotclear.&lt;/q&gt;&lt;/em&gt;&lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Fichier de désactivation d'un module</title>
        <link>https://dotclear.watch/Billet/Fichier-de-d%C3%A9sactivation-d-un-module</link>
        <guid isPermaLink="false">urn:md5:97509a7fdf791a5500dbcca62d002353</guid>
        <pubDate>Fri, 14 Jul 2023 00:39:00 +0100</pubDate>
        <dc:creator>Jean-Christian Denis</dc:creator>
                  <category>2.27</category>
                          <category>2.27</category>
                  <category>disabled</category>
                  <category>module</category>
                  <category>plugin</category>
                  <category>theme</category>
                <description>&lt;p&gt;Le fichier de désactivation en dur d'un module se nomme &lt;strong&gt;_disabled&lt;/strong&gt;, c'est un fichier vide qui est placé à la &lt;a href=&quot;https://dotclear.watch/Billet/Structure-d-un-module&quot;&gt;racine du module&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Normalement ce fichier n'est pas à manipuler, le gestionnaire de modules se charge de l'ajouter suivant des prérequis ou des actions définies.&lt;br /&gt;
Le gestionnaire de module va lire le &lt;a href=&quot;https://dotclear.watch/Billet/Fichier-de-d%C3%A9finition-d-un-module&quot;&gt;fichier de définition du module&lt;/a&gt; et si les prérequis du module ne sont pas remplis, il désactivera le module en ajoutant le fichier &lt;strong&gt;_disabled&lt;/strong&gt; à sa racine.&lt;br /&gt;
Depuis l'interface d'administration du blog, dans la liste des plugins ou des thèmes installés, il est possible de désactiver ou de réactiver des modules.&lt;br /&gt;
Une fois ce fichier présent, seul le fichier de définition du module est lu.&lt;br /&gt;
&lt;br /&gt;
&lt;em&gt;&lt;q&gt;Le contenu de ce document a été écrit suivant le code de la version 2.27 de Dotclear.&lt;/q&gt;&lt;/em&gt;&lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Fichier de définition d'un module</title>
        <link>https://dotclear.watch/Billet/Fichier-de-d%C3%A9finition-d-un-module</link>
        <guid isPermaLink="false">urn:md5:0deff8c52b8419d8f95fcddee9b92aa4</guid>
        <pubDate>Tue, 11 Jul 2023 21:14:00 +0100</pubDate>
        <dc:creator>Jean-Christian Denis</dc:creator>
                  <category>2.27</category>
                          <category>2.27</category>
                  <category>define</category>
                  <category>module</category>
                  <category>plugin</category>
                  <category>theme</category>
                <description>&lt;p&gt;Le fichier de définition se situe à la &lt;a href=&quot;https://dotclear.watch/Billet/Structure-d-un-module&quot;&gt;racine du module&lt;/a&gt;, il se nomme &lt;strong&gt;_define.php&lt;/strong&gt; et il va donner à Dotclear toutes les informations indispensables à sa compréhension. Il est en très grande partie commun aux thèmes et aux plugins.&lt;/p&gt; &lt;p&gt;Son contenu peut être le suivant :&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
/**
 * Mettre ici les informations de licence
 */
$this-&amp;gt;registerModule(
    &amp;#039;Le module&amp;#039;, // Nom (requis)
    &amp;#039;Un module qui ne fait rien&amp;#039;, // Description (requis)
    &amp;#039;Jean-Christian Denis and contributors&amp;#039;, // Auteur (requis)
    &amp;#039;1.0&amp;#039;,  // Version (requis)
    [
        &amp;#039;requires&amp;#039; =&amp;gt; [
            [&amp;#039;php&amp;#039;, &amp;#039;8.1&amp;#039;], // Version minimum de PHP (optionnel)
            [&amp;#039;core&amp;#039;, &amp;#039;2.26&amp;#039;], // Version miminum de Dotclear (recommandé)
            [&amp;#039;UnAutreModule&amp;#039;, &amp;#039;1.1&amp;#039;], // Dépendance à un autre module (optionnel)
        ],
        &amp;#039;priority&amp;#039; =&amp;gt; 1000, // priorité, nombre entier positif (optionnel)
        &amp;#039;permissions&amp;#039; =&amp;gt; dcCore::app()-&amp;gt;auth-&amp;gt;makePermissions([
            dcCore::app()-&amp;gt;auth::PERMISSION_CONTENT_ADMIN,
        ]), // Permissions (recommandé)
        &amp;#039;type&amp;#039; =&amp;gt; &amp;#039;plugin&amp;#039;, // type de module, plugin ou theme (requis)
        &amp;#039;settings&amp;#039;    =&amp;gt; [
            &amp;#039;blog&amp;#039; =&amp;gt; &amp;#039;#params.LeModule&amp;#039;, // plugin, sa configuration est sur la page de paramètres du blog
            &amp;#039;self&amp;#039; =&amp;gt; &amp;#039;&amp;#039;, // plugin, sa page de gestion est sa page de configuration
            &amp;#039;pref&amp;#039; =&amp;gt; &amp;#039;#user-options.LeModule&amp;#039;, // plugin, sa configuration est dans les préférences utilisateur
        ],
        &amp;#039;parent&amp;#039; =&amp;gt; &amp;#039;ductile&amp;#039;, // thème, son parent (optionnel)
        &amp;#039;tplset&amp;#039; =&amp;gt; &amp;#039;mustek&amp;#039;, // thème, le jeu de template à utiliser (optionnel)
        &amp;#039;standalone_config&amp;#039; =&amp;gt; true, // thème, utilisation de sa propre configuration (optionnel)
        &amp;#039;support&amp;#039; =&amp;gt; &amp;#039;https://github.com/JcDenis/LeModule&amp;#039;, // Lien vers la page du support (recommandé)
        &amp;#039;details&amp;#039; =&amp;gt; &amp;#039;https://plugins.dotaddict.org/dc2/details/LeModule&amp;#039;, // Lien vers la page de détails (recommandé)
        &amp;#039;repository&amp;#039; =&amp;gt; &amp;#039;https://raw.githubusercontent.com/JcDenis/LeModule/master/dcstore.xml&amp;#039;, // Lien vers la définition du dépôt tiers (optionnel)
        &amp;#039;widgettitleformat&amp;#039;     =&amp;gt; &amp;#039;&amp;#039;, // formatage de widget (optionnel)
        &amp;#039;widgetsubtitleformat&amp;#039;  =&amp;gt; &amp;#039;&amp;#039;, // formatage de widget (optionnel)
        &amp;#039;widgetcontainerformat&amp;#039; =&amp;gt; &amp;#039;&amp;#039;, // formatage de widget (optionnel)
    ]
);&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;
&lt;strong&gt;Attention :&lt;/strong&gt; Ce fichier est appelé très tôt dans le code, à l'intérieur d'une méthode, il peut être appelé plusieurs fois et d'autres script peuvent l'appeler, à cause de tout cela seules les classes dcAuth, dcCore et celles contenues dans les fichiers _init.php des modules peuvent être utilisées dans ce fichier.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;A noter :&lt;/strong&gt; Si la page de configuration du plugin est dans un fichier &lt;code&gt;src/Config.php&lt;/code&gt;, Dotclear l'indiquera de manière automatique, il n'est pas nécessaire de l'indiquer dans la définition des paramètres &lt;em&gt;settings&lt;/em&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;La présence du fichier define.php est obligatoire.&lt;/strong&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;em&gt;&lt;q&gt;Le contenu de ce document a été écrit suivant le code de la version 2.27 de Dotclear.&lt;/q&gt;&lt;/em&gt;&lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Structure d'un module</title>
        <link>https://dotclear.watch/Billet/Structure-d-un-module</link>
        <guid isPermaLink="false">urn:md5:6d0c1344a22a365bd1abddfe6de79f06</guid>
        <pubDate>Tue, 11 Jul 2023 21:09:00 +0100</pubDate>
        <dc:creator>Jean-Christian Denis</dc:creator>
                  <category>2.27</category>
                          <category>2.27</category>
                  <category>module</category>
                  <category>plugin</category>
                  <category>structure</category>
                  <category>theme</category>
                <description>&lt;p&gt;Avec la &lt;a href=&quot;https://dotclear.watch/Billet/Release-2.27&quot;&gt;version 2.27&lt;/a&gt; de Dotclear la structure de plugins et thèmes devient plus rigide. Cette structure deviendra obligatoire assez rapidement.&lt;/p&gt; &lt;p&gt;La structure générale d'un module est quasi commune aux plugins et aux thèmes. Elle se définit comme suit.&lt;br /&gt;&lt;/p&gt;

&lt;h5&gt;Nom&lt;/h5&gt;

&lt;p&gt;Depuis la mise en place des espaces de nom pour les modules, le nom du répertoire racine du module sera son ID et son espace de nom PHP. De ce fait il est proscrit tous caractères autres que des chiffres et lettres et le nom doit commencer par une lettre.&lt;br /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Invalide&lt;/strong&gt; : mon-plugin, 1to3plugin,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Valide :&lt;/strong&gt; monplugin, MonPlugin2,&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Fichiers à la racine du module :&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://dotclear.watch/Billet/Fichier-de-d%C3%A9finition-d-un-module&quot;&gt;_define.php&lt;/a&gt; : Fichier de définition&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dotclear.watch/Billet/Fichier-de-d%C3%A9sactivation-d-un-module&quot;&gt;_disabled&lt;/a&gt; : Fichier de désactivation&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dotclear.watch/Billet/Fichier-init-d-un-module&quot;&gt;_init.php&lt;/a&gt; : Fichier de définition d'initialisation&lt;/li&gt;
&lt;li&gt;CHANGELOG.md : récapitulatif des modifications/versions&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dotclear.watch/Billet/Fichier-de-d%C3%A9p%C3%B4t-tiers&quot;&gt;dcstore.xml&lt;/a&gt; : Fichier de définition de dépôt distant&lt;/li&gt;
&lt;li&gt;icon.svg : Icône&lt;/li&gt;
&lt;li&gt;icon-dark.svg : Icône sombre&lt;/li&gt;
&lt;li&gt;LICENSE : Licence&lt;/li&gt;
&lt;li&gt;README.md : Document d'introduction&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Répertoires à la racine du module :&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;css : Feuilles de styles&lt;/li&gt;
&lt;li&gt;default-templates : Templates&lt;/li&gt;
&lt;li&gt;img : Images&lt;/li&gt;
&lt;li&gt;js : Scripts javascript&lt;/li&gt;
&lt;li&gt;locales : Traductions&lt;/li&gt;
&lt;li&gt;src : Espace de nom contenant tous les fichiers .php&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Fichiers du dossier src :&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://dotclear.watch/Billet/Fichier-Backend-d-un-module&quot;&gt;Backend.php&lt;/a&gt; : ex _admin.php Préparation de la partie admin,&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dotclear.watch/Billet/Fichier-Config-d-un-module&quot;&gt;Config.php&lt;/a&gt; : ex _config.php Configurateur,&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dotclear.watch/Billet/Fichier-Frontend-d-un-module&quot;&gt;Frontend.php&lt;/a&gt; : ex _public.php Préparation de la partie publique&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dotclear.watch/Billet/Fichier-Install-d-un-module&quot;&gt;Install.php&lt;/a&gt; : ex _install.php Processus d'installation&lt;/li&gt;
&lt;li&gt;Manage.php : ex index.php Page de gestion principale&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dotclear.watch/Billet/Les-classes-de-module-My&quot;&gt;My.php&lt;/a&gt; : fonctions prédéfinies d'aides au code&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dotclear.watch/Billet/Fichier-Prepend-d-un-module&quot;&gt;Prepend.php&lt;/a&gt; : ex _prepend.php Préparation générale&lt;/li&gt;
&lt;li&gt;Widgets.php : ex _widgets.php Gestion des widgets par le plugin widgets&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Bonnes pratiques&lt;/h5&gt;

&lt;p&gt;Il est vivement recommandé (possible obligation à l'avenir) d'utiliser l'&lt;strong&gt;ID du module&lt;/strong&gt; pour l'identifiant de ses paramètres dans les espaces de paramètres (blog settings) et les espaces de préférences (user pref).&lt;br /&gt;
Il est recommandé de séparer les behaviors trop volumineux des fichiers &lt;strong&gt;Backend.php&lt;/strong&gt; / &lt;strong&gt;Frontend.php&lt;/strong&gt; et de les mettre dans un fichier &lt;code&gt;BackendBehaviors.php&lt;/code&gt; / &lt;code&gt;FrontendBehaviors.php&lt;/code&gt;.&lt;br /&gt;
De manière générale le nom de fichier et donc de classe doit être en rapport avec sa fonction, par exemple une classe contenant toutes les méthodes en rapport aux &lt;strong&gt;templates coté public&lt;/strong&gt; sera nommé &lt;code&gt;FrontendTemplate&lt;/code&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;em&gt;Ce document est en cours d'écriture, il est incomplet.&lt;/em&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;em&gt;&lt;q&gt;Le contenu de ce document a été écrit suivant le code de la version 2.27 de Dotclear.&lt;/q&gt;&lt;/em&gt;&lt;/p&gt;</description>
        
              </item>
          <item>
        <title>La class Process</title>
        <link>https://dotclear.watch/Billet/La-class-Process</link>
        <guid isPermaLink="false">urn:md5:c7e57bde7d87b749d5506bb78759ec9a</guid>
        <pubDate>Tue, 11 Jul 2023 20:41:00 +0100</pubDate>
        <dc:creator>Jean-Christian Denis</dc:creator>
                  <category>2.27</category>
                          <category>2.27</category>
                  <category>class</category>
                  <category>module</category>
                  <category>plugin</category>
                  <category>process</category>
                  <category>theme</category>
                <description>&lt;p&gt;La classe &lt;strong&gt;Process&lt;/strong&gt; introduite dans les dernières versions de Dotclear devient la norme et est requise quasi partout depuis &lt;a href=&quot;https://dotclear.watch/Billet/Release-2.27&quot; hreflang=&quot;fr&quot; title=&quot;Note de release 2.27&quot;&gt;Dotclear 2.27&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;La plupart des classes de plugins et thèmes doivent étendre la classe Process, pour cela il suffit de déclarer son utilisation en début de fichier puis d'étendre votre classe.&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
use Dotclear\Core\Process;

class Manage extends Process
{
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Cette classe est pour l'instant très succincte mais permet de découper le déroulement du script en trois parties.&lt;br /&gt;&lt;/p&gt;

&lt;h5&gt;Première partie&lt;/h5&gt;

&lt;p&gt;Elle utilise la méthode &lt;code&gt;Process::init()&lt;/code&gt; elle permet de vérifier les droits à utiliser votre classe. Elle utilise un mécanisme mémorisant le statut de cette initialisation, verrouillant ou non l'utilisation des méthodes suivantes.&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;public static function init(): bool
{
    // On enregistre la permissions d&amp;#039;utiliser la classe et on renvoie le résultat
    return self::status(My::checkContext(My::MANAGE));
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;On voit ici l'utilisation de la &lt;a href=&quot;https://dotclear.watch/Billet/Les-classes-de-module-My&quot;&gt;classe My&lt;/a&gt; qui est un outil d'aide à l'écriture des modules simplifiant l'utilisation de certains mécanismes.&lt;br /&gt;&lt;/p&gt;

&lt;h5&gt;Seconde partie&lt;/h5&gt;

&lt;p&gt;Elle utilise la méthode &lt;code&gt;Process::process()&lt;/code&gt; qui est consacrée à la préparation et au traitement des données, telles que celles des formulaires par exemple.&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;public static function process(): bool
{
    // On vérifie le droit d&amp;#039;effectuer cette partie
    if (!self::status()) {
        return false;
    }

    if (!empty($_POST[&amp;#039;id&amp;#039;])) {
        // traitement de mon formulaire

        // On a réussi, on ajoute un message
        Notices::addSuccessNotice(__(&amp;#039;Victory&amp;#039;));
        // On redirige vers la page du plugin
        dcCore::-&amp;gt;admin-&amp;gt;url-&amp;gt;redirect(&amp;#039;admin.plugin.&amp;#039; . My::id());
    }

    // Cette méthode doit retourner true si on veut exécuter la troisième partie
    return true;
}&lt;/code&gt;&lt;/pre&gt;

&lt;h5&gt;La troisième partie&lt;/h5&gt;

&lt;p&gt;Elle utilise la méthode &lt;code&gt;Process::render()&lt;/code&gt; qui est consacré au rendu. C'est à dire à l'affichage dans le navigateur.&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;public static function render(): void
{
    // On vérifie le droit d&amp;#039;effectuer cette partie
    if (!self::status()) {
        return;
    }

    // On prépare l&amp;#039;affichage du haut de page
    Page::openModule(My::name());

    // On ajoute le menu façon Dotclear
    echo
    Page::breadcrumb(
        [
            __(&amp;#039;Plugin&amp;#039;)  =&amp;gt; &amp;#039;&amp;#039;,
            My::name() =&amp;gt; &amp;#039;&amp;#039;,
        ]
    ) .
    // On affiche d&amp;#039;éventuelle messages
    Notices::getNotices();

    // On ajoute le contenu de la page
    echo __(&amp;#039;yeah!&amp;#039;);

    // On ajoute l&amp;#039;aide de la page
    Page::helpBlock(My::id());

    // On ferme la page
    Page::closeModule();
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ici on voit l'utilisation des classes d'outils My et Page qui vont grandement faciliter l'écriture des plugins et thèmes.&lt;br /&gt;
&lt;br /&gt;
A noter que seule la première méthode &lt;strong&gt;init()&lt;/strong&gt; est obligatoire. Si elle renvoie &lt;strong&gt;true&lt;/strong&gt;, c'est que la classe ne contient pas de méthode &lt;strong&gt;process()&lt;/strong&gt;, la méthode &lt;strong&gt;render()&lt;/strong&gt; sera exécuté.&lt;br /&gt;
&lt;br /&gt;
&lt;em&gt;&lt;q&gt;Le contenu de ce document a été écrit suivant le code de la version 2.27 de Dotclear.&lt;/q&gt;&lt;/em&gt;&lt;/p&gt;</description>
        
              </item>
      </channel>
</rss>
