Respecter les WordPress Coding Standards

Les « coding standards » sont des normes à respecter pour écrire le code d’une application. WordPress possède ses propres normes : les WordPress Coding Standards (WPCS). Elles concernent PHP, CSS, Javascript et l’accessibilité. Nous allons voir comment configurer nos outils pour pouvoir les respecter.

Présentation des WPCS

Coding standards : qu’est-ce que c’est ?

Les règles de codage (« coding standards » ou « coding conventions » en anglais) sont un ensemble de règles à respecter lorsque l’on écrit du code. Elles s’appliquent à tout type de code (un logiciel, un site web, une application mobile, etc.), mais elles peuvent être différentes d’un langage à l’autre et d’un logiciel à l’autre. Les « coding standards » permettent d’uniformiser le code d’un logiciel, d’améliorer la lisibilité et, par conséquent, la maintenabilité du code, de promouvoir les bonnes pratiques et d’éviter certaines erreurs.

Exemple de non respect des WordPress Coding Standards dans VSCode

Les standards de WordPress

WordPress dispose de ses propres règles ; elles se nomment WordPress Coding Standards (ou WPCS de manière abrégée). Elles concernent PHP, HTML, CSS, Javascript et l’accessibilité. Vous pouvez retrouver l’ensemble des règles dans le Coding Standards Handbook de WordPress. Je ne vais pas vous citer toutes ces règles, mais voici quelques exemples.

Parmi les règles concernant PHP, il faut notamment :

  • utiliser des tabulations et non des espaces pour l’indentation,
  • prioriser l’utilisation des quotes simples,
  • déclarer un item par ligne si l’array comporte plus qu’un item,
  • mettre un espace après la parenthèse ouvrante et un autre avant la parenthèse fermante.

Parmi les règles concernant HTML, il faut notamment :

  • utiliser un espace avant le slash de fermeture des balises auto-fermantes,
  • indenter avec des tabulations plutôt que des espaces,
  • écrire les attributs en minuscule et encadrer les valeurs de double ou simple quotes.

Parmi les règles concernant CSS, il faut notamment :

  • utiliser des tabulations pour indenter,
  • déclarer les sélecteurs et propriétés sur plusieurs lignes,
  • écrire les sélecteurs en lettres minuscules et séparer les mots par des traits d’union.

Parmi les règles concernant Javascript, il faut notamment :

  • utiliser la syntaxe camelCase pour les variables et fonctions,
  • indenter avec des tabulations,
  • mettre un espace après la parenthèse ouvrante et un autre avant la parenthèse fermante.

Comment respecter les WordPress Coding Standards ?

Évidemment, il est possible de respecter ces standards directement sans outil. Toutefois, l’erreur est humaine ; je préfère donc utiliser des outils pour simplifier le respect de ces règles.

Ici, je vais vous présenter ma façon de faire pour respecter les WordPress Coding Standards. Toutefois, cette méthode n’engage que moi et ce n’est peut-être pas la façon de faire des personnes s’occupant de WordPress. Certains réglages peuvent ne pas correspondre avec leur manière de faire. Par ailleurs, ces règles s’appliquent à la conception de thèmes et plugins WordPress ; si vous travaillez sur le « core » de WordPress, il y a des règles spécifiques à respecter.

Configuration de l’IDE

Pour commencer, je place un fichier générique .editorconfig qui contient des directives qui pourront être appliquées quelque soit l’IDE utilisé.

root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = tab
indent_size = 4
tab_width = 4

[*.css]
indent_size = 2
tab_width = 2

[{*.json,*.yml}]
indent_style = space
indent_size = 2

[*.md]
trim_trailing_whitespace = false

[{*.txt,wp-config-sample.php}]
end_of_line = crlf

J’ai également un dossier .vscode, puisque j’utilise VS Code, contenant la configuration à appliquer à l’espace de travail. Le fichier settings.json contient des configurations propres à l’éditeur, mais également aux extensions que j’utilise comme PHPCS et Prettier. Voici son contenu :

{
	// Editor Settings
	"editor.insertSpaces": false,
	"editor.formatOnSave": true,
	"editor.formatOnPaste": false,
	// PHP Coding Standards Settings
	"phpcs.enable": true,
	"phpcs.standard": "WordPress",
	"phpcs.ignorePatterns": ["*/htdocs/wp/*"],
	// Prettier Settings
	"prettier.arrowParens": "avoid",
	"prettier.bracketSpacing": true,
	"prettier.endOfLine": "lf",
	"prettier.htmlWhitespaceSensitivity": "css",
	"prettier.insertPragma": false,
	"prettier.jsxBracketSameLine": false,
	"prettier.jsxSingleQuote": true,
	"prettier.printWidth": 80,
	"prettier.proseWrap": "preserve",
	"prettier.quoteProps": "as-needed",
	"prettier.requirePragma": false,
	"prettier.semi": true,
	"prettier.singleQuote": true,
	"prettier.tabWidth": 4,
	"prettier.trailingComma": "es5",
	"prettier.useTabs": true,
	"prettier.vueIndentScriptAndStyle": true,
	// CSS
	"[css]": {
		"editor.formatOnSave": true
	},
	// PHP
	"[php]": {
		"editor.detectIndentation": true,
		"editor.useTabStops": true,
		"editor.formatOnSave": false,
		"editor.insertSpaces": false
	},
	// Javascript
	"[javascript]": {
		"editor.insertSpaces": true,
		"editor.detectIndentation": false,
		"editor.useTabStops": false
	},
	// Json
	"[json]": {
		"editor.formatOnSave": false
	},
	// XML
	"[xml]": {
		"editor.formatOnSave": false
	}
}

La ligne phpcs.ignorePatterns permet d’indiquer à PHPCS d’ignorer ce chemin. Vous devez évidemment l’adapter à votre projet. Ici, je lui demande d’ignorer le dossier contenant le « core » de WordPress puisque mon dossier wp-content est défini ailleurs.

Configuration des extensions

Prettier

À la racine du projet, je place également un fichier .prettierrc contenant les directives pour l’extension Prettier. Il s’agit d’un formateur de code assez répandu donc quelque soit votre IDE vous devriez trouver une extension pour l’utiliser.

{
	"printWidth": 80,
	"tabWidth": 4,
	"useTabs": true,
	"semi": true,
	"singleQuote": true,
	"quoteProps": "as-needed",
	"jsxSingleQuote": true,
	"trailingComma": "es5",
	"bracketSpacing": true,
	"jsxBracketSameLine": false,
	"arrowParens": "avoid",
	"requirePragma": false,
	"insertPragma": false,
	"proseWrap": "preserve",
	"htmlWhitespaceSensitivity": "css",
	"vueIndentScriptAndStyle": true,
	"endOfLine": "lf",
	"overrides": [
		{
			"files": "*.yml",
			"options": {
				"tabWidth": 2,
				"useTabs": false
			}
		},
		{
			"files": ["*.txt"],
			"options": {
				"endOfLine": "crlf"
			}
		}
	]
}

PHPCS

PHP Code Sniffer (PHPCS) est un outil pour vérifier la conformité du code. Pour lui indiquer des directives, en plus de définir WordPress comme standard dans les réglages de l’extension, j’utilise un fichier phpcs.xml.dist :

<?xml version="1.0"?>
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="WordPress Coding Standards">
	<description>A custom PHPCS Ruleset for WordPress Themes and Plugins</description>
	<!-- Check files in this directory and subdirectories. -->
	<file>.</file>
	<!-- Excluse some files -->
	<exclude-pattern>*/wp-config-sample.php</exclude-pattern>
	<exclude-pattern>*/wp-config.php</exclude-pattern>
	<exclude-pattern>./htdocs/index.php</exclude-pattern>
	<!-- Exclude some directories. -->
	<exclude-pattern>*/wp/*</exclude-pattern>
	<exclude-pattern>*/vendor/*</exclude-pattern>
	<exclude-pattern>*/node_modules/*</exclude-pattern>
	<!-- Pass flags to PHPCS:
		 p: Show progress of the run.
		 s: Show sniff codes in all reports.
		 v: Print verbose output.
	-->
	<arg value="psv"/>
	<!-- Strip the filepaths down to the relevant bit. Disabled, bug with VSCode. -->
	<!-- <arg name="basepath" value="./"/> -->
	<!-- Only check PHP files. -->
	<arg name="extensions" value="php,css,scss/css"/>
	<!-- Use the WordPress ruleset -->
	<rule ref="WordPress" />
	<!-- Allow theme-specific exceptions to WordPress filename rules. -->
	<rule ref="WordPress.Files.FileName">
		<properties>
			<property name="is_theme" value="true"/>
		</properties>
	</rule>
	<!-- Verify that no WP functions are used which are deprecated or removed. -->
	<rule ref="WordPress.WP.DeprecatedFunctions">
		<properties>
			<property name="minimum_supported_version" value="4.5"/>
		</properties>
	</rule>
	<!-- Check all globals have the expected prefix. -->
	<rule ref="WordPress.NamingConventions.PrefixAllGlobals">
		<properties>
			<property name="prefixes" type="array" value="CHILD_THEME, CHILD_TEXT_DOMAIN"/>
		</properties>
	</rule>
	<rule ref="WordPress.Arrays.MultipleStatementAlignment">
		<properties>
			<!-- No need to adjust alignment of large arrays when the item with the largest key is removed. -->
			<property name="exact" value="false"/>
			<!-- Don't align multi-line items if ALL items in the array are multi-line. -->
			<property name="alignMultilineItems" value="!=100"/>
			<!-- Array assignment operator should always be on the same line as the array key. -->
			<property name="ignoreNewlines" value="false"/>
		</properties>
	</rule>
	<rule ref="WordPress.WhiteSpace.ControlStructureSpacing">
		<properties>
			<property name="blank_line_check" value="true"/>
		</properties>
	</rule>
	<!-- Enforce PSR1 compatible namespaces. -->
	<rule ref="PSR1.Classes.ClassDeclaration"/>
	<rule ref="PSR2.Methods.FunctionClosingBrace"/>
	<!-- Check code for cross-version PHP compatibility. -->
	<config name="testVersion" value="5.4-"/>
	<rule ref="PHPCompatibility">
		<!-- Exclude PHP constants back-filled by PHPCS. -->
		<exclude name="PHPCompatibility.Constants.NewConstants.t_finallyFound"/>
		<exclude name="PHPCompatibility.Constants.NewConstants.t_yieldFound"/>
		<exclude name="PHPCompatibility.Constants.NewConstants.t_ellipsisFound"/>
		<exclude name="PHPCompatibility.Constants.NewConstants.t_powFound"/>
		<exclude name="PHPCompatibility.Constants.NewConstants.t_pow_equalFound"/>
		<exclude name="PHPCompatibility.Constants.NewConstants.t_spaceshipFound"/>
		<exclude name="PHPCompatibility.Constants.NewConstants.t_coalesceFound"/>
		<exclude name="PHPCompatibility.Constants.NewConstants.t_coalesce_equalFound"/>
		<exclude name="PHPCompatibility.Constants.NewConstants.t_yield_fromFound"/>
	</rule>
</ruleset>

Stylelint

J’utilise également l’extension Stylelint avec un fichier de configuration nommé stylelintrc.json :

{
	"extends": [
		"stylelint-config-wordpress",
		"stylelint-config-wordpress/scss"
	]
}

ESLint

Pour Javascript, j’utilise ESLint et deux fichiers de configurations. Le premier .eslintignore permet d’indiquer les dossiers et fichiers à ignorer. Le deuxième, .eslintrc.js, contient les directives pour l’extension.

module.exports = {
	env: {
		jest: true,
		node: true,
		es6: true
	},
	extends: [ "plugin:@wordpress/eslint-plugin/recommended" ]
};

Composer + PHP CodeSniffer + WPCS

J’utilise Composer pour installer PHPCS et les WordPress Coding Standards dans chacun des projets.

"require-dev": {
	"squizlabs/php_codesniffer": "^3.5",
	"wp-coding-standards/wpcs": "^2.2",
	"dealerdirect/phpcodesniffer-composer-installer": "^0.6.2",
	"phpcompatibility/phpcompatibility-wp": "*"
},
"scripts": {
	"wplint": "phpcs --standard=WordPress",
	"wpfix": "phpcbf --standard=WordPress"
}

Il y a 4 paquets nécessaires :

  • le premier, squizlabs/php_codesniffer, contient PHPCS
  • le second, wp-coding-standards/wpcs, contient les standards WordPress
  • le troisième, dealerdirect/phpcodesniffer-composer-installer, permet de configurer automatiquement les standards pour PHPCS
  • le dernier, phpcompatibility/phpcompatibility-wp, permet d’ajouter des règles à PHPCS pour vérifier les problèmes de compatibilité en fonction des versions de PHP

Je configure également 2 scripts pour utiliser PHPCS plus facilement. Le premier wplint permet de vérifier que le code correspond aux standards WordPress. Le deuxième wpfix permet de corriger automatiquement ces erreurs.

NPM + Prettier + ESLint + Stylelint

Grâce à npm, j’installe également les paquets nécessaires pour détecter les erreurs CSS (Stylelint) et Javascript (ESLint). Ces paquets viennent avec deux paquets spécifiques à WordPress contenant les différentes règles à appliquer. Si vous utilisez l’extension Prettier, il me semble que le paquet prettier est redondant donc celui-ci est optionnel.

"devDependencies": {
	"@wordpress/eslint-plugin": "^5.1.0",
	"eslint": "^6.0.0",
	"prettier": "^1.12.1",
	"stylelint": "^13.3.3",
	"stylelint-config-wordpress": "^16.0.0"
}

Faut-il corriger toutes les erreurs ?

J’utilise les WordPress Coding Standards depuis peu. En fait, je les utilise depuis que je mets mon code à disposition sur des sites comme Github ou Gitlab. Pour une question de maintenabilité, je trouve ça important de les respecter. Toutefois, comme vous pouvez le voir avec Minimalist, je ne pense pas respecter toutes les règles à la lettre.

Par exemple, j’utilise Sass et je n’ai pas encore cherché comment rassembler les media queries à la fin du document CSS. De même, les préfixes sont ajoutés au cours de la compilation et leur indentation ne correspond pas aux règles de WordPress. Même si je m’efforce de les respecter au mieux, il y a encore des imperfections.

Ceci dit, si vous regardez le code du « core » de WordPress, vous verrez qu’eux-mêmes ont parfois du mal à se tenir à leurs standards. J’irai même jusqu’à dire qu’il y a des incohérences… Pour CSS, les standards de WordPress disent d’utiliser uniquement les traits d’union pour les sélecteurs, mais les standards concernant Gutenberg autorisent les underscores. Ce genre d’exception peut vite devenir contraignant et difficile à automatiser sur de larges projets.

Enfin, si certaines erreurs n’en sont pas vraiment, les outils (comme phpcs et stylelint) possèdent des instructions pour ignorer une ligne ou un bloc de code. Si vous y avez recours, je vous conseille d’ajouter un commentaire pour que les autres sachent le pourquoi de cette instruction.

Le mot de la fin

Si vous avez suivi toutes les étapes, vous devriez avoir tous les fichiers / paquets nécessaires pour commencer à coder votre projet WordPress. Votre IDE vous informera des erreurs et vous pourrez alors les corriger soit manuellement soit automatiquement (stylelint et phpcs possèdent chacun un fixer). Vous pouvez retrouver l’ensemble des fichiers sur mon repo Github ou Gitlab.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.