Référence sur drupal.org : 17 Janvier 2009 – 00h32 - http://drupal.org/node/360052
Cette section expose les normes Drupal pour l’écriture du code et le maintien de la sécurité. Elle examine également un certain nombre de bonnes pratiques qui vous aideront à optimiser la vitesse et les performances de votre application.
Référence sur drupal.org : 8 Juin 2009 – 15h51 - http://drupal.org/coding-standards
Remarque : les Normes de programmation de Drupal s’appliquent au code de Drupal et à celui des modules tiers. Ce document est basé sur les normes de codage PEAR. Les commentaires et les noms devraient utiliser l’orthographe anglo-américaine (« color » et non pas « colour », etc).
Utilisez une indentation de 2 espaces, pas de tabulations.
Pas d’espace après le dernier mot de la ligne.
Les lignes doivent être formatées avec un \n en fin de ligne (fins de ligne Unix), pas de \r\n (fins de lignes Windows).
Tous les opérateurs tels que +, -, =, !=, ==, >, etc, doivent avoir une espace avant et après l’opérateur, pour améliorer la lisibilité.
Par exemple, une affectation doit être formatée $foo = $bar; au lieu de $foo=$bar;.
Cela concerne if, for, while, switch, etc. Voici un exemple de déclaration IF, puisque c’est une des plus complexe :
Les déclaration de structures de contrôle devraient avoir une espace entre le mot-clé et la parenthèse ouvrante, afin de les distinguer des appels de fonctions.
Vous êtes fortement encouragés à toujours utiliser les accolades, même dans les cas où elles seraient techniquement facultatives. Ceci accroît la lisibilité et réduit les risques d’erreurs de logique qui peuvent apparaître avec l’ajout de nouvelles lignes.
Pour les déclarations switch :
Les fonctions devraient être appelées sans espace entre le nom de la fonction, la parenthèse ouvrante, et le premier paramètre; espaces entre les virgules et chaque paramètre, la parenthèse fermante, le point-virgule. Voici un exemple :
Comme affiché plus haut, il devrait y avoir une espace de part et d’autre du signe égal utilisé pour affecter la valeur de retour de la fonction à la variable. Dans le cas de blocs comportant plusieurs affectations, plus d’espaces peuvent être insérées afin d’accroître la lisbilité :
Les arguments ayant des valeurs par défaut se trouvent en dernières positions de la liste d’arguments. Tentez toujours de retourner une valeur d’une fonction s’il en existe d’adéquate.
Les tableaux devraient être formatés avec une espace séparant chaque élément et opérateur d’affectation, si le tableau le permet :
Notez que si la ligne dépasse 80 caractères (ce qui est souvent le cas pour la déclaration d’un formulaire ou d’un menu) chaque élément devrait être disposé dans sa propre ligne, et indenter d’un niveau :
Notez la virgule après les dernier élément du tableau. Ce n’est pas de la typographie ! Cela évite des erreurs de parsing si un autre élément est ultérieurement placé en fin de liste.
Les guillemets simples et doubles sont des caractéristiques de PHP pour faciliter la programmation et il n’y a pas de raisons qui feraient préférer les uns ou les autres. Cette pratique est laissée à l’appréciation du programmeur. Quand c’est possible, soyez cohérents dans tous vos modules et respectez le style des autres développeurs.
Avec cette mise en garde : les guillemets simples sont connus pour être plus rapides puisque le parser n’a pas à recherche des variables dedans. Leur utilisation est recommandée sauf dans deux cas :
1.utilisation de variables à l’intérieur des guillemets
2.Chaînes traduites où l’on peut éviter l’échappement des guillemets simples en encadrant la chaîne de doubles guillemets. Une chaîne de ce type « C’est un bon gars » deviendrait ’C\’est un bon gars » avec des guillemets simples. Ce type d’échappement pourrait ne pas être correctement géré par les générateurs de fichiers de traductions .pot.
Pour améliorer la lisibilité, utilisez toujours une espace entre le point et les chaînes à concaténer :
<?php
$string = 'Foo' . $bar;
$string = $bar . 'foo';
$string = bar() . 'foo';
$string = 'foo' . 'bar';
?>Quand vous concaténez des variables simples, vous pouvez utiliser de guillemets doubles et ajouter la chaîne dedans, sinon utilisez des guillemets simples.
<?php
$string = "Foo $bar";
?>Quand vous utilisez l’opérateur de concaténation .=, utilisez une espace de part et d’autre, comme pour le signe égal :
<?php
$string .= 'Foo';
$string .= $bar;
$string .= baz();
?>La documentation au sein du code-source devrait respecter les normes de formatage Doxygen.
Les commentaires divers sont fortement encouragés. Une règle générale dit que si vous regardez une portion de code et vous exclamez « La vache ! Je ne veux pas essayer d’expliquer ça ! », alors vous devez commenter le code avant d’oublier comment il marche.
Les commentaires divers devraient utiliser des phrases avec des majuscules et ponctuées. Les phrases devraient être séparées par des espaces simples. Les lettres ne doivent être en capitales que pour désigner les constantes, par exemple : TRUE. Les commentaires devraient être sur une ligne à part juste avant la ligne de code ou le bloc de code qu’ils désignent. Par exemple :
Si chaque ligne d’une liste a besoin d’un commentaire, ils peuvent être placés sur la même ligne et indentés de façon uniforme pour une meilleure lisibilité.
Les commentaires comme en C /* */ et en C++ // sont valables. L’utilisation de commentaires à la façon Perl/shell # sont déconseillés.
Quel que soit l’endroit où vous incluez un fichier de classe inconditionnellement, utilisez require_once().
Quel que soit l’endroit où vous incluez un fichier de classes conditionnellement (par exemple, pour des factory methods), utilisez include_once().
Chacune de ces instructions fera en sorte que les fichiers classes ne soient inclus qu’une fois. Elles partagent la même liste de fichiers ce qui fait que vous pouvez les mélanger sans crainte – un fichier inclus avec require_once() ne sera pas à nouveau inclus avec include_once().
Remarque : include_once() et require_once() dont des instructions, pas des fonctions. Vous n’avez pas besoin des parenthèses autour du nom de fichier à inclure.
Lorsque vous incluez du code du même dossier ou d’un sous-dossier, commencez le chemin du fichier avec . :
include_once ./includes/mymodule_formatting.inc
Dans Drupal 7.x et ultérieur, utilisez DRUPAL_ROOT :
require_once DRUPAL_ROOT . '/' . variable_get('cache_inc', 'includes/cache.inc');
Utilisez toujours <?php ?> pour délimiter le code PHP, pas le raccourci <? ?>. C’est exigé pour la conformité avec Drupal et c’est aussi la façon la plus portable d’inclure du code PHP sur différents systèmes d’exploitation ou configurations.
Notez qu’à compter de Drupal 4.7, le ?> à la fin du code est volontairement omis. Cela concerne les modules et les fichiers inclus. En voici brièvement les raisons :
Le langage PHP exige la présence de points-virgules à la fin de la plupart des lignes mais permet leur omission à la fin d’un bloc de code.
Les normes de programmation Drupal les exigent, même à la fin d’un bloc de code. En particulier pour les blocs d’une seule ligne :
<?php print $tax; ?> -- YES
<?php print $tax ?> -- NO
?>Tout code source du core de Drupal devrait contenir le bloc de commentaire suivant en en-tête :
Cette étiquette sera complétée avec des infos utiles par le CVS :
Utilisez « example.com » pour toutes les exemples d’URL, comme expliqué dans RFC 2006.
Les noms de fonctions doivent être en minuscules et les mots séparés par un signe souligné. De plus, le nom du module doit préfixer le nom, pour éviter les conflits entre les modules.
Les membres de classes privées (c’est à dire les membres de classes destinées à n’être utilisées que dans la classe où ils sont déclarés) sont précédés par un signe souligné unique. Par exemple :
_node_get()
$this->_status
Les constantes doivent toujours êtres écrites en majuscules, avec un signe souligné » séparant les mots. Cela concerne les constantes pré-déclarées de PHP, comme TRU, FLASE et NULL. Les constantes déclarées dans les modules doivent aussi être préfixées par le nom du module où elles sont déclarées, en majuscules.
Si vous avez besoin de définir des variables globales, leur nom doit commencer par un signe souligné unique, suivi du nom du thème ou du module et d’un autre signe souligné.
Les classes doivent être nommées en utilisant le style CamelCase. Par exemple :
<?php
abstract class DatabaseConnection extends PDO {
?>Les méthodes de classe et les propriétés doivent utiliser le style lowerCamelCase
<?php
public $lastStatement;
?>Tous les fichiers de documentation doivent porter l’extension .txt pour pouvoir les repérer facilement sur un système Windows. De même, les noms de ces fichiers doivent être entièrement en capitales (par exemple : README.txt au lieu de readme.txt), tandis que l’extension doit toujours être en minuscules (c’est à dire .txt au lieu de .TXT).
Exemples : README.txt, INSTALL.txt, TODO.txt, CHANGELOG.txt etc.
Drupal dispose d’un script en ligne de commande pour vérifier si votre code satisfait aux normes de codage. Le fichier code-style.pl est situé dans le dossiers /scripts. Pour l’utiliser, indiquez simplement votre fichier en argument (assurez-vous que le script soit exécutable :
./code-style.pl path/to/file/example.module
Vous obtiendrez une liste de propositions sur les endroits de votre code à améliorer. Vous devrez effectuer ces modifications vous-même.
Il existe un module qui vous assiste dans les révisions du code. Pour l’utiliser, effectuez les opérations suivantes :
Référence sur drupal.org : 28 Mai 2009 – 14h16 - http://drupal.org/node/1354
Doxygen est un logiciel permettant de créer une documentation. Les informations sont directement puisées dans le code-source, ce qui en rend la maintenance plus aisée et plus conforme avec le code-source.
Le site Doxygen fournit un excellent manuel de l’utilisateur. Les notes qui suivent concernent l’implémentation de Doxygen dans Drupal.
Pour documenter un bloc de code, la syntaxe à utiliser est la suivante :
Doxygen analysera tout commentaire placé dans ce type de bloc. Notre but est d’utiliser le moins de commandes Doxygen possibles, pour préserver la lisibilité du code. Toute mention de fonctions ou de fichiers dans la documentation sera automatiquement liée au code correspondant, il sera donc inutile de présenter les balises qui génèrent les liens.
Il est recommandé de de décrire, en début de chaque fichier, ce qu’il fait. Par exemple :
La ligne se trouvant juste après la directive @file est une brève description qui sera affichée dans la liste des fichiers de la documentation. Si la ligne commence par un verbe, il devra être au présent (par exemple : « Handles files uploads »). Une description plus détaillée peut se trouver après une ligne vierge.
Pour ajouter à votre fichier la balise ID du CVS, ajoutez un // $Id$ à votre fichier. CVS le complétera automatiquement au format indiqué précédemment. Dans le futur, vous n’aurez plus à vous en préoccuper car CVS actualisera automatiquement cette information.
Pour les fichiers .install, le modèle suivant est utilisé :
Toutes les fonctions susceptibles d’être appelées par d’autres fichiers devraient être documentées; les fonctions privées peuvent également être documentées. Un bloc de documentation de fonction devrait immédiatement précéder la déclaration de fonction elle-même, comme ceci :
La première ligne du bloc devrait contenir une brève description de ce que fait la fonction, elle débutera par un verbe sous la forme « Do such and such » (plutôt que « Does such and such »). Une description plus longue, comprenant des indications d’utilisation peut être ajoutée, en laissant une ligne vierge avant.
Les paramètres seront mentionnés avec la directive @param, avec leur description dans la ligne d’après. Après tous les paramètres, une directive @return doit être utilisée pour indiquer la valeur retournée par la fonction, si elle existe. Il n’y a pas de ligne vierge entre les directive @param et @return.
Les fonctions qui peuvent être décrites en une seule ligne peuvent omettre ces directives, comme ci-dessous :
Les paramètres et la valeur de retour doivent être décrits dans cette seule ligne de description.
De nombreux modules sont constitués d’implémentation de hooks. Si l’implémentation est plutôt standard et n’exige pas plus d’explications que celles fournies par la référence au hook, une courte documentation peut être utilisée :
Ceci génère un lien vers la référence du hook, rappelle au développeur qu’il s’agit d’une implémentation de hook, et évite d’avoir à documenter les paramètres et les valeurs de retour, qui sont les mêmes pour chaque implémentation du hook.
Pour fournir un guide de référence sommaire aux concepteurs de thèmes, on balise chacune des fonction qui construisent les formulaires, ainsi Doxygen peut les regrouper ensemble.
Une fonction de construction de formulaire est une fonction pouvant être utilisée comme argument pour drupal_get_form. Pour ce faire, ajoutez une instruction de regroupement à la documentation de cette fonction. De plus, alors que submit, validate et autre gestionnaires du formulaire ne sont pas destinés à figurer dans le groupe, vous devrez fournir un @see pour fournir une référence aux gestionnaires rattachés à ce formulaire.
Pour fournir un guide de référence sommaire aux développeurs de thèmes, on balise toutes les fonctions « thémables » pour que Doxygen puisse les regrouper sur une seule page. Pour ce faire, ajoutez une instruction de regroupement à la documentation de ces fonctions :
Si une gabarit et une fonction de pré-traitement est utilisé à la place d’une fonction de thème, une déclaration de fonction vide pour la fonction de thèe qui n’est pas utilisée doit être placée dans la documentation contributive (contributions/docs/developer/theme.php).
Le gabarit lui-même doit être documentée avec la directive @file et doit contenir la liste des variables que template_preprocess_HOOK lui a préparé.
Si l’une de ces variables contient des données dont il est, pour x raisons, risqué d’afficher la valeur, elles doivent être documentées; sinon, on suppose que les variables disponibles sont correctement filtrées. Ce qui n’est pas listé ne doit pas être considéré comme sûr pour l’affichage.
La directive @see doit également être mentionnée pour un lien vers les fonctions de pré-traitement et les fonctions theme_X
La fonction template_preprocess_HOOK doit également contenir les directives @see adéquates.
Une façon de faire conseillée pour l’utilisation de regroupement Doxygen dans les modules tiers et les thèmes est la suivante :
Dans votre example.module principal :
Dans les autres modules et fichiers de code de votre module :
De cette façon, vous avez tous les fichiers du module présentés ensemble dans le groupe « example ».
Le module de traitement Doxygen de Drupal, api.module, ne supporte actuellement qu’un petit ensemble des commandes Doxygen et s'attend à quelque formatage du code-source. Le code à faire traiter par l’api.module doit se conformer à ces conventions.
L’api.module ne supporte actuellement que l’un des trois mécanismes de regroupement de Doxygen : Modules (@defgroup, @ingroup, @addtogroup, @{, @}). Lorsque vous les utilisez, notez ce qui suit :
Pour voir Doxygen à l’œuvre sur la documentation du core Drupal, jetez un œil à ax' Drupal site. Plus particulièrement, regardez les « logs d’erreurs doxygen » et donnez un coup de main en améliorant la documentation du core Drupal.
Référence sur drupal.org : 30 Avril 2009 – 08h55 - http://drupal.org/node/302199
Cet article est une suggestion. Voir la discussion sur http://groups.drupal.org/node/14421
Remarque : les normes de codage CSS pour Drupal s’appliquent au code faisant partie du core ou des modules tiers. Ce document se base sur les normes initialement proposées par Nick Lewis.
Les discussions sur ces normes se poursuivent ici : http://groups.drupal.org/node/14421
Tout le code CSS devrait être répondre aux normes, de préférence à la norme CSS 2.1, mais la norme CSS 3.0 est acceptable à condition que son utilisation soit justifiée et qu’il puisse y être dérogé sans altération majeure de la présentations.
Les sélecteurs doivent être sur une seule ligne, avec une espace après le dernier sélecteur, suivi par une accolade. Un sélecteur doit se terminer par une accolade fermante, non indentée, sur une ligne séparée.
En cas de sélecteurs multiples, ils doivent figurer chacun sur une seule ligne, sans espaces après la virgule.
Toutes les propriétés doivent se trouver sur la ligne qui suit l’accolade.
Chaque propriété doit :
Les propriétés doivent être classées par ordre alphabétique. Plutôt que d’avoir ceci
vous devriez avoir cela
Lorsque des propriétés peuvent avoir des valeurs multiples, chacune de ces valeurs doit être séparé par une espace :
Les fichiers CSS devraient être annotés en utilisant la syntaxe CSSdoc. Comme pour les normes de codage PHP, un bloc de documentation doit être utilisé comme ci-dessous, pour décrire la section de code qui suit le commentaire :
Une balise CVS ID et un bloc CSSdoc de version de fichier devraient être placés au début du fichier pour décrire le contenu du fichier :
La balise CVS ID sera complétée par le CVS avec les informations adéquates
De brefs commentaires peuvent être ajoutés après une propriété, précédés par une espace :
Drupal supporte le chargement conditionnel des fichiers CSS comportant des règles pour les langues s’écrivant de droite à gauche.
Pour un module, la surcharge de la règle doit se trouver dans un fichier nommé MODULE-rtl.css, par exemple node-rtl.css.
Pour un thème, la règle qui est surchargée doit être commentée dans la règle CSS par défaut.
Dans node-rtl.css:
La règle dans node.css sera surchargée si le fichier rtl.css est chargé :
Voir aussi http://drupal.org/node/132442#language-rtl.
En règle générale, vous devriez ajouter un commentaire /* LTR */ dans votre feuille de style :
Référence sur Drupal.org : 25 Octobre 2008 – 08h13 - http://drupal.org/node/546
Tout le code-source de Drupal doit débuter par un en-tête contenant le mot-clé $Id$.
Si vous ajoutez un nouveau fichier au CVS, écrivez simplement
Copiez cette ligne 1.1. Notez que :
Fichiers CSS
doivent contenir la balise CVS ID sur la première ligne utilisant un commentaire CSS correct.
Attention : avec certains navigateurs, utiliser un commentaire ou une syntaxe de commentaire incorrects peut casser toute la feuille de style.
Fichiers JavaScript
doivent contenir la balise CVS ID sur la première ligne utilisant un commentaire JS correct.
Fichier .info
doivent contenir la balise CVS ID sur la première ligne, précédée d’un point-virgule
Fichiers Texte
comme README.txt ou CHANGELOG.txt, doivent contenir la balise CVS ID sur la première ligne, en utilisant l’une de ces notations :
Notez que si votre copie locale ne complète pas ces mots-clé, il est possible que votre client CVS soit mal paramétré, ou que quelqu’un avec un client CVS mal paramétré ait fait un check-in du fichier, avec un flag qui désactive la substitution du mot-clé.
Vous pouvez utiliser cvs status et chercher la ligne Sticky options. Si vous voyez -ko ou -kb, cela signifie que la substitution de mot-clé a été désactivée pour ce fichier. Dans ce cas, vous pouvez exécuter cvs admin -kkv [nomdefichier] pour rétablir la substitution. Si vous utiliser une interface graphique pour CVS, y trouver la façon de spécifier ce flag est laissé au soin du lecteur...
Référence sur drupal.org : 14 Mars 2009 – 22h26 - http://drupal.org/node/2497
N’utilisez pas les mots-clé de (ANSI) SQL / MySQL / PostgreSQL / MS SQL Server / …, les mots-clés pour les noms de colonnes, tables. Même si ça marche bien avec votre installation de xxSQL, ça peut ne pas marcher du tout avec d’autres, ou avec d’autres bases de données.
Quelques références :
Quelques mots-clés fréquemment mal-employés : TIMESTAMP, TYPE, TYPES, MODULE, DATA, DATE, TIME, ...
Voir aussi [bug] SQL Reserved Words.
<?php%d|%s|%%|%f|%b?>).
Cela garantit que les données seront correctement
échappées et évite les attaques par injection de code SQL.Exemple :
<?php
db_query("INSERT INTO {filters} (format, module, delta, weight) VALUES (%d, 'php', 0, 0)", $format);
?>
Remarque : depuis Drupal 6.x, les déclarations de tables et de contraintes (comme les clés primaires, clés uniques, indexes) doivent toujours être manipulés par Schema API, qui résout automatiquement les questions de compatibilité inter-bases de données.
Remarque : depuis Drupal 6.x, les déclarations de table et de contraintes doivent toujours être gérées par l’API Schema.
Beaucoup de serveurs de bases de données utilisent une extension pour le SQL standard. Cependant, plusieurs d’entre eux peuvent être configurés pour s'exécuter dans plus d’un standard. Chaque développeur est encouragé à utiliser le mode le plus conforme à la norme pour éviter le codage fantaisiste et des problèmes de compatibilité.
MySQL
Activez les mode ANSI et Strict.
Merci de nous aider à compléter cette liste de serveur de bases de données !
Drupal n’a pas de méthodes normalisée pour l’indentation ou la mise en forme de requêtes SQL longues sur plusieurs lignes. Parmi ces méthodes, on a :
<?php
if (!(db_query(
"
INSERT INTO {mlsp_media_file_type}
SET extension = '%s',
attributes = '%s'
",
$file_type_entry['extension'],
$selected_attributes
))) {
$errors = TRUE;
}
?>
ou
<?php
$sql = "SELECT t.*, j1.col1, j2.col2"
. " FROM {table} AS t"
. " LEFT JOIN {join1} AS j1 ON j1.id = t.jid"
. " LEFT JOIN {join2} AS j2 ON j2.id = t.jjid"
. " WHERE t.col LIKE '%s'"
. " ORDER BY %s"
;
$result = db_query($sql, 'findme', 't.weight');
?>
Référence sur drupal.org : 15 Février 2009 – 20h02 - http://drupal.org/node/374660
Evitez l’utilisation du caractère * dans les requêtes SELECT. Il est nettement préférable de spécifier les champs qui doivent être sélectionnés.
Avant Drupal 7.x, l’utilisation de requêtes comme SELECT * FROM {node} pouvait présenter un risque de sécurité car elles outrepassent le système d'accès aux nodes de Drupal (Drupal's Node Access). Dans ce cas de figure, du contenu confidentiel pouvait être affiché aux utilisateurs non autorisés. Par conséquent, les requêtes qui génèrent des liste de nodes doivent toujours éviter la syntaxe SELECT *.
Ce n’est pas encore une norme de programmation dans Drupal, mais un consensus est en train de se faire pour que les requêtes du style SELECT * FROM... ou SELECT p.*, b.* FROM... soient évitées.
Référence sur Drupal.org : 3 Mai 2007 – 12h51 - http://drupal.org/node/141051
La liste ci-dessous regroupe les mots-clé SQL. Elle est établie à partir des sources suivantes :
Il y a bien évidemment d’autres sources qui pourraient êtres ajoutées à cette liste, mais elle n’en constitue pas moins un bon point de départ.
Référence sur drupal.org : 19 Avril 2009 – 00h48 - http://drupal.org/node/209715
Il est tenant d’utiliser un obscur symbole comme caractère de substitution, surtout s’il n’y a que votre code qui peut le voir : mais ce n’est pas garanti. Les symboles non imprimés, invalides ou non documentés peuvent ne pas être traitées correctement dans le cas improbable où ils seraient vus par un navigateur ou un aggrégateur de news. Et moins ils sont susceptibles d’êtres vus, moins ils sont susceptibles d’être testés. Ce qui signifie qu’il faudra coder de quoi supprimer ces insidieux symboles, y compris dans le code que vous utilisez à cette fin.
Pour éviter cela, et pour allonger la durée de vie de votre code, utilisez des chaînes alphanumériques adéquates – préfixées du nom du module et un tiret – ou un signe souligné _ et encadré de crochets […].
Si vous avez besoin de délimiter des symboles de substitution, le délimiteur fermant peut inclure un / après le [ initial et peut suffixer le nom du module.
Une PCRE comme '@\[modulename-tag\](.+?)\[/tag-modulename\]@' peut être utilisée pour trouver la chaîne que vous avez précédemment délimité.
Référence sur drupal.org : 26 Mai 2009 – 18h05 - http://drupal.org/node/473460
Si vous écrivez un module ou un thème, sachez qu’il pourra être utilisé sur des sites du monde entier, certains pouvant utiliser des langues dont les caractères sont codés sur plusieurs octets en Unicode plutôt que sur le seul octet des formats ASCII ou Européen. Certaines des fonctions intégrées de PHP pour le traitement des chaînes ne fonctionnent pas correctement sur des textes multi-octets.
Pour cette raison, Drupal fournit des fonctions qui remplacent les fonctions intégrées de PHP. Vous devez les utiliser lorsque vous programmez pour Drupal, sauf quand cela est précisé. Le module Coder peut vérifier votre module en vue de ces remplacements.
Voici ces fonctions :
Si vous programmez du texte, consultez également le guide to handling text in a secure fashion .
Référence sur drupal.org : 9 Avril 2009 – 01h34 - http://drupal.org/node/34341
Actuellement, le code Drupal n’est pas coforme E_STRICT. Quand vous faites tourner un site Drupal avec E_ALL, chaque page crée des tonnes de messages d’erreurs. Beaucoup de développeurs Drupal pensent qu’il serait bon que le code Drupal soit mis en conformité avec les bonnes pratiques couramment admises.
Le but de ce document est double :
Une fois que ces règles seront acquises, ce ne sera plus qu’une question de temps, et d’efforts pour les développeurs, pour que tout le code antérieur soit corrigé. Nous pourrons ensuite faire tourner Drupal avec la directive E_ALL.
Si vous voulez vérifier qu’un tableau a bien reçu une valeur, ne faites pas :
<?php
if ($foo) {}
?>mais faites plutôt :
<?php
// either
if (isset($foo)) {} // $foo=0 (zero) and $foo= '' return TRUE
// or
if (!empty($foo)) {} // use this when 0 or '' are not expected
// and are not valid values for $foo.
?>La différence entre isset() et !empty() est qu’à l’inverse de !empty(), isset() renverra TRUE même si la variable a été initialisée avec une chaîne vide ou l’entier 0. Pour déterminer quelle fonction utiliser, étudiez si 0 ou '' sont des valeurs possibles pour votre variable.
Le code suivant est incorrect :
<?php
function _form_builder($form, $parents = array(), $multiple = FALSE) {
// (...)
if ($form['#input']) {
// some code (...)
}
}
?>Ici, la variable $form est passée à la fonction. Si $form['#input'] a été initialisé avec n’importe quelle valeur, some code est exécuté. Le problème est qu’en testant de cette façon, cela affiche le message d’erreur suivant :
Même si le tableau $form est déjà déclaré et passé à la fonction, chaque index doit exlicitement être déclaré. Le code précédent devrait plutôt être écrit comme ceci :
<?php
function _form_builder($form, $parents = array(), $multiple = FALSE) {
// (...)
if (!empty($form['#input'])) {
// some code (...)
}
}
?>Attention !
La fonction isset() renvoie TRUE quand la variable est initialisée avec l’entier 0, mais FALSE lorsqu’elle l’est avec la valeur NULL. Dans certains cas, is_null() est préférable, surtout lorsqu’il s’agit de tester une valeur retournée par une requête SQL.
Si vous voulez aider au nettoyage du code Drupal pour qu’il soit confome à E_STRICT, vous pouvez paramétrer un site de test et modifier le fichier includes/common.inc :
<?php
if ($errno & (E_ALL ^ E_NOTICE)) {
?>en :
<?php
if ($errno & (E_ALL )) {
?>Référence sur drupal.org : 8 Mars 2009 – 03h59 - http://drupal.org/node/161085
Lorsque vous soumettez (ou maintenez) des modules, l’existence d’une bonne documentation est vitale pour ceux qui viennent après vous. De nombreux ouvrages en parlent, et tout développeur digne de ce nom a son idée sur ce qui constitue une bonne documentation. Il y a toujours une ligne de démarcation entre trop de documentation et pas assez.
Les indications qui suivent doivent être utilisées pour les modules qui feront partie des modules contributifs de Drupal.
Ayez un README utile
Tous les modules, sauf les plus simples, doivent être accompagnés d’un README.txt. Ce fichier doit contenir un aperçu de ce que fait le module et de comment l’utiliser. Ce peut être une copie du résumé figurant sur la page du projet. Il est également conseillé de faire un lien direct vers le README.txt depuis la page du projet :
http://cvs.drupal.org/viewvc.py/drupal/contributions/modules/modulename/...
Ce fichier doit donner suffisamment d’informations à l’utilisateur pour qu’il puisse évaluer si le module correspond à ses besoins avant qu’il ne le télécharge et ne l’installe.
Utiliser hook-help
Tous les modules, sauf les plus simples, doivent, dans une certaine mesure, implémenter hook_help(). Reportez-vous à Embedded documentation style guide pour voir comment structurer votre documentation. Sinon, vous pouvez simplement inclure le README avec une fonction comme :
<?php
/**
* Implementation of hook_help().
*/
function mymodule_help($section) {
switch ($section) {
case 'admin/help#mymodule':
// Return a line-break version of the module README
return filter_filter('process', 2, NULL, file_get_contents( dirname(__FILE__)."/README.txt") );
}
}
?>Les pages d’aide Drupal sont évidemment l’endroit pour accéder aux informations sur votre module, à un niveau utilisateur ou développeur.
Dites aux utilisateurs ce que fait le module
Le README et l’aide doivent décrire comment accéder aux fonctionnalités du module.
Si le module fournit quelques éléments de menus, indiquez les chemins pour que l’utilisateur n’ait pas à les chercher dans l’interface d’administration.
S’il modifie des Interface Utilisateur de formulaires avec l’API Forms, dites à l’utilisateur ce qu’il doit chercher pour être sûr que ça marche.
Si le module a besoin d’un paramétrage, fournissez le lien vers la page d’administration et écrivez éventuellement un petit guide de démarrage.
Réfléchissez au nom du « package »
Vous pouvez définir un groupe dans le fichier module.info. Beaucoup de modules n’utilisent pas du tout de « package » groupe. Citation de la page « Comment écrire les fichiers .info » : « En règle générale, ce champ ne devrait être utilisé que par les grands modules multi-package, ou par les modules qui étendent ces packages, comme CCK, Views, E-Commerce, Organic Groups et assimilés ». Si vous avez une utilisation valable du package name, utilisez la liste existante des groupes de projets pour intituler votre module, veillez au respect des majuscules/minuscules.
Documentez toutes les fonctions correctement
Dans vos modules, vous êtes invité à utiliser des commentaires formatés Doxygen . Bien que cela ressemble parois à une tarte à la crème, apprenez à les apprécier, puisque ce sont ces commentaires qui alimentent l’intégralité du site api.drupal.org et peuvent faire la même chose pour vous en utilisant le module API. Votre code peut être auto-documenté... gratuitement !
De plus, beaucoup d’IDE sont à même de détecter automatiquement les blocs de documentation Doxygen, et de fournir une aide contextuelle. Sans compter les avantages évidents pour les personnes qui lisent votre code.
Lisez les règles d’écriture de commentaires et notamment m’utilisation de la directive @ingroup.
Les suggestions qui suivent ne sont pas sacro-saintes mais peuvent aider à rendre votre module plus developpeur-friendly.
<?php
/**
* Implementation of hook_install().
*/
function mymodule_install() {
drupal_set_message(st("YourModule settings are available under !link",
array( '!link' => l('Administer > Site configuration > Your Module ', 'admin/settings/yourmodule/settings' ) )
));
}
?>Référence sur drupal.org : 9 Février 2009 – 11h54 - http://drupal.org/node/223584
Le Drupal Markup Style Guide est un document en cours de rédaction sur la façon de :
Référence sur drupal.org : 26 Avril 2009 – 23h50 - http://drupal.org/node/172169
Utilisez une indentation de 2 espaces, pas de tabulations. Pas d’espace après le dernier mot de la ligne.
Utilisez toujours une espace entre le signe + et les chaînes à concaténer :
Quand vous utilisez l’opérateur de concaténation +=, utilisez une espace de part et d’autre, comme pour le signe égal :
A l’inverse des variables et fonctions déclarées dans le PHP Drupal, les noms de variables ou de fonctions JavaScript comportant plusieurs mots doivent être lowerCamelCased. La première lettre de chaque variable ou fonction doit être en minuscule, tandis que la première lettre de chaque mot doit être en capitale. Il ne devraient pas y avoir de signe souligné entre les mots.
JavaScript autorise l’utilisation de toute expression comme instruction et utilise le point-virgule pour signaler la fin d’une instruction.
Cependant, cela devient facultatif avec les « semi-colon insertion »
(ajout, par JavaScript, d’un point-virgule entre deux instructions se trouvant sur deux lignes à la suite, exemple :
devient
mais cela peut masquer des erreurs et causer un échec de l’aggrégation du code.
Toutes les instruction doivent être suivies d’un ; à l’exception des suivantes :
for, function, if, switch, try, while
Ces exceptions sont les fonctions déclarées comme
et
Elles doivent toujours être suivies d’un point-virgule.
De plus, le valeur de l’expression return doit débuter sur la même ligne que le mot-clé return, pour éviter l’ajout du point-virgule.
Si l’option de performance Drupal 6 « Optimiser les fichiers JavaScript » est activé et s’il manque des points-virgule, alors l’aggrégation JS échouera. Il est donc très important que les points-virgules soient utilisés.
Cela concerne if, for, while, switch, etc. Voici un exemple de déclaration IF, puisque c’est une des plus complexe :
Les déclaration de structures de contrôle doivent avoir une espace entre le mot-clé et la parenthèse ouvrante, afin de les distinguer des appels de fonctions.
Vous êtes fortement encouragés à toujours utiliser les accolades, même dans les cas où elles seraient techniquement facultatives. Ceci accroît la lisibilité et réduit les risques d’erreurs de logique qui peuvent apparaître avec l’ajout de nouvelles lignes.
Pour les déclarations switch :
Les instructions try doivent avoir la forme suivante :
L’instruction for in permet de parcourir toutes les propriétés d’un objet. Malheureusement, tous les membres qui auront été hérités via la chaîne prototype seront également inclus dans la boucle.
Pour éviter cela, le corps de chaque instruction for in doit être encadrée par une instruction IF agissant comme filtre. Elle peut sélectionner un type ou une série de valeurs particuliers, ou elle peut exclure des fonctions, ou elle peut exclure des propriétés du prototype. Par exemple :
Vous pouvez utiliser la méthode hasOwnProperty pour différencier les vrais membres de l’objet :
Les méthodes et fonctions doivent être nommées en utilisant lowerCamelCase :
Les fonctions doivent être appelées sans espace entre le nom de la fonction, la parenthèse ouvrante, et le premier paramètre; espaces entre les virgules et chaque paramètre, la parenthèse fermante, le point-virgule. Voici un exemple :
Comme affiché ci-dessus, il devrait y avoir une espace de part et d’autre du signe égal utilisé pour affecter la valeur de retour de la fonction à la variable. Dans le cas de blocs comportant plusieurs affectations, plus d’espaces peuvent être insérées afin d’accroître la lisbilité :
Si une fonction littérale est anonyme, il doit y avoir une espace entre le mot function et la parenthèse gauche. Si l’espace est omis, il se pourrait que l’on prenne le mot « function » comme nom de fonction.
Les arguments ayant des valeurs par défaut se trouvent en dernières positions de la liste d’arguments. Tentez toujours de retourner une valeur d’une fonction s’il en existe d’adéquate.
Prenez en compte la notion de fonction anonyme décrite ci-dessus.
Toutes les variables doivent être déclarée avec le mot var avant d’être utilisées et ne doivent être déclarées qu’une seule fois. Cela facilite la lecture du programme et la détection de variables non déclarées qui peuvent devenir implicitement globales.
La portée des variables ne devrait pas être globale; essayez de leur donner une portée locale en les déclarant à tout prix dans une fonction. Toutes les variables doivent être déclarées au début des fonctions.
lowerCamelCasing doit être utilisé pour les constantes pré-définies. A l’inverse des normes pour le PHP, vous devez utilisez true, false et null puisque les majuscules ne sont pas valides en JavaScript.
Les variables ajoutées via drupal_add_js() doivent aussi être lowerCamelCased, pour être en conformité avec les autres variables une fois qu'elles seront utilisées dans le JavaScript.
<?php
drupal_add_js(array('myModule' => array('basePath' => base_path())), 'setting');
?>Cette variable sera référencée :
Les tableaux devraient être formatés avec une espace séparant chaque élément et opérateur d’affectation, si le tableau le permet :
Notez que si la ligne dépasse 80 caractères (ce qui est souvent le cas pour la déclaration d’un formulaire ou d’un menu) chaque élément devra être disposé dans sa propre ligne, et indenter d’un niveau :
Notez qu’il n’y a pas de virgule après le dernier élément du tableau. C’est une différence avec les normes PHP. En JavaScript, mettre une virgule après le dernier élément du tableau causera une exception.
La documentation au sein du code-source devrait respecter les normes de formatage Doxygen.
Les commentaires divers sont fortement encouragés. Une règle générale dit que si vous regardez une portion de code et vous exclamez « La vache ! Je ne veux pas essayer d’expliquer ça ! », alors vous devez commenter le code avant d’oublier comment il marche. Les commentaires peuvent être enlevés ultérieurement par les utilitaires JS, ils n’impactent donc pas la taille du fichier téléchargé.
Les commentaires divers devraient utiliser des phrases avec des majuscules et ponctuées. Les lettres ne doivent être en capitales que pour désigner les constantes, par exemple : TRUE. Les commentaires devraient être sur une ligne à part juste avant la ligne de code ou le bloc de code qu’ils désignent. Par exemple :
Si chaque ligne d’une liste a besoin d’un commentaire, ils peuvent être placés sur la même ligne et indentés de façon uniforme pour une meilleure lisibilité.
Les commentaires comme en C /* */ et en C++ // sont valables. L’utilisation de commentaires à la façon Perl/shell # sont déconseillés.
Tout code-source de Drupal doit contenir le commentaire suivant placé en début de fichier :
Cette balise sera complétée par le CVS avec les données utiles :
Autant que faire se peut, le code JavaScript ne devrait pas être liée au HTML car cela accroît significativement le poids d’une page sans offrir de possibilité de réduction par la mise en cache ou la compression.
L’instruction with est destinée à fournir un moyen d’accès rapide aux membres d’objets profondément imbriqués. Par exemple, il est possible (mais déconseillé) d’utiliser l’accès ci-dessous pour foo.bar.foobar.abc etc :
Cependant, en regardant ce code, il est impossible de savoir lequel d’entre abc et xyz sera modifié. foo.bar.abc sera-t-il modifié ? Ou les variables globales abc et xyz ?
Vous devriez plutôt utiliser la version longue :
ou si vous voulez réellement utiliser un raccourci, utilisez cette méthode :
Les opérateurs ==
et != effectuent
une conversion de type
implicite avant d’effectuer la comparaison. Ce qui est une mauvaise
chose puisque ' \t\r\n' == 0
sera vrai. Cela peut occulter des
erreurs de types. Pour les comparaisons avec l’une des valeurs
suivantes, utilisez les opérateurs ===
ou !== , qui ne
provoquent pas de contraintes de type : <?php0 '' undefined null false true?>
L’utilisation de l’opérateur virgule, qui entraîne l’exécution des expressions qui se trouvent à sa gauche et à sa droite, dans le sens gauche-droite et renvoie la valeur de l’expression située à sa droite, doit être évité. Un exemple d’utilisation est :
Cette instruction initialise x à 9. Cette opération est déroutante pour les utilisateurs qui ne sont pas familiarisés avec cette syntaxe et rend plus difficiles la lecture et la compréhension du code-source. En conséquence, évitez l’utilisation de l’opérateur virgule, sauf dans la partie contrôle d’une instruction FOR.
Ceci ne s’applique pas au séparateur virgule utilisé dans les objets, tableaux, etc.
Pour éviter le code inaccessible, une instruction return, break, continue ou throw doit être suivie d’une } ou d'un case ou d'un default.
Les constructeurs sont des fonctions conçues pour être utilisées avec le préfixe new. Ce préfixe crée un nouvel objet basé sur le prototype d’une fonction et lie cet objet aux fonctions par l’opérateur this. JavaScript n’émet pas d’avertissements si un new requis est omis. Si vous négligez le new, aucun nouvel objet ne sera créé et this sera lié à l’objet global (pas glop).
Les constructeurs doivent être nommés avec une initiale en majuscule et une fonction dont l’initiale du nom est en majuscule ne devrait pas être appelée à moins qu’elle n’ait le préfixe new.
Utilisez des expressions littérales à la place de l’opérateur new :
Dans la plupart des cas, la forme « wrapper » sera la même que l’expression littérale. Ce n’est cependant pas toujours le cas, voir l’exemple suivant :
eval() est mauvais. Il demande au navigateur de créer un nouvel environnement de scripting (comme la création d’une nouvelle page web), d’importer toutes les variables de l’environnement en cours, d’exécuter le script, de lancer le ramasse-miettes (garbage collector) et d’exporter la variable dans l’environnement d’origine. De plus, le code ne peut être mis en cache aux fins d’optimisation.
Il s’agit probablement de la fonction la plus puissante et la plus mal employée de JavaScript. Elle a aussi ses alias. Aussi, n’utilisez pas le constructeur Function et ne passez pas des chaînes à setTimeout() ou setInterval().
Toute sortie vers le navigateur qui a été fournie par l’utilisateur doit être exécutée dans la fonction Drupal.checkPlain(). Elle est semblable à la fonction PHP de Drupal check_plain() et encode les caractères spéciaux en plain-text pour l’afficher en tant qu’HTML.
Lorque vous utilisez une vérification tpeof, n’utilisez pas de parenthèse pour le typeof. Ce qui suit respecte les normes de programmation :
Lors de l’ajout de nouveaux éléments au DOM, n’utilisez pas document.createElement(). Pour des questions de compatibilité entre les navigateurs et aussi dans le but de réduire la taille des fichiers, utilisez son équivalent jQquery.
Ne faites pas :
Mais faites :
Drupal 6 a introduit l’habillage JavaScript et la traduction des fichiers JavaScript.
Il y a un mécanisme d’habillage pour le code JavaScript. Tout module contenant du JavaScript qui produit du contenu HTML doit fournir des fonctions de thèmes par défaut dans le Drupal.theme.prototype namespace.
Toutes les chaînes des fichiers JavaScript doivent être passées dans Drupal.t(), qui est l’équivalent de la célèbre fonction t(). De même, il y a aussi un équivalent à format_plural(), nommé Drupal.formatPlural(). L’ordre des paramètres est le même que pour les fonctions PHP.
Référence sur drupal.org : 15 Mai 2009 – 15h38 - http://drupal.org/writing-secure-code
Vous avez repéré un problème de sécurité ? Informez-en l’équipe de sécurité.
Que vous écriviez un petit bout de code ou un module de A à Z, il est important que votre code soit sécurisé.
Aucun contenu fourni par l’utilisateur ne doit être restitué tel quel dans le HTML.
Reportez-vous à Comment manipuler du texte de façon sûre pour plus d’informations
Utilisez la couche base de données correctement. Par exemple, ne concaténez jamais des données dans une requête SQL comme ceci :
<?php
db_query('SELECT foo FROM {table} t WHERE t.name = '. $_GET['user']);
?>A la place, utilisez les caractères de substitution avec db_query :
<?php
db_query("SELECT foo FROM {table} t WHERE t.name = '%s' ", $_GET['user']);
?>S’il y a un nombre variable d’arguments dans votre requête, créer un tableau de caractères de substitution. Ne faites pas ceci :
<?php
db_query("SELECT t.s FROM {table} t WHERE t.field IN (%s)", $from_user);
?>Mais faites cela :
<?php
$placeholders = implode(',', array_fill(0, count($from_user), "%d"));
db_query("SELECT t.s FROM {table} t WHERE t.field IN ($placeholders)", $from_user);
?>Beaucoup d’instructions SQL qui se réfèrent aux nodes ou à la table {node} doivent êtres emballées dans un appel à la fonction db_rewrite_sql() :
<?php
$result = db_query(db_rewrite_sql("SELECT n.nid, n.title FROM {node} n"));
?>Le mécanisme d’accès aux nodes de Drupal requiert ces appels. Sans eux, les visiteurs pourraient avoir accès à des nodes pour lesquels ils n’ont pas d’autorisation d’accès.
Référence sur drupal.org : 18 Mai 2009 – 20h51 - http://drupal.org/node/101496
Drupal fournit plusieurs fonctions pour envoyer des requêtes à la base de données. La forme classique est db_query. Utilisez toujours ces fonctions pour éviter les attaques par injection SQL. Cependant, n’utiliser que ces fonctions n’est pas suffisant, comme le montre l’exemple suivant :
<?php
/** Exemple 1 - Risqué
* SQL injection via $type
* Affiche les titres de nodes du type $type (indiqué par l'utilisateur vie une zone de saisie de formulaire)
*/
$result = db_query("SELECT n.nid, n.title FROM {node} n WHERE n.type = '$type'");
$items = array();
while ($row = db_fetch_object($result)) {
$items[] = l($row->title, "node/{$row->nid}");
}
return theme('item_list', $items);
?>Cet exemple affiche une liste de titres dépendants de l’argument fourni par l’utilisateur. Une liste de nodes page sera extraite lorsque $type sera page, une liste de nodes articles lorsque $type sera article. Malheureusement, cet exemple est vulnérable à une injection SQL.
La vulnérabilité peut être utilisée sur les bases de données supportant UNION (MySQL 4.1+) en obtenant un accès utilisateur au site, en indiquant comme type : story' UNION SELECT s.sid, s.sid FROM {sessions} s WHERE s.uid = 1/*.
Ce qui générera la requête suivante :
Comme ce code affichera des ID de session valides pour le compte administrateur, un agresseur pourra indiquer à son navigateur d’utiliser ces ID et aura tous les droits sur le site.
Empêcher l’injection SQL est facile : db_query fournit une méthode d’utilisation des requêtes paramétrées. Les fonctions de bases de données de Drupal remplacent le caractère de substitution avec l’argument correctement échappé, dans leur ordre d’apparition.
<?php
db_query("SELECT n.nid FROM {node} n WHERE n.nid > %d", $nid);
db_query("SELECT n.nid FROM {node} n WHERE n.type = '%s'", $type);
db_query("SELECT n.nid FROM {node} n WHERE n.nid > %d AND n.type = '%s'", $nid, $type);
db_query("SELECT n.nid FROM {node} n WHERE n.type = '%s' AND n.nid > %d", $type, $nid);
?>Les caractères de substitution valides sont renseignés dans la documentation de l’API :
Voici le premier exemple corrigé :
<?php
/** Exemple 1 - Corrigé
* Affiche les titres de nodes du type $type (indiqué par l'utilisateur vie une zone de saisie de formulaire)
*/
$result = db_query("SELECT n.nid, n.title FROM {node} n WHERE n.type = '%s'", $type);
$items = array();
while ($row = db_fetch_object($result)) {
$items[] = l($row->title, "node/{$row->nid}");
}
return theme('item_list', $items);
?>De temps à autre, vous aurez besoin d’injecter plusieurs arguments dans une requête, en utilisant la fonction IN().
Dans Drupal 5, vous utiliserez ce code :
<?php
$placeholders = implode(',', array_fill(0, count($from_user), "%d"));
db_query("SELECT t.s FROM {table} t WHERE t.field IN ($placeholders)", $from_user);
?>A partir de Drupal 6, une fonction db_placeholders est disponible. Exemple :
<?php
$values = array(1, 2, 3, 4, 5);
$placeholders = db_placeholders($values);
db_query("SELECT t.s FROM {table} t WHERE t.field IN ($placeholders)", $values);
?>Référence sur drupal.org : 2 Mars 2009 – 03h45 - http://drupal.org/node/101495
Les saisies, qu'elles viennent des internautes ou des serveurs, doivent être manipulées avec précaution.
Prenons l’exemple suivant, basé sur A programmer Introduction to PHP 4.0 de W.J. Gilmore. Il utilise une saisie effectuée par un utilisateur et la place dans une requête SQL :
<?php
/** Exemple 1 - Périlleux
* SQL injection via $keyword
*/
$keyword = $_REQUEST['keyword'];
$query = "SELECT cust_id, cust_name, cust_email FROM customers WHERE category = '$keyword'";
$result = db_query($query);
?>Ceci permet à l’utilisateur d’injecter des instructions SQL dans une requête. Que se passera-t-il si l’utilisateur utilise le mot-clé '; DROP TABLE customers; -- ? La requête sera SELECT cust_id, cust_name, cust_email FROM customers WHERE category = ''; DROP TABLE customers; --'
Vous avez peut-être déjà lu ce conseil d’expert dans les articles traitant des problèmes de sécurité : toujours valider les saisies. Le problème avec un CMS comme Drupal est que la notion de saisie n’est pas bien définie.
La seule chose que nous ayons à faire est que, indépendamment des données, leur contenu ne doit pouvoir être interprété comme du SQL. Nous utilisons pour cela les fonctions d’échappement fournies par l’API database. Nous faisons cet échappement dans la couche database et non juste après la saisie puisqu’il pourrait y avoir plus d’un échappement, ou filtrage, à faire.
<?php
/** Exemple 2 - Périlleux
* SQL injection via $keyword
* XSS via $keyword et (potentiellement) $row->cust_name, $row->cust_email
*/
$keyword = $_REQUEST['keyword'];
$query = "SELECT cust_id, cust_name, cust_email FROM customers WHERE category = '$keyword'";
$result = db_query($query);
echo "<h2>$keyword</h2>":
while ($row = db_fetch_object($result)) {
echo "$row->cust_name, $row->cust_email <br />";
}
?>Exemple 2 : bien qu’il soit modeste et truffé de failles, il met en évidence le problème du filtrage et de l’échappement des saisies. La variable $keyword doit être filtrée ou échappée deux fois pour différentes raisons : une pour empêcher les injections SQL, et une de plus pour empêcher les attaques par cross-scripting (XSS). Appliquer les deux filtres dès la saisie de $keyword provoquera l’apparition d’étranges barres obliques (slashes) dans les affichages, ou l’échec des recherches contenant des "
La solution consiste en utiliser le filtre adéquat au bon moment. Par exemple, juste avant d’envoyer le texte au navigateur ou avant de le mixer avec du code HTML, échappez-le avec check_plain.
<?php
/** Exemple 2 - corrigé
*/
$keyword = $_REQUEST['keyword'];
$query = "SELECT cust_id, cust_name, cust_email FROM customers WHERE category = '%s'";
$result = db_query($query, $keyword);
echo '<h2>'. check_plain($keyword) .'</h2>':
while ($row = db_fetch_object($result)) {
// Not very elegant, but making a point.
echo check_plain($row->cust_name) .','. check_plain($row->cust_email) .'<br />';
}
?>Référence Drupal.org : 4 Février 2009 – 10h22 - http://drupal.org/node/178896
Une attaque Cross-site request forgery (CSRF ou XSRF ) consiste à effectuer une requête vers un site comme si elle venait d’un utilisateur, alors que l’utilisateur n’a pas demandé cette requête. Cela peut se faire de différentes façons, mais il est simple de se prémunir contre ces attaques avec Drupal.
Les spécifications HTTP 1.1 distinguent clairement les requêtes POST qui peuvent modifier des données dans le site (section 9.5) des requêtes GET qui ne doivent pas modifier de données (section 9.3). Les modules qui modifient des données devraient exiger une requête POST (par exemple, dans un formulaire).
Dans les versions de Drupal antérieures à l’annonce SA-2007-017 il était possible de créer des pages spécifiquement conçues qui contenaient des balises image dans lesquelles l’élément src était un lien vers des menus désactivant les URL d’un site Drupal. Si l’administrateur du site visitait cette page alors qu’il était loggé dans son site, le navigateur effectuait une requête vers cette page, ce qui désavctivait alors les éléments de menu
In versions of Drupal prior to the release of SA-2007-017 it was possible to create a specifically formed page that contained image tags where the image "src" element was a link to certain menu "disable" URLs on a Drupal site. If a site admin visited that page when they were logged into their site then their browser would request the URL of the menu disable page which would then disable their menu items.
L’API Form fournit une protection contre les CSRF par l’ajout automatique de tokens spéciaux dans le formulaire. Si votre module utilise l’API Form pour toutes les requêtes qui modifient des données et si vous suivez correctement la documentation Form API, alors votre module est protégé contre les CSRF.
Le code incorrect peut être de deux sortes :
Vous pouvez voir un exemple de mauvais code et sa correction dans Drupal Core CSRF vulnerabilities fixed in 5.2
Voir la documentation de l’API Form.
Référence sur Drupal.org : 10 Avril 2008 – 12h02 - http://drupal.org/node/117054
(Cette section est en cours de rédaction)
Permettre la gestion des fichiers aux utilisateurs est potentiellement dangereux.
Vous devez être sûr qu’ils ne peuvent :
Par « divers » on parle de n’importe quel fichier sur le serveur. Ainsi, par exemple, si vous restreignez l’accès au seul dossier files on ne parle plus de fichiers divers. Mais si le code pour l’écriture des fichiers permet à l’utilisateur d’altérer le chemin d’accès, alors il pourra ajouter un ../../ au nom de fichier, ce qui le placera en-dehors du dossier files/ et lui donnera accès à d’autres dossiers de votre serveur.
Voyez également File Permissions and Ownership For Security.
Référence sur drupal.org : 29 Janvier 2008 – 17h59 - http://drupal.org/node/117058
Pour les débutants : assurez-vous toujours que les actions sur les fichiers (upload, visualisation, donwload, suppression) se fassent dans le dossier files ou dans tout autre dossier réservé à cet effet. Faites attention au fait que dans les exemples ci-dessous, le dossier files est codé en dur dans le code, en réalité le nom de ce dossier est paramétrable.
Les utilisateurs n’ont pas à accéder aux fichiers système (tels que /etc/password ou sites/default/settings.php). Bien que les exemples ci-dessous s’intéressent surtout à la suppression des fichiers, ayez à l’esprit que lire des fichiers quels qu’ils soient est néfaste.
<?php
/** Exemple 1 - Périlleux
* Suppression arbitraire de fichier
*
* $file est le chemin/fichier (eg files/myfile.txt) fourni par l'utilisateur.
*/
file_delete($file);
?>Dans ce premier exemple, un utilisateur malveillant peut outrepasser la confiance qui lui est donnée en fournissant des noms de fichiers dans différentes dossiers tels que /sites/default/settings.php. L’attaque est clairement limitée par les droits du compte utilisateur, qui exécute Drupal (souvent le serveur web), sur ces fichiers.
<?php
/** Exemple 2a - Périlleux
* Suppression arbitraire de fichier
*
* $file est le nom de fichier (eg. myfile.txt) fourni par l'utilisateur.
*/
file_delete("files/$file");
?><?php
/** Exemple 2b - Périlleux
* Suppression arbitraire de fichier
*
* $file est le chemin/fichier (eg files/myfile.txt) fourni par l'utilisateur.
*/
// Check whether $file is files/file
if (strpos($file, "files/") === 0) {
file_delete($file);
}
?>Les exemples 2a et 2b essaient d’atténuer l’attaque en s’assurant tout deux que le nom du fichier fourni soit précédé d’un nom de dossier. Ces deux exemples sont vulnérables à une attaque avec les dossiers parents (..).
Que se passerait-il si un utilisateur malveillant indiquait comme chemin :
Exemple 2a : ../sites/default/settings.php
Exemple 2b : files/../sites/default/settings.php
Les deux essaieront d’effacer sites/default/settings.php.
Pour une vérification correcte du vrai chemin d’un fichier, utilisez la fonction Drupal file_check_location.
<?php
/** Exemple 3
* N'est plus vulnérable aux attaques de type chemin-parent (..) .
*
* $file est le chemin/fichier (eg files/myfile.txt) fourni par l'utilisateur.
*/
// Check whether $file is files/file
if (file_check_location($file, 'files') {
file_delete($file);
}
?>Référence sur drupal.org : 12 Novembre 2008 – 04h55 - http://drupal.org/node/28984
Lorsque vous manipulez et affichez du texte en HTML, vous devez veiller à ce qu’un filtrage ou un échappement correct soit effectué. Autrement, il pourrait y avoir des bugs si des utilisateurs utilisent des crochets ou des esperluettes. Ou pire, vous pourriez ouvrir la voie à des attaques XSS.
Lorsqu’on manipule des données, la règle est d’enregistrer exactement ce que l’utilisateur a saisi. Lorsqu’il modifie un texte créé précédemment, le formulaire doit contenir exactement le texte saisi auparavant. Ce qui veut dire que les conversions se font lors de l’affichage du contenu, pas lors de sa sauvegarde dans la base de données (lisez bien la documentation db_query() sur la façon d’utiliser l’API database de façon sûre).
Pour déterminer les contrôles à effectuer, il peut être pratique de distinguer les textes selon leur nature. S’agit-il de texte seul (plain text), HTML, Bbcode ou Textile ? De là, chaque fois que vous concaténez deux chaînes de caractères, vous devez vous assurer qu’elles soient du même format. Si elles ne le sont pas, une vérification adéquate, une conversion ou un filtrage doit être appliqué.
Dans Drupal, les données soumises par les utilisateurs peuvent être réparties en trois catégories :
1. Texte seul (plain text)
C’est du texte simple, sans aucun balisage. Ce que l’utilisateur saisit est affiché tel quel à l’écran, sans aucune interprétation d’aucune sorte. C’est habituellement le format utilisé pour les champs texte sur une seule ligne.
Lorsque vous affichez du plain-text, vous devez le passer par check_plain() avant de l’inclure dans du HTML. Cela convertit les guillemets, les esperluettes et les crochets en entités HTML, ce qui fait que la chaîne est affichée littéralement dans le navigateur.
Beaucoup d’API et de fonctions « thémables » prennent du HTML en argument et il y en a quelques-unes qui assainissent automatiquement le texte en le passant à check_plain() :
<?php
$form['safe'] = array(
'#type' => 'textfield',
'#default_value' => $u_supplied,
);
$form['also_safe'] = array(
'#type' => 'select',
'#default_value' => 0,
'#options' => node_get_types('names'), // Could contain unsafe values but FAPI will pass through check_plain() before displaying to user.
);
?>Certains emplacements exigent que tout texte soit préalablement assaini :
<?php
drupal_set_title($node->title); // XSS vulnerability, bad
drupal_set_title(check_plain($node->title)); // Correct
?><?php
Drupal 5:
watchdog('content', t("Deleted !title", array('!title' => $node->title))); // XSS
watchdog('content', t("Deleted %title", array('%title' => $node->title))); // or @
Drupal 6 (The message and variables are passed through t() by the watchdog function):
watchdog('content', "Deleted !title", array('!title' => $node->title)); // XSS
watchdog('content', "Deleted %title", array('%title' => $node->title)); // or @
?><?php
$form['bad'] = array(
'#type' => 'textfield',
'#default_value' => check_plain($u_supplied), // bad: escaped twice
'#description' => t("Old data: !data", array('!data' => $u_supplied)), // XSS
);
$form['good'] = array(
'#type' => 'textfield',
'#default_value' => $u_supplied,
'#description' => t("Old data: @data", array('@data' => $u_supplied)),
);
?><?php
$form['bad'] = array(
'#type' => 'checkboxes',
'#options' => array($u_supplied0, $u_supplied1),
);
$form['good'] = array(
'#type' => 'checkboxes',
'#options' => array(check_plain($u_supplied0), check_plain($u_supplied1)),
);
?><?php
$form['unsafe'] = array('#value' => $user->name); //XSS
$form['safe'] = array('#value' => check_plain($user->name));
or
$form['safe'] = array('#value' => theme('username', $user));
?>2. Rich Text
Le Rich Text contient des balises HTML, Textile ou autres. Il est enregistré dans le format propre aux balises et converti en HTML lors de l’affichage grâce aux différents filtres activés. C’est le format généralement utilisé pour du texte multi-ligne.
Tout ce que vous avez à faire et de passer le rich text à check_markup() pour obtenir du HTML en retour, sûr pour l’affichage. Vous pouvez aussi permettre à l’utilisateur le choix du format de saisie, avec un widget de format via filter_form() et passer le format choisi à check_markup().
Vous devez vous assurer que l’auteur d’un message est autorisé à utiliser un format de saisie spécifique. Par sécurité, check_markup() effectué cette vérification pour l’utilisateur en cours par défaut. Toutefois, comme le contenu est filtré à l’affichage, ce n’est pas toujours la personnes à l’origine du contenu. Dans ce cas, vous devez désactiver cette vérification en passant $check = false à check_markup(), et en vous assurant que le format est contrôlé avec filter_access() lorsque le contenu est soumis.
3. Admin-only HTML
Depuis Drupal 4.7, il y a une troisième façon de traiter le texte. Il y a des parties de la section administration où l’on ne peut pas appeler le filtre système (pour le rich text) mais où des balises simples sont souhaitées, telles que des liens ou des italiques (donc le plain text n’est pas utilisable).
Ce peut-être le cas dans l’objectif du site, les règles d’utilisation et les descriptions de forums.
Pour ces cas-là, vous pouvez utiliser une zone de texte normale et passer le texte dans la fonction filter_xss_admin() pour l’affichage. Cela autorisera la plupart des balises HTML, tandis que cela bloquera les scripts ou les styles potentiellement nuisisbles.
Les URL dans Drupal doivent être manipulées de façon spéciale dans deux cas :
Notez que toutes les fonction Drupal qui retournent des URL (url(), request_uri(), etc) affichent du texte seul, qui n’a pas été échappé du tout. Pour les échapper avant un affichage HTML (ou XML), utilisez check_url(). Mais ne l’utilisez pas dans les cas où une véritable URL est attendue, comme dans le header Location : ….
Toutes les règles ci-dessus peuvent se résumer à ceci : rien de ce qu’un utilisateur soumet comme contenu ne doit être restitué tel quel dans le code HTML. Si vous n’êtes pas sûr, vous pouvez le tester en soumettant un bout de texte comme <u>xss</u> dans les champs de votre module. Si le texte est restitué souligné ou mutile les balises existantes, vous savez que vous avez un problème.
Voici des exemples de code corrects et incorrects. $title, $body et $url sont censés être des saisies utilisateurs contenant respectivement un titre, un bout de texte balisé et une URL. Elles sont issues de la base de données et contiennent ainsi exactement ce que l’utilisateur a soumis, sans modifications.
Incorrect :
<?php print '<tr><td>$title</td><td>'; ?>
<?php print '<a href="/..." title="$title">view node</a>';?>
Correct (le titre est du texte seul et ne doit pas être placé tel quel dans le code HTML):
<?php print '<tr><td>'. check_plain($title) .'</td></tr>'; ?>
<?php print '<a href="/..." title="'. check_plain($title) .'">view node</a>'; ?>
Incorrect :
<?php print l(check_plain($title), 'node/'. $nid); ?>
Correct (l() appelle déjà check_plain() par défaut ):
<?php print l($title, 'node/'. $nid); ?>
Incorrect :
<?php print '<a href="/$url">'; ?>
<?php print '<a href="/'. check_plain($url) .'">'; ?>
Correct (les URL doivent être vérifiées avec check_url()):
<?php print '<a href="/'. check_url($url) .'">'; ?>
Lorsque vous écrivez des filtres qui convertissent un langage de balises en code HTML, vous devez veillez à ne pas créer vous-même des failles de sécurité. D’une manière générale on applique les mêmes règles : vérifiez les URL avec check_url() et veillez à ce qu’aucun code HTML littéral puisse être injecté en l’échappant correctement avec check_plain().
Référence sur Drupal.org : 15 Février 2007 – 12h20 - http://drupal.org/node/119326
(Cette partie est en cours d’écriture sur Drupal.org)
Quelques règles générales :
Référence sur drupal.org : 25 Janvier 2007 – 10:58 - http://drupal.org/node/101499
Les sessions PHP permettent de conserver des données durant la visite d’un utilisateur. Lorsqu’un internaute accède à votre site, un identifiant unique lui est assigné, l’ID de session. Côté internaute, cet ID est stocké dans un cookie et est envoyé à votre site à chaque requête de page.
Drupal enregistre les ID Utilisateurs dans la base de données. A chaque accès à une page, Drupal reçoit l’ID de session envoyé par la navigateur de l’internaute. Il cherche alors l’ID dans la table session pour trouver l’internaute associé. Cet ID Utilisateur sert à établir les droits que l’internaute a sur le site.
Pour conserver la sécurité de ce système, il est impératif de garder l’ID de session confidentiel. Si vous écrivez une module, vous ne devrez jamais rendre ces ID publics. Ils pourraient être lus par des utilisateurs et permettre le détournement des sessions.
Faites attention au fait que, même si votre sortie n’est pas affichée, si elle fait partie d’une requête AJAX par exemple, elle peut néanmoins être vue si l’utilisateur utilise un sniffer comme WireShark ou Fiddler.
Référence sur Drupal.org : 15 Mai 2009 – 15h51 - http://drupal.org/node/93737
db_rewrite_sql() fournit aux modules une méthode pour compléter vos requêtes SQL. Par exemple, un module qui contrôle l’accès aux nodes devra restreindre le resultat de vos requêtes, en enlevant tous les nodes pour lesquels l’utilisateur n’a pas les droits d’accès.
Si vous n’utilisez pas db_rewrite_sql(), les contrôles d’accès des modules ne pourront pas modifier ou compléter vos requêtes SQL, et vous pourriez révéler sans le vouloir du contenu confidentiel.
C’est une bonne habitude de toujours utiliser db_rewrite_sql()
Quelques exceptions à cette règle :
Référence sur drupal.org : 23 Février 2009 – 03h46 - http://drupal.org/node/263002
Une approche répandue dans d’autres applications web est de traiter ou filtrer les saisies utilisateurs pour des raisons de sécurité. Historiquement, Drupal préservait les saisies telles quelles et ne les filtraient qu’en sortie. Le sujet est débattu de temps à autre dans la communauté Drupal.
L’excellent article Safe string theory for the web de Steven Witten apporte une explication technique sur les raisons de filtrer selon les différents contextes des sorties.
Désormais, nous voyons que filtrer la saisie est problématique car nous ne pouvons connaître les caractères interdits sans connaître le contexte dans lequel ils apparaîtront.
Pour compliquer les choses, une chaîne donnée peut apparaître dans plus d’un contexte, par exemple en tant que texte HTML et aussi en tant qu’attribut comme dans <a title="$node->title">$node->title</a>. Donc si vous voulez filtrer tous les caractères, votre système sera paralysé parce que vous aurez besoin de filtrer trop de caractères, si vous voulez encoder, vous ne pouvez savoir comment encoder. L’encodage présente une autre problème, traiter du texte échappé est très malaisé (essayez d’extraire le teaser du corps d’un node HTML échappé).
Il n’y a pas d’autre alternative que d’enregistrer les saisies utilisateur sans modifications et d’appliquer les filtrages et les traitements appropriés lors des sorties.
Référence sur Drupal.org : 2 Juin 2009 – 03h47 - http://drupal.org/node/218104
Il y a une discussion pour déplacer cette fonctionnalité dans le core, pour que les développeurs puissent le faire sans risques : #287292: Add function to switch local user
Il y a plusieurs cas pour lesquels vous voudrez que votre code « usurpe » l’identité d’un autre utilisateur. C’est le cas lorsqu’une action d’utilisateur déclenche un autre processus. Si c’est autre processus doit être fait par un utilisateur différent, alors vous voudrez « usurper » l’identité de cet autre utilisateur.
Voici un exemple de code incorrect et risqué qui « usurpe » l’identité d’un autre utilisateur :
<?php
global $user;
$original_user = $user;
$user = user_load(array('uid' => 1));
// Take your action here where you pretend to be the user with UID = 1 (typically the admin user on a site)
// NOTE: - this is the unsafe part - if your code here fails, then the user suddenly has the permissions of UID 1!
$user = $original_user;
?>Le mode opératoire correct et sûr consiste à utiliser la fonction session_save_session() comme ci-dessous :
<?php
global $user;
$original_user = $user;
session_save_session(FALSE);
$user = user_load(array('uid' => 1));
// Take your action here where you pretend to be the user with UID = 1 (typically the admin user on a site)
// If your code fails, it's not a problem because the session will not be saved
$user = $original_user;
session_save_session(TRUE);
// From here on the $user is back to normal so it's OK for the session to be saved
?>
Référence sur Drupal.org : 19 Février 2008 – 03h55 - http://drupal.org/node/218037
Chaque fois qu’elle en à l’occasion, l’équipe Drupal Sécurité essaie de partager les informations sur ses méthodes et sur la façon d’écrire du code sécurisé dans Drupal . La présentation en pièce jointe a été réalisée lors de la DrupalCon de Barcelone en 2008.
Cette présentation traite de la sécurité à partir de « Why bother » puis examine comment les failles de sécurité sont souvent présentes, de quels types de faille il s’agit, lesquelles sont les plus courantes et comment résoudre la plupart des problèmes par l’utilisation correcte des API Drupal.
Référence en anglais : 28 Avril 2009 - 20h17 - http://drupal.org/node/447604
Important : cet article est en cours de rédaction. Une discussion a lieu sur http://groups.drupal.org/node/14523.
La seule norme actuelle concernant le code contribué est de placer un fichier README.txt dans le paquetage (package). La documentation supplémentaire peut être placée dans un fichier INSTALL.txt.
Quelques README.txt sympas sont disponibles ici:
Référence en anglais : 17 Janvier 2009 - 00h33 - http://drupal.org/node/287350
Cette page expose brièvement nos meilleures pratiques pour programmer avec Drupal. Cela concerne autant des questions de haut niveau que celles abordées dans les pages Normes de programmation et Configuration & Usage Best Practices.
Le but de ces pages n'est pas de vous apprendre à programmer mais de de vous apprendre à devenir un meilleur programmeur dans le framework Drupal.
Tout le monde peut écrire du code, mais peu savent qu'il y a une façon de faire avec Drupal. Pourquoi la vitesse et les performances sont-elles si importantes ? Pourquoi documenter le code-source ? Pourquoi ce bout de code si utilisé est-il mauvais ? Nous répondons ici à ces questions, et à plein d'autres encore, et nous expliquons pourquoi.
Référence en anglais : 10 octobre 2008 - 17h17 -
Connaître l'API de Drupal n'est pas une tâche titanesque. La consulter chaque fois que vous pensez en avoir besoin est fortement conseillé. N'essayez pas de résoudre à tout prix les différentes questions de programmation par du codage brut. Au lieu de cela, chaque fois que vous pensez écrire plus de fonctions qu'il n'y en a besoin, arrêtez-vous et consultez la documentation de l'API pour voir s'il n'y a pas une façon de contourner votre problème. Si vous travaillez avec des modules contributifs, parcourir l'index des modules contributifs peut aider.
Admettez-le. Vous êtes intelligent mais il y a de bonnes chances que quelqu'un d'autre, quelque part, ait déjà essayé de faire ce que vous faites; et l'ait écrit dans une API. Vous pouvez avoir besoin d'une simple fonction, ou d'une série de fonctions, mais puisque l'un des buts d'une bonne programmation est la robustesse d'un code, utilisez l'API chaque fois que vous en aurez l'occasion.
Référence en anglais sur drupal.org :27 Mai 2009 - 02h13 - http://drupal.org/node/299070
Choisir un nom adéquat pour vos fonctions est très important. Mais vous devriez apporter le même soin aux noms des variables. N'utilisez pas simplement $i et $j à tout bout de champ. Le nom de la variable doit clairement faire allusion à ce qu'elle contient. Si possible, regardez dans le core pour avoir un exemple des conventions de nommage des variables et utilisez les mêmes conventions dans votre code-source.
Faites également attention aux mots réservés, leur utilisation à mauvais escient vous mènera à des problèmes insoupçonnables et impossibles à débogguer.
Faites attention aux singuliers et aux pluriels pour le nom des scalaires et des tableaux, vous pouvez éviter des erreurs de programmation en adoptant une « écriture grammaticale » cohérente.
Vous pouvez aussi utiliser une classe plutôt que des variables globales. Vous pouvez ainsi nommer les variables sans avoir besoin de les préfixer avec le nom du module puisqu'il est contenu dans l'objet. Utilisez les fonctions magiques _set, _get et _toString pour contrôler les paramètres des variables via un tableau privé.
Référence en anglais sur drupal.org : 9 Janvier 2009 - 10h00 - http://drupal.org/node/299074
Si l'implémentation d'une fonction ne tient pas sur un écran de votre éditeur, c'est probablement qu'elle essaie de faire trop de choses. Elle devrait être divisée en fonctions plus petites.
Référence en anglais sur drupal.org : 23 Août 2008 - 17h24 - http://drupal.org/node/299085
Drupal est disponible dans tous les pays du monde, et bien qu'il soit programmé en anglais, les chaînes de texte qu'il affiche sont traduites dans presque toutes les langues que vous pouvez envisager. La fonction t() est obligatoire pour toutes les chaînes de caractères qui seront lues par un utilisateur ou un administrateur, et c'est la seule façon qu'a le core pour traduire les chaînes en quelque chose de lisible par les lecteurs.
t() est non seulement indispensable pour la localisation, mais dispose de fonctionnalités de sécurité importantes que chaque développeur Drupal devrait connaître et comprendre. Il est plus simple d'intégrer les textes dès le départ dans une fonction t() que de revenir dans le code ultérieurement pour le faire si vous (ou quelqu'un d'autre) décidez d'utiliser une autre langue.
Référence en anglais sur drupal.org : 23 Août 2008 - 16h57 - http://drupal.org/node/299067
Quand vous écrivez du code-source, placez-le dès que possible dans un système de contrôle de version et committez-le au fur et à mesure, avec des messages explicites sur ce que vous changez et pourquoi. N'attendez pas d'avoir votre release 1.0 pour tout committer d'un coup - le but d'un contrôle de version est de maintenir un historique de vos changements, de vos décisions et de leurs raisons.
Faîtes-en usage dès le début de votre projet. Ainsi, lorsque vous aurez besoin, des mois plus tard, de débogguer, modifier ou améliorer quelque chose, vous serez content de pouvoir comprendre ce que vous aviez fait initialement et les raisons pour lesquelles vous l'aviez fait.
Voir la conception initiale de votre code-source peut également aider d'autres personnes, qui voudront l'étendre, l'améliorer ou le débogguer.
Enfin, cela vous servira également de sauvegarde hors-site pour votre travail. Votre portable peut être volé ou exploser en plein vol, vos supers-idées seront toujours à l'abri dans le dépôt. N'oubliez pas que si un code-source n'existe pas en différents endroits, il n'existe pas du tout.
Référence du document en anglais sur drupal.org : 4 Mai 2009 - 08h19 - http://drupal.org/node/328206 - Incomplet
Dans le monde des programmeurs il y a une course. Une course pour savoir qui écrira le code qui s'exécutera le plus vite possible. Pas seulement le code le plus rapide, mais le code le plus utile. Et si vous êtes programmeur, qui est votre adversaire ? Vous bien sûr !
En tant que programmeurs, nous cherchons non seulement à écrire un code qui fasse quelque chose, mais aussi à ce qu'il le fasse bien. Nous parlons de ce «bien» en tant qu'efficacité. L'efficacité s'entend comme vitesse, économie de moyens et objectifs. Les trois doivent évoluer en harmonie. Et dans le cas de Drupal, la vitesse est très importante car nous ne voulons pas faire attendre l'utilisateur ou déclencher un timeout du serveur. Les objectifs sont également importants car Drupal n'est rien s'il ne peut rien proposer d'utile à son public.
Il y a une façon à considérer: celle d'un produit concret. Supposons que vous possédez une entreprise qui fabrique un produit B. Votre entreprise, comme toute entreprise qui fabrique des produits, est remise en question : produisez-vous beaucoup de produits B vraiment rapidement, ou votre produit B est-il très utile.
Dans un monde sans frontières nous devrons faire le maximum possible. Malheureusement, la fabrication du produit B ne tient pas compte des deux idées en même temps, d'où une limite. L'entreprise devra alors dépenser du temps et des efforts pour trouver le point d'équilibre. Un point d'équilibre dont nous connaissons les éléments : prix des éléments, travail, valeur et autres facteurs. Ainsi, une fois ces questions réglées, l'entreprise adapte ses méthodes de fabrication pour produire le plus de produits B tout en améliorant sa qualité.
Le parallèle avec le monde de la programmation est là (Ah. Je me disais aussi. NdT). Vous programmez pour atteindre un objectif (l'objectif est le produit B). Vous pouvez aussi programmer pour apporter une incroyable vitesse et d'aussi incroyables objectifs (et nous supposons que la qualité fait partie des objectifs).
Cependant, étant donné les limites des technologies modernes, vous ne pouvez obtenir les deux à la fois. Vous devez donc trouver votre point d'équilibre car vous ne pouvez obtenir les deux : la vitesse seule n'est rien s'il n'y a pas quelque chose à proposer, et proposer quelque chose ne doit pas prendre des plombes. Ceci - trouver le point d'équilibre - est ce que les pages suivantes de ce chapitre traiteront.
Les sujets présentés ici se rapportent à des problèmes simples à comprendre, qui seront également décrits. Ces sujets et problèmes incluent, entre autres, l'efficacité de la recursivité, le travail avec un ensemble de données sans rapport. En programmation, les problèmes peuvent facilement se résumer en une simple question, pourtant la plus simple des questions peut parfois demander des tonnes de réflexion pour être résolue.
Si vous avez un sujet relative à l'efficacité que vous voudriez voir ici (sur drupal.org ! NdT) n'hésitez pas à publier un commentaire sur cette page, d'aller en parler sur IRC, ou même d'ajouter cette page vous-même, si vous vous sentez au point sur le sujet.
(Ah oui, ça valait le coup de traduire ça. Vivement la suite. NdT)