mirrored from git://git.moodle.org/moodle.git
/
coding.html
executable file
·256 lines (181 loc) · 20.1 KB
/
coding.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Documentation Moodle : Directives pour la programmation</title>
<link rel="stylesheet" href="docstyles.css" type="text/css" />
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head>
<body>
<h1>Directives pour la programmation</h1>
<p class="normaltext">Tout projet où l'on travaille en collaboration nécessite une cohérence et une stabilité fortes.</p>
<p class="normaltext">L'objectif de ces directives est de fournir un cadre à respecter pour tout le code de Moodle. Il est vrai que certaines parties plus anciennes du code ne les respectent pas toujours ; le code sera corrigé. Tout le nouveau code doit absolument respecter ces directives aussi précisément que possible.</p>
<h2>Règles générales</h2>
<ol class="normaltext">
<li class="spaced">Tous les fichiers contenant du code doivent avoir l'extension .php.</li>
<li class="spaced">Tous les fichiers modèles (« themes ») doivent avoir l'extension .html.</li>
<li class="spaced">Tous les fichiers en format texte doivent être en format Unix (la plupart des éditeurs de texte permettent de convertir les caractères de fin de ligne).</li>
<li class="spaced">Toutes les balises php doivent être en forme complète, comme ceci <font color="#339900"><?php ... ?></font>, et non en forme abrégée comme ceci <font color="#339900"><?php ... ?></font>.</li>
<li class="spaced">Toutes les indications de copyright doivent être conservées. Vous pouvez ajouter les vôtres au besoin.</li>
<li class="spaced">Tous les fichiers doivent comporter une commande d'inclusion du fichier config.php principal.</li>
<li class="spaced">Tous les fichiers doivent vérifier que l'utilisateur est correctement authentifié, à l'aide de require_login() et d'une des fonctions isadmin(), isteacher(), iscreator() et isstudent().</li>
<li class="spaced">Tous les accès aux bases de données doivent autant que possible utiliser les fonctions définies dans lib/datalib.php. Ceci permet la compatibilité avec un grand nombre de marques de bases de données. Il est possible de faire presque tout avec ces fonctions. Si vous devez écrire du code SQL, assurez-vous qu'il soit : multi-plateforme, restreint à des fonctions spécifiques de votre code (habituellement placés dans un fichier lib.php) et clairement marqué.</li>
<li class="spaced">Ne créez et n'utilisez aucune variable globale, sauf les variables standard $CFG, $SESSION, $THEME et $USER.</li>
<li class="spaced">Toutes les variables doivent être initialisées ou au moins leur existence doit être testée avec isset() ou empty() avant leur utilisation.</li>
<li class="spaced">Toutes les chaînes de caractères doivent être traduisibles. Créez les nouvelles chaînes dans les fichiers du dossier « lang/en », donnez-leur des noms en minuscules, courts, en anglais, et utilisez-les dans votre code par l'intermédiaire des fonctions get_string() ou print_string().</li>
<li class="spaced">Tous les fichiers d'aide doivent être traduisibles. Créez-les dans le dossier « lang/en/help » et appelez-les avec la fonction helpbutton().</li>
<li class="spaced">Les magic_quotes sont automatiquement appliquées aux données en provenance du navigateur (envoyées via GET ou POST), indépendamment des réglages de PHP. Il est donc sûr de les insérer directement dans la base de données. Toutes les autres données brutes (en provenance de fichiers ou de bases de données) doivent être encodées avec <font color="#339900">addslashes()</font> avant de les insérer dans la base de données.</li>
<li class="spaced">IMPORTANT : tous les textes dans Moodle, tout particulièrement ceux qui proviennent des utilisateurs, doivent être affichés à l'aide de la fonction format_text(). Ceci permet de s'assurer que le texte est filtré et nettoyé correctement.</li>
</ol>
<p> </p>
<h2>Style du code</h2>
<p class="normaltext">Je suis conscient qu'il est ennuyeux de changer votre style si vous avez d'autres habitudes, mais comparez cet embêtement avec les gros ennuis qu'ont ultérieurement les personnes qui essaient de comprendre un code composé dans des styles différents. Bien sûr il y a des avantages et des inconvénients à chaque style, mais le style de Moodle <strong>existe</strong>, alors tenez-vous y, s'il vous plaît.</p>
<ol class="normaltext">
<li class="spaced">L'<strong>indentation</strong> doit être de 4 espaces. N'utiliser pas <strong>DU TOUT</strong> de tabulations.</li>
<li class="spaced">Les <strong>noms des variables</strong> doivent toujours être des mots anglais en minuscules, faciles à lire et ayant une signification claire. Si vous avez vraiment besoin de plusieurs mots, concaténez-les, mais gardez-les aussi courts que possible. Utilisez des noms au pluriel pour les tableaux d'objets.
<p class="examplecode"><font color="#006600">BON : $quiz<br />
BON : $errorstring<br />
BON : $assignments (pour un tableau d'objets)<br />
BON : $i (mais seulement dans de petites boucles)<br />
<br />
MAUVAIS : $Quiz <br />
MAUVAIS : $aReallyLongVariableNameWithoutAGoodReason<br />
MAUVAIS : $error_string</font></p></li>
<li class="spaced">Les noms des <strong>constantes</strong> doivent toujours être en majuscules, et toujours commencer par le nom du module. Les mots qui les constituent doivent être séparés par des caractères « souligné » (underscore).
<p class="examplecode"><font color="#006600">define("FORUM_MODE_FLATOLDEST", 1);</font></p></li>
<li class="spaced">Les noms des <strong>fonctions</strong> doivent être de simples mots anglais en minuscules, et commencer par le nom du module, pour éviter les conflits entre modules. Les mots qui les constituent doivent être séparés par des caractères « souligné » (underscore). Les paramètres doivent avoir si possible une valeur par défaut sensée. On ne place pas d'espace entre le nom de la fonction et la suite (parenthèses)
<p class="examplecode"> <font color="#007700">function </font><font color="#0000BB">forum_set_display_mode</font><font color="#007700">(</font><font color="#0000BB">$mode</font><font color="#007700">=</font><font color="#0000BB">0</font><font color="#007700">)
{<br />
global </font><font color="#0000BB">$USER</font><font color="#007700">,
</font><font color="#0000BB">$CFG</font><font color="#007700">;<br />
<br />
if (</font><font color="#0000BB">$mode</font><font color="#007700">)
{<br />
</font><font color="#0000BB">$USER</font><font color="#007700">-></font><font color="#0000BB">mode
</font><font color="#007700">= </font><font color="#0000BB">$mode</font><font color="#007700">;<br />
} else if (empty(</font><font color="#0000BB">$USER</font><font color="#007700">-></font><font color="#0000BB">mode</font><font color="#007700">))
{<br />
</font><font color="#0000BB">$USER</font><font color="#007700">-></font><font color="#0000BB">mode
</font><font color="#007700">= </font><font color="#0000BB">$CFG</font><font color="#007700">-></font><font color="#0000BB">forum_displaymode</font><font color="#007700">;<br />
}<br />
}</font></p>
</li>
<li class="spaced">Les <strong>blocs</strong> doivent toujours être placés entre accolades (même s'ils ne sont constitués que d'une ligne). Moodle utilise le style suivant :
<p class="examplecode"> <font color="#006600">if (</font><font color="#0000CC">$quiz</font><font color="#006600">-></font><font color="#0000CC">attempts</font><font color="#006600">)
{<br />
if (</font><font color="#0000CC">$numattempts </font><font color="#006600">>
</font><font color="#0000CC">$quiz</font><font color="#006600">-></font><font color="#0000CC">attempts</font><font color="#006600">)
{<br />
</font><font color="#0000CC">error</font><font color="#006600">(</font><font color="#0000BB">$strtoomanyattempts</font><font color="#006600">,
</font><font color="#CC0000">"view.php?id=$cm</font><font color="#006600">-></font><font color="#CC0000">id"</font><font color="#006600">);<br />
}<br />
}</font></p>
</li>
<li class="spaced">Les <strong>chaînes de caractères</strong> doivent être définies avec des apostrophes droites (pas des guillemets) lorsque c'est possible, afin d'améliorer les performances.
<p class="examplecode"> <font color="#006600">$var = 'some text without any
variables';<br />
$var = "with special characters like a new line \n";<br />
$var = 'a very, very long string with a '.$single.' variable in it';<br />
$var = "some $text with $many variables $within it"; </font></p>
</li>
<li class="spaced">Les <strong>commentaires</strong> doivent être ajoutés autant que possible, dans le but d'expliciter le fonctionnement du code et le pourquoi des fonctions et variables.
<ul>
<li>Toutes les fonctions (et les classes) doivent utiliser le format très répandu <a target="_blank" href="http://www.phpdoc.org/">phpDoc</a>, qui permet la génération automatique de la documentation du code.</li>
<li>Dans le code lui-même, il convient d'utiliser le style //, formatté proprement, de sorte que les commentaires soient bien ajustés et alignés avec le code.</li>
</ul>
<p class="examplecode"><font color="#ff8800">
/**<br />
* La description doit apparaître d'abord, avec des astérisques positionnés<br />
* exactement comme dans cet exemple. Pour vous référer à une autre fonction,<br />
* utiliser cette syntaxe : {@link clean_param()}. Après la description de la<br />
* fonction, ajouter celle de chacun des paramètre de la façon suivante.<br />
*<br />
* @param int $postid Le type PHP est suivi du nom de la variable<br />
* @param array $scale Le type PHP est suivi du nom de la variable<br />
* @param array $ratings Le type PHP est suivi du nom de la variable<br />
* @return mixed<br />
*/</font><br />
<font color="#006600">function </font><font color="#0000BB">forum_get_ratings_mean</font><font color="#007700">(</font><font color="#0000BB">$postid</font><font color="#007700">,
</font><font color="#0000BB">$scale</font><font color="#007700">, </font><font color="#0000BB">$ratings</font><font color="#007700">=</font><font color="#0000BB">NULL</font><font color="#007700">)
{<br /></font>
<font color="#007700">if (!</font><font color="#0000BB">$ratings</font><font color="#007700">)
{<br />
</font><font color="#0000BB">$ratings
</font><font color="#007700">= array(); </font><font color="#FF8000">//
Initialize the empty array</font><font color="#007700"><br />
if (</font><font color="#0000BB">$rates
</font><font color="#007700">= </font><font color="#0000BB">get_records</font><font color="#007700">(</font><font color="#DD0000">"forum_ratings"</font><font color="#007700">,
</font><font color="#DD0000">"post"</font><font color="#007700">, </font><font color="#0000BB">$postid</font><font color="#007700">))
{<br />
</font><font color="#FF8000">//
Process each rating in turn</font><font color="#007700"><br />
foreach
(</font><font color="#0000BB">$rates </font><font color="#007700">as </font><font color="#0000BB">$rate</font><font color="#007700">)
{</font> <br />
... etc. </p>
</li>
<li class="spaced">Les <strong>espaces</strong> doivent être utilisés généreusement. N'ayez pas peur d'espacer les lignes pour accroître la lisibilité. En général, il doit y avoir un espace entre les parenthèses et les instructions normales, mais aucun espace entre les parenthèses et les variables ou fonctions :
<p class="examplecode"> <font color="#007700">foreach (</font><font color="#0000BB">$objects
</font><font color="#007700">as </font><font color="#0000BB">$key </font><font color="#007700">=></font><font color="#0000BB">
$thing</font><font color="#007700">)</font><font color="#006600"> {<br />
</font><font color="#007700"> </font><font color="#0000BB">process($thing);</font><font color="#006600">
<br />
} <br />
<br />
</font><font color="#007700">if (</font><font color="#0000BB">$x </font><font color="#007700">==
</font><font color="#0000BB">$y</font><font color="#007700">)</font><font color="#006600">
{<br />
</font><font color="#007700"> </font><font color="#0000BB">$a
</font><font color="#007700">= </font><font color="#0000BB">$b</font><font color="#007700">;</font><font color="#006600"><br />
} else if (</font><font color="#0000BB">$x </font><font color="#007700">==
</font><font color="#0000BB">$z</font><font color="#006600">) {<br />
</font><font color="#007700"> </font><font color="#0000BB">$a
</font><font color="#007700">= </font><font color="#0000BB">$c</font><font color="#007700">;</font><font color="#006600"><br />
} else {<br />
</font><font color="#007700"> </font><font color="#0000BB">$a
</font><font color="#007700">= </font><font color="#0000BB">$d</font><font color="#007700">;</font><font color="#006600"><br />
} </font></p>
</li>
</ol>
<p> </p>
<h2>Structure des bases de données</h2>
<ol class="normaltext">
<li class="spaced">Toutes les tables doivent avoir un champ <strong>id</strong> (INT10) à incrémentation automatique pour index principal.</li>
<li class="spaced">La table principale contenant les instances de chaque module doit avoir le même nom que le module (par exemple <strong>bidule</strong>) et doit contenir au moins les champs suivants :
<ul>
<li><strong>id</strong> : voir description ci-dessus</li>
<li><strong>course</strong> : l'identifiant du cours auquel appartient chaque instance</li>
<li><strong>name</strong> : le nom complet de chaque instance du module</li>
</ul>
</li>
<li class="spaced">Les autres tables associées à un module et contenant des informations sur des « machins » doivent être appelées <strong>bidule_machins</strong> (remarquez le pluriel).</li>
<li class="spaced">Les noms de colonnes doivent être simples et courts, suivant les mêmes règles que les noms des variables.</li>
<li class="spaced">Si possible, les colonnes faisant référence au champ id d'une autre table (par exemple <strong>bidule</strong>) doivent être appelées <strong>biduleid</strong>. Cette convention est nouvelle, et n'a pas été suivie dans certaines tables plus anciennes.</li>
<li class="spaced">Les champs booléens doivent être implémentés comme des entiers petits (par exemple INT4) contenant 0 ou 1, afin de permettre une éventuelle extension des valeurs si nécessaire.</li>
<li class="spaced">La plupart des tables doivent avoir un champ <strong>timemodified</strong> (INT10) qui soit mis à jour avec la date et l'heure obtenue avec la fonction PHP <strong>time()</strong>.</li>
</ol>
<hr />
<h2>Problèmes de sécurité (et traitement des données des formulaires et des URLs)</h2>
<ol class="normaltext">
<li class="spaced">Ne vous basez pas sur l'option « register_globals ». <strong>Toutes</strong> les variables doivent être correctement initialisées dans <strong>tous</strong> les fichiers de code. La provenance du nom de la variable doit être évidente.</li>
<li class="spaced">Initialisez tous les tableaux et tous les objets, même lorsqu'ils sont vides. <code>$a = array()</code> ou <code>$obj = new stdClass();</code>.</li>
<li class="spaced">N'utilisez pas la fonction <code>optional_variable()</code>. Utilisez en lieu et place la fonction <code>optional_param()</code>. Choisissez la valeur PARAM_XXXX correcte pour le type de données que vous attendez. Pour vérifier et assigner une valeur optionnelle à une variable, utilisez la fonction <code>set_default()</code>.</li>
<li class="spaced">N'utilisez pas la fonction <code>require_variable()</code>. Utilisez en lieu et place la fonction <code>required_param()</code>. Choisissez la valeur PARAM_XXXX correcte pour le type de données que vous attendez.</li>
<li class="spaced">N'utilisez pas si possible la fonction <code>data_submitted()</code>, car elle court-circuite les fonctions de nettoyage de <code>required_param()</code> et de <code>optional_param()</code>.
<li class="spaced">N'utilisez pas <code>$_GET</code>, <code>$_POST</code> ni <code>$_REQUEST</code>. Utilisez la fonction <code>required_param()</code> ou <code>optional_param()</code> appropriée à vos besoins.</li>
<li class="spaced">Ne vérifiez pas l'exécution d'actions avec par exemple <code>if (isset($_GET['something']))</code>. Utilisez plutôt <code>$something = optional_param( 'something',-1,PARAM_INT )</code> et effectuez ensuite un test correct pour vérifier si la valeur se trouve dans l'intervalle voulu, par exemple <code>if ($something>=0) {...</code>.</li>
<li class="spaced">Groupez chaque fois que cela est possible vos <code>required_param()</code>, <code>optional_param()</code> et les autres initialisations de variables initialisation au début de chaque fichier, de sorte qu'elles soient faciles à trouver.</li>
<li class="spaced">Utilisez le mécanisme « sesskey » pour protéger vos routines de traitement de formulaires d'éventuelles attaques. Un exemple simple : lorsque le formulaire est généré, ajoutez <code><input type="hidden" name="sesskey" value="<?php echo sesskey(); ?>" /></code>. Lors du traitement du formulaire, vérifiez avec <code>if (!confirm_sesskey()) {error('Bad Session Key');}</code>.</li>
<li class="spaced">Tous les noms de fichiers doivent être nettoyés par la fonction <code>clean_filename()</code>, pour autant que cela n'ait pas encore été fait par une utilisation adéquate de <code>required_param()</code> ou de <code>optional_param()</code>.</li>
<li class="spaced">Toutes les données lues dans la base de données doivent être passées par <code>addslashes()</code> avant d'être récrites dans la base de données. La fonction <code>addslashes_object()</code> permet de traiter ainsi un objet complet de données.</li>
<li class="spaced">Chaque fois que c'est possible, les données devant être stockées dans la base de données doivent provenir de données <code>POST</code> (d'un formulaire avec <code>method="POST"</code>), et non de données <code>GET</code> (c'est-à-dire provenant de l'URL).</li>
<li class="spaced">Si vous pouvez l'éviter, n'utilisez pas de données provenant de la variable <code>$_SERVER</code>, en raison de problèmes de portabilité.</li>
<li class="spaced">Si cela n'a pas été fait ailleurs, assurez-vous que toutes les données écrites dans la base de données ont été traitées par la fonction <code>clean_param()</code> avec le paramètre PARAM_XXXX adéquat au type de données.</li>
<li class="spaced">Si vous écrivez du code SQL brut, assurez-vous très attentivement qu'il est correct. Faites tout particulièrement attention aux guillemets manquants autour des valeurs, pouvant se transformer en autant de failles de sécurité (injections SQL).</li>
<li class="spaced">Vérifiez toutes les données (particulièrement celles qui sont écrites dans la base de données) dans <strong>tous</strong> les fichiers où elles sont utilisées. N'attendez rien et ne vous reposez sur rien de ce qui est fait ailleurs.</li>
<li class="spaced">Les blocs de code à inclure doivent comporter une structure PHP définie (par exemple, une déclaration de classe, des définitions de fonctions, etc.), Les blocs de code non structurés engendrent l'utilisation de variables non initialisées.</li>
</ol>
<p align="center"><font size="1"><a href="." target="_top">Documentation Moodle</a></font></p>
<p align="center"><font size="1">Version: $Id$</font></p>
</body>
</html>