Attention : vous consultez actuellement la documentation dédiée aux versions 1.x de Moodle. La documentation pour les versions 2.x de Moodle est consultable ici : Développement:Directives de codage, celle pour les versions 3.x de Moodle est consultable ici : Développement:Directives de codage et celle pour Moodle 4.x est consultable là : Développement:Directives de codage.

Développement:Directives de codage

De MoodleDocs
Aller à :navigation, rechercher

Remarque : la traduction de cet article n'est pas terminée. N'hésitez pas à traduire tout ou partie de cette page ou à la compléter. Vous pouvez aussi utiliser la page de discussion pour vos recommandations et suggestions d'améliorations.


Tout projet collaboratif a besoin de cohérence et de stabilité pour rester solide.

Ces directives de codage sont faites pour assurer un but commun à tout code de Moodle. Il est vrai que quelques uns des plus vieux codes existants sont déficients, mais ils seront tous finalement réarrangés. Tout nouveau code doit adhérer à ces standards de manière aussi proche que possible.

Règles générales

  1. Tous les fichiers de code doivent avoir l'extension .php .
  2. Tous les fichiers template doivent avoir l'extension .html .
  3. Tous les fichiers de texte doivent utiliser le format de texte style Unix (la plupart des éditeurs de texte l'ont comme option).
  4. Toutes les balises php doivent être des balises "complètes" <?php ?> ... et non des balises "courtes" comme <? ?>.
  5. Toutes les notes de copyright existantes doivent être conservées. Vous pouvez ajouter la vôtre si nécessaire.
  6. Chaque fichier doit inclure (require_once) le fichier principal config.php .
  7. Tous les autres include/require doivent utiliser un début de chemin absolu commençant pas $CFG->dirroot ou $CFG->libdir, pas d'inclusions relatives, qui se comportent parfois de manière étrange sous PHP.
  8. Les inclusions doivent être faites au début des fichiers ou à l'intérieur des fonctions/méthodes, ne pas mettre d'include/require au milieu d'un fichier.
  9. Chaque fichier doit vérifier que l'utilisateur est correctement identifié, en utilisant require_login() et has_capability ou require_capablity().
  10. Tous les accès aux bases de données doivent utiliser les fonctions de lib/dmllib.php autant que possible - cela permet une compatibilité entre une large gamme de bases de données. Vous devriez remarquer que presque tout est possible en utilisant ces fonctions. Si vous devez écrire du code SQL, alors assurez-vous qu'il est : cross-plaform; restreint à des fonctions spécifiques à l'intérieur de votre code (normalement un fichier lib.php); et clairement indiqué.
  11. Ne créez pas de nouvelles variables globales. Utilisez seulement les variables globales standard de Moodle $CFG, $SESSION, $THEME, $SITE, $COURSE et $USER.
  12. Toutes les variables doivent être initialisées ou leur existence doit avoir été au moins testés en utilisant isset() ou empty() avant d'être utilisées.
  13. Toutes les chaînes doivent être traduisibles - créez de nouveaux textes dans les fichiers "lang/en_utf8" avec des noms anglais concis et en minuscules, et récupérez-les dans votre code en utilisant get_string() ou print_string(). N'effacez jamais les chaînes pour assurez que la rétro-compatibilité des packs de langues soit maintenue.
  14. N'utilisez pas les fonctions p() et s() pour afficher des chaînes. Ces fonctions ne sont pas destinées à afficher du html avec des balises. Utilisez echo() à la place.
  15. Toutes les erreurs doivent être affichées en utilisant print_error() pour optimiser la traduction et l'aide aux utilisateurs (cela se lie automatiquement au documents wiki).
  16. Tous les fichiers d'aide doivent être traduisibles - créez de nouveaux textes dans le répertoire "lang/en_utf8/help" et appelez-les en utilisant helpbutton(). Si vous avez besoin de mettre à jour un fichier d'aide :
    • avec un changement mineur, où une vieille traduction du fichier aura toujours un sens, alors vous pouvez faire le changement mais vous devez l'annoncer ) translation AT moodle DOT org.
    • pour un changement majeur, vous devez créer un nouveau fichier en ajoutant un nombre incrémenté (ex nomdefichier2.html), ainsi les traducteurs peuvent facilement voir que c'est une nouvelle version du fichier. Il est évident que le nouveau code et les fichiers index d'aide doivent également être modifiés pour pointer vers les versions les plus récentes.
  17. Les données entrantes depuis le navigateur (envoyées via GET ou POST) voient automatiquement s'ajouter des magic_quotes (sans tenir compte des réglages de PHP), ainsi vous pouvez les insérer sans danger directement dans la base de données. Toute autres donnée brute (depuis des fichiers, ou depuis des bases de données) doit être sécurisée avec addslashes() avant de l'insérer dans la base de données. Parce que ceci est trop souvent fait mal correctement, il y a plus d'explications sur ce problème d'ajouter et supprimer des slashes sur une page à part.
  18. TRES IMPORTANT : A l'intérieur de Moodle, Tous les textes doivent être affichés en utilisant la fonction format_text(), particulièrement ceux qui viennent des utilisateurs. Ceci assure un texte correctement filtré et nettoyé. Plus d'informations peuvent être trouvées sur la page à propos des fonctions de sortie.
  19. Les actions d'utilisateurs doivent être enregistrées en utilisant la fonction add_to_log(). Ces historiques sont utilisés pour les reports d'activité et les Logs.
  20. Créez toujours des liens HTML relatifs à la racine du site, i.e. des liens du type $CFG->wwwroot/mod/blonk/view.php?id=99 plutôt que seulement view.php?id=99. Cela permettra à votre code de fonctionner s'il est appelé par un script dans un autre dossier, entre autres.
  21. Les modules doivent stocker les variables de configuration en utilisant set_config('varname', $value, 'mod/modulename') où le dernier paramètre est le chemin vers le répertoire du module.
  22. Respectez les séparateurs décimaux spécifiés dans le pack de langage - n'utilisez pas number_format() directement, à la place utilisez format_float() et unformat_float() quand vous affichez ou traitez des nombres flottants (obligatoire en 2.0)

Modèle de codage

Nous savons que cela peut-être un peu agaçant de changer votre style si vous avez l'habitude d'un autre, mais il faut trouver un équilibre entre cet agacement et celui de tous les gens qui essaieront plus tard de trouver un sens au code de Moodle avec un mélange de styles. Il y a évidemment beaucoup de bons points pour et contre chaque style propre à chaque personne, mais le modèle actuel est ainsi, donc approchez-vous en au maximum, s'il vous plaît.

1. L'indentation doit être constamment de 4 espaces. N'utilisez pas DU TOUT les tabulations.

2. Les noms de variables doivent toujours être facile à lire, significatifs, en Anglais et en minuscules. Si vous avez vraiment besoin de plus d'un mot alors attachez-les, mais gardez-les aussi courts que possible. Utilisez des noms pluriels pour les tableaux d'objets.

     BON: $quiz
     BON: $errorstring
     BON: $assignments (pour les tableaux d'objets)
     BON: $i (uniquement dans les petites boucles)
     MAUVAIS: $Quiz
     MAUVAIS: $aReallyLongVariableNameWithoutAGoodReason
     MAUVAIS: $error_string

3. Les constantes doivent toujours être en majuscules, et toujours commencer par le nom du module. Les mots doivent être séparés par des underscores.

     define("FORUM_MODE_FLATOLDEST", 1);

4. Les noms de fonctions doivent être des mots anglais simples et en minuscules, et commencer par le nom du module pour éviter les conflits entre modules. Les mots doivent être séparés par des underscores. Les paramètres doivent toujours avoir une valeur par défaut si possible. Notez qu'il n'y a pas d'espace entre le nom de la fonction et la suite (accolades).

     function forum_set_display_mode($mode=0) {
         global $USER, $CFG;
         
         if ($mode) {
             $USER->mode = $mode;
         } else if (empty($USER->mode)) {
             $USER->mode = $CFG->forum_displaymode;
         }
     }

La même chose s'applique pour nommer les classes et leurs méthodes. Utilisez des mots en minuscules séparés par des underscores.

     class some_custom_class {
         function class_method() {
             ...
         }
     }

5. Les blocs doivent toujours entourés d'accolades (même s'ils ne font qu'une ligne). Moodle utilise ce modèle :

     if ($quiz->attempts) {
         if ($numattempts > $quiz->attempts) {
             error($strtoomanyattempts, "view.php?id=$cm->id");
         }
     }

6. Les chaînes doivent être définies en utilisant des simples quotes quand c'est possible, ainsi moins de mémoire est utilisée.

     $var = 'du texte sans aucune variable';
     $var = 'avec des caractères spéciaux comme un saut de ligne '."\n";
     $var = 'une très très longue chaîne avec une '.$simple.' variable dedans';
     $var = "un $texte avec $beaucoup de variables $dedans";

7. Les commentaires doivent être ajoutés dès que c'est pratique, pour expliquer le code et le but des fonctions et variables.

  • Chaque fonction (et classe) doit utiliser le populaire format phpDoc. Ceci permet de générer automatiquement la documentation du code.
  • Les commentaires sur une ligne doivent utiliser le modèle //, être mis en page proprement, ainsi ils s'alignent avec le code.
     /**
     * La description doit être au début, avec des astérisques mises en page exactement
     * comme dans cet exemple. Si vous voulez vous référer à une autre fonction,
     * faites comme ceci : {@link clean_param()}. Ensuite, ajoutez des descriptions
     * pour chaque paramètre comme ci-dessous.
     *
     * @param int $postid Le type PHP est suivi du nom de la variable
     * @param array $scale Le type PHP est suivi du nom de la variable
     * @param array $ratings Le type PHP est suivi du nom de la variable
     * @return mixed
     */
     function forum_get_ratings_mean($postid, $scale, $ratings=NULL) {
         if (!$ratings) {
             $ratings = array();     // Initialise le tableau vide
             if ($rates = get_records("forum_ratings", "post", $postid)) {
                 // Process each rating in turn
                 foreach ($rates as $rate) {
     ....etc

8. Les espaces doivent être utilisés généreusement - n'ayez pas peur d'étaler les choses un peu pour gagner en clarté. En règle générale, il devrait y avoir un espace entre les parenthèses et les déclarations normales, mais pas d'espace entre les parenthèses et les variables ou les fonctions :

     foreach ($objects as $key => $thing) {
         process($thing);
     }
     
     if ($x == $y) {
         $a = $b;
     } else if ($x == $z) {
         $a = $c;
     } else {
         $a = $d;
     }

9. Quand vous faites une COPIE d'un objet, utilisez toujours la fonction php5 clone().

     MAUVAIS:   $b = $a;
     BON:  $b = clone($a);

Si ce que vous voulez copier n'est pas un objet, mais peut contenir des objets (ex un tableau d'objets), alors utilisez fullclone() à la place.

Structure de la base de données

Pour vous aider à créer des tables qui respectent ces directives, nous vous recommandons d'utiliser l'éditeur XMLDB.

  1. Chaque table doit avoir un champ id auto-incrémenté (INT10) pour clé primaire. (voir en:IdColumnReasons)
  2. La table principale, contenant les instances de chaque module, doit avoir le même nom que le module (ex widget) et contenir au moins les champs suivants :
    • id - comme décrit ci-dessus
    • course - l'id du cours auquel appartient chaque instance
    • name - le nom complet de chaque instance du module
  3. Les autres tables, associées avec un module, qui contiennent des informations à propos de 'choses' doivent être nommées widget_choses (notez le pluriel).
  4. Les noms de tables et de colonnes doivent éviter d'utiliser des mots réservés. Vérifiez-les avant la création s'il vous plaît. Les noms de tables peuvent monter à 28 caravtères, et les noms de Colonnes jusque 30 caractères.
  5. Les noms de colonnes doivent être toujours en minuscules, simples et courts, suivant les mêmes règles que les noms de variables.
  6. Si possible, les colonnes qui contiennent une référence au champ id d'une autre table (ex widget) doivent être appeléees widgetid. (Notez que cette convention est récente et pas suivie dans les plus anciennes tables)
  7. Les champs de booléens doivent être déclarés en tant que champs small integer (ex INT4) contenant 0 ou 1, pour permettre une future extension des valeurs si nécessaire.
  8. La plupart des tables doivent avoir un champ timemodified (INT10) qui est mis à jour avec un timestamp courant obtenu avec la fonction PHP time().
  9. Définissez toujours une valeur par défaut pour chaque champ (et raisonnable)
  10. Chaque nom de table doit commencer avec le préfixe de base de données ($CFG->prefix). Dans beaucoup de cas, c'est fait automatiquement. Aussi, sous Postgres, le nom de chaque index doit commencer avec le préfixe aussi.
  11. Dans le but de garantir la compatibilité inter-bases, suivez ces règles simples à propos du mot-clé AS (seulement si vous avez besoin d'alias pour des tables/colonnes, bien sûr) :
    • N'utilisez pas le mot-clé AS pour des alias de tables.
    • Utilisez le mot-clé AS pour des alias de colonnes.
  12. Ne créez jamais de clés uniques (UNIQUE KEY) (contraintes). Au lieux de cela, utilisez les indexes uniques (UNIQUE INDEX). Dans le futur, si nous décidons d'ajouter l'intégrité référentielle à Moodle et que nous avons besoin des clés uniques (UNIQUE KEY) elle seront utilisées, mais pas pour le moment.
  13. Those XMLDB-only UNIQUE KEYs (read previous point) only must be defined if such field/fields are going to be the target for some (XMLDB-only too) FOREIGN KEY. Else, create them as simple UNIQUE INDEXes.
  14. Les tables associées avec un bloc doivent suivre cette convention pour leurs noms : $CFG->prefix + "block_" + nom_du_bloc + ce_que_vous_voulez. Par exemple, en supposant que $CFG->prefix est 'mdl_', toutes les tables pour le bloc "rss_client" doivent commencer par 'mdl_block_rss_client' (il est possible d'ajouter d'autres mots à la fin, i.e. 'mdl_block-rss-client_uneautretable'...). Cette règle sera appliquée à 100% avec Moodle 2.0, en donnant du temps aux développeurs jusque là. Voir Task 6786 pour plus d'informations à ce propos.
  15. Ne jamais faire des changements de base de données dans les branches STABLES. Sinon, les utilisateurs qui mettent à jour d'une version stable à la prochaine auront des changements qui se dupliquent, ce qui peut causer de graves erreurs.
  16. Quand vous faites allusion à une variable entière dans des requêtes SQL, n'entourez pas la valeur de guillemets. Par exemple, get_records_select('question, "category=$catid") est juste. get_records_select('question, "category='$catid'") est mauvais. Cela cache les bugs où $catid n'est pas définie. (Ce sujet explique.)

Problèmes de sécurité (et manipulation de formulaires et données URL)

  1. Ne vous fiez pas à 'register_globals'. Chaque variable doir être correctement initialisée dans chaque fichier de code. ca doit être évident, quel que soit l'endroit d'où vienne la variable.
  2. Initialisez tous les tableaux et objets, même s'ils sont vides. $a = array() ou $obj = new stdClass();.
  3. N'utilisez pas la fonction optional_variable(). Utilisez la fonction optional_param() à la place. Choisissez la valeur correcte de PARAM_XXX pour le type de données que vous attendez.
  4. N'utilisez pas la fonction require_variable(). Utilisez la fonction require_param() à la place. Choisissez la valeur correcte de PARAM_XXX pour le type de données que vous attendez.
  5. Utilisez date_submitted(), avec soin. Les données doivent toujours être nettoyées avant utilisation. Utilisez confirm_sesskey avec data_submitted() pour empêcher les attaques CSRF.
  6. N'utilisez pas $_GET, $_POST ou $_REQUEST. Utilisez les required_param() ou optional_param() appropriés à vos besoins.
  7. Do not check for an action using something like if (isset($_GET['something'])). Use, e.g., $something = optional_param( 'something',-1,PARAM_INT ) and then perform proper test for it being in its expected range of values e.g., if ($something>=0) {....
  8. Où que possible, groupez tous vos required_param(), optional_param() et autres variables d'initialisation au début de chaque fichier afin qu'elles soient faciles à trouver.
  9. Utilisez le mécanisme 'sesskey' pour protéger les manipulations habituelles de formulaires contre des attaques. Exemple basique d'utilisation : quand le formulaire est généré, incluez <input type="hidden" name="sesskey" value="<?php echo sesskey(); ?>" />. Quand vous traitez le formulaire, vérifiez avec if (!confirm_sesskey()) { print_error('confirmsesskeybad');}.
  10. Tous les noms de fichiers doivent être 'nettoyés' en utilisant la fonction clean_filename(), si ça n'a pas déjà été fait par une utilisation appropriée de required_param() ou optional_param()
  11. Il faut avoir appliqué addslashes() sur chaque donnée lue depuis la base de données avant qu'elle puisse être écrite à nouveau. Un ensemble de données peut être traité en une fois avec addslashes_object().
  12. addslashes_js() doit être utilisé pour la protection des chaînes javascript
  13. Où que possible, les données stockées dans la base de données doivent venir de données POST (depuis un formulaire avec method="POST") au contraire des données GET (ie, des données d'une adresse URL).
  14. N'utilisez pas les données de $_SERVER si vous pouvez éviter.
  15. Si ça n'a pas été fait autre part, faites en sorte d'être sûr que toutes les données écrites dans la base de données sont passées par la fonction clean_param() en utilisant le PARAM_XXX approprié pour le type de donnée.
  16. Si vous écrivez du code SQL, soyez sûr qu'il est correct. En particulier, vérifiez les guillemets manquants autour des valeurs. Il est possible d'exploiter les 'injections' SQL.
  17. Vérifiez toutes les données (particulièrement celles écrites dans la base de données) dans chaque fichier qui est utilisé.
  18. Blocks of code to be included should contain a definite PHP structure (e.g, a class declaration, function definition(s) etc.) - straight blocks of code promote uninitialised variable usage.
  19. Si vous avez besoin d'utiliser shell_exec() (ou toutes autre fonction appelant le shell), soyez sûr que vous nettoyer d'abord les paramètres avec escapeshellcmd()/escapeshellarg (sinon, nous sommes ouverts aux injections shell).

Utilisation de Javascript dans Moodle

Sur une page à part, voir en:Development:JavaScript guidelines.