Mise en place

Structure de fichiers

Si le code de l’extension est suffisamment court pour tenir dans un seul fichier PHP il suffira de placer ce fichier, du nom approprié et contenant une en-tête de description (voir plus loin), dans les répertoires des plugins, habituellement « wp-content/plugins  » depuis la racine de WordPress.

Au contraire s’il nécessite plusieurs fichiers il faudra créer là un répertoire de nom original et placer dans celui-ci les fichiers nécessaires dont un (PHP) contiendra l’en-tête, on l’appellera le fichier principal de l’extension. Généralement ce fichier porte le même nom que le répertoire, mais ce n’est pas une obligation.

Dans le cas où l’on crée un répertoire pour plusieurs fichiers, il est utile d’y placer un fichier index.php « vide », typiquement contenant:

<?php
// 

Ainsi un visiteur tentant d’atteindre ce répertoire n’y trouvera rien.

 

En-tête

Le fichier principal (d’initialisation), éventuellement le seul fichier de l’extension doit débuter ainsi :

<?php
/*
Plugin Name: Ma superbe extension
Plugin URI: https://codex.wordpress.org/Writing_a_Plugin
Description: Une extension qui fait tout !
Version: 1.0.0
Author: Moi-même
Author URI: https://wp.bourbre.org/
License: GPL2
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: wporg
Domain Path: /languages
*/

En fait, seule la ligne « Plugin Name » est obligatoire, car c’est par elle que WordPress identifiera l’extension.

Toutefois, « Description » et « Version » sont utiles car leur contenu apparaitra dans la liste des extensions enregistrées. le reste est nécessaire si l’extension doit être publiée.

En savoir plus :
https://developer.wordpress.org/plugins/the-basics/header-requirements/

On utilise indifféremment les mots “extension” ou “plugin”. Ils ont la même signification.

Dans l’action

Beaucoup d’extensions (ou plugins) changent le comportement de WordPress, soit en ajoutant des actions soit en modifiant des contenus.

Dans le premier cas il s’agit de « crochets » (hooks) qui sont exécutés à certains moment de l’exécution de WordPress. On utilise généralement le fonction WordPress « add-action » pour définir le moment de l’action et les instructions à exécuter.

Dans le second cas ce sont des « filtres » (filters), ils reçoivent une information et la renvoient modifiée. Il sont mis en place par la fonction « add_filter » qui permet de définir l’emplacement du filtre et son action.

En savoir plus (partiellement en français) :
https://codex.wordpress.org/fr:Plugin_API

Le plus simple des plugins (ou extensions)

Voici un plugin qui ne fait rien de visible.

On place, à la suite de l’en-tête le code suivant :

defined( 'ABSPATH' ) OR exit;
function action_cachee() {
  //....
}
add_action('wp_loaded', 'action_cachee');

Ce fichier, étant le fichier principal, est lancé, si le plugin est activé à chaque ouverture de page WordPress.

Tout d’abord, après l’en-tête est ajoutée la ligne

defined( 'ABSPATH' ) OR exit;

Afin d’empêcher quelqu’un, qui aurait connaissance de ce fichier, d’accéder à son contenu.

Le corps du plugin accroche la fonction « action_cachee » au moment « wp_loaded  », soit au chargement de WordPress. Cette fonction s’exécutera à chaque chargement de page, par exemple pour enregistrer les accès.

On verra par la suite que l’on peut faire plus compliqué.

Remarque importante si le plugin est composé de plusieurs fichiers

Il ne faut pas oublier que les fichiers de programme ne s’exécutent pas dans le contexte du répertoire où ils sont placés. Par conséquent si, depuis un fichier, on doit inclure le fichier « toto.php », du même répertoire, on doit utiliser :

include dirname( __FILE__ ) . “/toto.php“;

ou la fonction spécifique :

include_once plugin_dir_path( __FILE__ ).’/toto.php‘;

(voir : https://codex.wordpress.org/Determining_Plugin_and_Content_Directories)

Fonctions « publiques »

Les fonctions qui sont déclarées dans le plugin sont accessibles à l’ensemble de WordPress une fois le plugin activé. En effet, le code du plugin est dans une fonction WordPress et en PHP les fonctions déclarées à l’intérieur d’une autre fonction sont accessibles dès que la fonction englobante à été appelée.

Cela présente un avantage et un inconvénient, commençons par l’avantage.

On peut déclarer des fonctions dans le corps du plugin qui seront accessibles par l’ensemble de WordPress, par exemple dans d’autres plugins ou thèmes. Pour ceux-là il est judicieux de s’assurer que le plugin est bien actif, donc que la fonction est utilisable ainsi :

if ( function_exists ('ma_superbe_fonction' ) ) {
   ... ma_superbe_fonction(...) ...
}

Si une extension utilise des fonctions d’une autre extension, il faut être très prudent car on ne connais pas à priori l’ordre d’activation des extensions. Par conséquent une extension ne devrait pas utiliser au cours de son activation une fonction d’une autre extension. En revanche, cela ne posera pas de problème si l’appel se fait après l’activation (par un « hook »).

Et voici l’inconvénient.

Il faut être très prudent dans le nom à donner aux fonctions afin de ne pas redéclarer d’éventuelles fonctions existantes (ou à venir). Si l’on en a plusieurs à définir, il peut être préférable de déclarer une classe où ces fonctions en seront les méthodes où de définir un espace de noms.

 

Précautions

Si le plugin utilise des particularités de PHP ou de WordPress qui ne sont disponibles que dans les versions récentes, il est utile de tester, en regard, les version actuelles et d’activer l’extension que si ces conditions sont validées, sinon produire un message d’erreur.

On sait que l’identification la version de PHP est produite par la fonction PHP « phpversion() », la version active de WordPress se trouve dans la variable « $wp_version » et que la fonction PHP « version_compare » sert à la comparaison des versions.

On utilise donc cette fonction au début du fichier principal afin de vérifier les versions lors de l’activation de l’extension. Si le test échoue, on produit un message d’erreur et surtout ou exécute un « return » qui ne poursuivra donc pas l’activation de l’extension.

Voici un exemple d’utilisation :

define('VERSION_PHP_REQUISE', '5.4');
define('VERSION_WP_REQUISE', '4.7');

function ce_plugin_erreur_versionPHP() {
 ?>
<div style="
 margin: 10px; padding: 10px;
 background: #f88; color: #000; font-size: 24px; font-weight: bold; text-align: center;
 ">
 La version PHP du serveur est insuffisante, il faudrait la version <?= VERSION_PHP_REQUISE ?>.
</div>
 <?php
}
function ce_plugin_erreur_versionWP() {
 ?>
<div style="
 margin: 10px; padding: 10px;
 background: #f88; color: #000; font-size: 24px; font-weight: bold; text-align: center;
 ">
 La version WordPress du serveur est insuffisante, il faudrait la version <?= VERSION_WP_REQUISE ?>.
</div>
 <?php
}
if ( version_compare( phpversion(), VERSION_PHP_REQUISE ) < 0) {
 add_action( 'admin_notices', 'ce_plugin_erreur_versionPHP');
 return;
}
global $wp_version;
if ( version_compare( $wp_version, VERSION_WP_REQUISE ) < 0) {
 add_action( 'admin_notices', 'ce_plugin_erreur_versionWP');
 return;
}

Mis à par les deux définitions de versions requises, on a créé deux fonctions d’erreur qui se ressemblent beaucoup : « ce_plugin_erreur_versionPHP » et« ce_plugin_erreur_versionWP ».

Ensuite on teste les versions et, en cas d’échec, on appelle ces fonctions par«  add_action( ‘admin_notices’, ‘fonction_erreur‘) » puis « return » afin de ne pas aller plus loin.

ATTENTION : tout ce code est exécuté par une fonction de WordPress, donc pour accéder à la variable globale « $wp_version » il faut la définir ainsi ou utiliser « $GLOBALS['wp_version'] ».