Comment créer un plugin WordPress

Créer un plugin WordPress

Un plugin WordPress, pourquoi faire ?

Un plugin WordPress vous permettra d’ajouter des extensions à votre site. WordPress est un outil formidable, mais il ne possède pas toutes les fonctionnalités que vous pourriez désirer pour votre entreprise particulière. Il est donc la plupart du temps nécessaire d’ajouter des plugins à votre installation WordPress. Vous voulez pouvoir paramétrer des codes produits sur-mesure ? Vous voulez afficher une livraison express sur votre page produit ? Vous voulez ajouter la possibilité à vos clients de choisir un point relais ? Vous voulez que vos clients puissent paramétrer eux-mêmes leurs produits sur votre boutique ? Vous êtes blogueur et vous souhaitez diffuser votre article automatiquement sur tous vos réseaux sociaux dès qu’il est publié sur votre site ? Vous souhaitez ajouter une barre de recherche intelligente pour que vos clients retrouvent plus rapidement et facilement vos produits ? Toutes ces fonctionnalités ne sont pas dans le WordPress de base, il faudra donc soit acheter un plugin, soit en développer un par vous-même. Dans cet article, je vais vous expliquer comment développer un plugin WordPress en partant de zéro. Vous devez avoir un minimum de connaissance en Php, Html, Css & JavaScript. Cet article s’adresse à des développeurs web.

Comment fonctionne un plugin WordPress ?

En utilisant n’importe-quelle combinaison de PHP, HTML, CSS, JavaScript/jQuery ou tout autre langage de programmation Web, un plugin peut ajouter de nouvelles fonctionnalités à toute partie de votre site Web, y compris dans le tableau de bord. Les plugins vont vous permettre de personnaliser facilement votre site web et de l’adapter à tous les besoins de votre site web ou des sites web de vos clients.

Étant donné que les plugins WordPress sont autonomes, ils ne modifient pas physiquement le code principal WordPress. Ils peuvent ainsi être copiés et installés sur n’importe-quelle installation de WordPress. Un mode alternatif et que je déconseille fortement, consiste à écrire de nouvelles fonctions dans le fichier WordPress functions.php, qui est stocké dans le dossier /wp-includes/, ou encore dans le fichier functions.php qui fait partie du thème choisi. Cela pose un certain nombre de problèmes potentiels. A proscrire, donc.

En effet, WordPress et ses thèmes reçoivent des mises à jour régulières. Et à moins d’utiliser le thème enfant WordPress, lorsque functions.php est écrasé par une mise à jour, votre nouveau code sera supprimé et vous devrez l’écrire à nouveau. De surcroit, si vous écrivez beaucoup de fonctions et que l’une d’elles a une erreur que vous ne parvenez pas à déboguer, vous devrez peut-être remplacer l’intégralité du fichier par l’original, en supprimant toutes les modifications que vous avez effectuées. L’objectif du développement web étant de gagner, on voit que cette méthode n’est clairement pas adaptée !

A contrario, les plugins ne sont jamais automatiquement écrasés ou supprimés lors de l’installation des mises à jour WordPress. Si votre plugin a des erreurs de codage, vous pouvez généralement le désactiver dans le Panneau d’administration pour pouvoir le déboguer tranquillement. Si votre plugin a une erreur critique, WordPress va parfois le désactiver automatiquement pour vous, ce qui permettra à votre site de continuer à fonctionner.

Que sont les hooks ?

Les plugins WordPress interagissent avec le code de base en utilisant des hooks (crochets). Il existe deux types de hooks différents.

  1. Les actions (Pour ajouter/supprimer des fonctions) : par exemple, un développeur insère une fonction via une action, qui permet de partager un article sur facebook, au moment où l’article est enregistré
  2. Les filtres (Pour intercepter une valeur générée par une fonction WordPress afin de la modifier) : une extension intercepte la catégorie d’un article, afin d’en écrire une version enrichie, avec des synonymes, dans un but de référencement.

Les actions sont contextuelles – certaines sont appelées sur chaque page de votre site, d’autres uniquement lorsque vous visitez le panel d’administration. Une liste complète des actions et leur contexte est consultable sur la page de référence des actions pour les plugins WordPress.

Voyons un exemple de hook pour mieux comprendre :

<?php 
function remove_menu_pages() {
	remove_menu_page( 'tools.php' );

}
add_action( 'admin_menu', 'remove_menu_pages' );

J’indique à WordPress, qu’avant de générer le menu d’admin, je veux lancer ma propre fonction remove_menu_pages, afin d’ajouter ou supprimer des entrées dans ce menu. En effet, l’action « admin_menu » est appelée par WordPress au moment où ce dernier s’apprête à afficher menu d’admin.

Attention ! Si vous donnez des noms de fonction trop génériques, ils risquent de rentrer en conflit avec d’autres. Une bonne pratique consiste à préfixer les fonctions que vous écrivez avec les initiales de votre entreprise ou celle du plugin que vous développez.

Créer la structure principale

Créez un dossier dans le dossier « wp-content/plugins » de votre site web et donnez-lui le nom de votre plugin en utilisant un tiret court entre chaque terme. Par exemple, je souhaite créer un plugin, qui, pour chaque produit de ma boutique WooCommerce, affichera le jour estimé de livraison : « Recevez-le lundi 16 Mai ». Je souhaite que ce texte s’affiche uniquement pour les produits physiques et aux endroits suivants :

  • Sous le prix de chaque vignette produit lorsque l’utilisateur visualise l’ensemble des produits
  • Sous le prix du produit lorsque l’utilisateur est dans la fiche produit

Rien de très sorcier me direz-vous… Et pourtant ! Il va falloir bosser un peu. 😉 Pour commencer, dans le dossier de votre plugin, que vous appellerez « estimated-delivery-day », créez un fichier php, intitulé « estimated-delivery-day.php ». Dans ce fichier, placez le code ci-dessous :

<?php
/*
Plugin Name: Estimated Delivery Day
Description: This plugin estimates the delivery day according to the woocommerce shipping zones and shipping methods you put in place, or custom
Author: Roxane Anquetil, Webstreet Agency
*/

// Include edd-functions.php, use require_once to stop the script if edd-functions.php is not found
require_once plugin_dir_path(__FILE__) . 'includes/edd-functions.php';

Dans ce fichier, vous pouvez voir le nom du plugin qui apparaîtra dans le tableau de bord WordPress, la description, l’auteur et l’inclusion via la fonction « require_once » du fichier de fonctions du plugin, fichier que vous allez devoir également créé. Dans ce fichier, vous irez écrire les fonctions de votre plugin. Nous utiliserons la fonction intégrée de WordPress add_menu_page().

Les quatre paramètres requis de add_menu_page() sont les suivantes :

  1. Le titre de la page que vous voyez après avoir cliqué sur le lien (affiché dans l’onglet de votre navigateur)
  2. Le texte à afficher en tant que lien de menu (affiché dans la liste de navigation du panneau d’administration), le nom de votre plugin par exemple
  3. Les droits utilisateur pour l’affichage du menu, dans cet exemple, seuls les utilisateurs disposant de la fonctionnalité ‘manage_options’ peuvent accéder à la page
  4. Le fichier à utiliser lors de l’affichage de la page réelle, qui sera stocké dans le sous-dossier « includes » et nommé edd-admin-page.php. L’URL saisie ici est appelée « slug ».
  5. La fonction appelée lorsque l’on clique sur le lien
  6. L’icône du point de menu : dans notre exemple, nous utilisons dashicons. Pour trouver l’icône qui convient à votre plugin, rendez-vous sur cette page : https://developer.wordpress.org/resource/dashicons. Cliquez sur l’icône et copiez-collez le code tout en haut en paramètre.
  7. L’ordre dans lequel l’item de menu doit apparaître sur la page : plus le nombre est élevé, plus l’item sera bas dans le menu

Voici donc le contenu final de la page intitulée « estimated-delivery-day.php » :

<?php
/*
 * Add my new menu to the Admin Control Panel
 */
 
// Hook the 'admin_menu' action hook, run the function named 'edd_Add_Admin_Link()'
add_action( 'admin_menu', 'edd_Add_Admin_Link' );
 
// Add a new top level menu link to the ACP
function edd_Add_Admin_Link()
{
      add_menu_page(
        'Welcome to Estimated Delivery Day', // Title of the page
        'Estimated DDay', // Text to show on the menu link
        'manage_options', // Capability requirement to see the link
         'estimated-dday/admin-page.php', // The 'slug' - file to display when clicking the link
         'edd_Admin_Page', //the function handled when clicking the link
        'dashicons-calendar', //it is the icon URL, here using dashicons
        100 // the order of the menu item into the dashboard menu
    );
}

Et voici à quoi devrait ressembler votre dossier :

Structure de base plugin WordPress

Rendez-vous maintenant dans le menu Extensions ou Plugins de votre tableau de bord. And voilà !

Cliquez sur Activer. Votre point de menu ‘Estimated DDay’ devrait alors apparaître dans votre menu de gauche.

Créer la page d’administration

Maintenant, vous devez créer la page à afficher lorsque vous cliquez sur le point de menu. Revenez dans le fichier « edd-functions.php » et mettez-le à jour de la manière suivante :

<?php
/*
 * Add my new menu to the Admin Control Panel
 */

// Hook the 'admin_menu' action hook, run the function named 'edd_Add_Admin_Link()'
add_action( 'admin_menu', 'edd_Add_Admin_Link' );

// Add a new top level menu link to the ACP
function edd_Add_Admin_Link()
{
    add_menu_page(
        'Estimated Delivery Day', // Title of the page
        'Estimated DDay', // Text to show on the menu link
        'manage_options', // Capability requirement to see the link
        'estimated-dday/admin-page.php', // The 'slug' - file to display when clicking the link
         'edd_Admin_Page', //the function handled when clicking the link
        'dashicons-calendar', //it is the icon URL, here using dashicons
        100 // the order of the menu item into the dashboard menu
    );
}

function edd_Admin_Page()
{
    ?>
    <div class="wrap">
        <h1>Welcome to Estimated Delivery Day</h1>
        <h2>Settings</h2>
        <p>In how many business days can you deliver your customers?</p>
        <input name="business-days" type="integer" id="business-days"> <span> business days</span>
        <button type="submit" class="edd-submit">Record settings</button>

    </div>
    <?php
}

Gérer un formulaire dans votre plugin WordPress

C’est bien beau tout ça, mais pour le moment, mon formulaire ne fait rien de bien intéressant ! Ce que je souhaite, c’est que lorsque l’utilisateur clique sur « Record settings », un message s’affiche sous chaque prix de produit, disant « Livraison d’ici x jours ouvrés, où x correspond au nombre de jour que j’ai mis dans le champ « business days » du formulaire. Avant de savoir comment nous pourons calculer la date de livraison, focalisons-nous sur l’affichage sous le prix. Il est possible de faire apparaître cette affichage en utilisant un filtre. Ajoutez le code suivant au fichier « edd-functions.php ».

**
 * Add estimated delivery date after the woocommerce price
 */

add_filter( 'woocommerce_get_price_html', 'edd_add_description_after_price' );

function edd_add_description_after_price($price){
    $edd_estimated_delivery_date = "<br/><div><svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor' class='bi bi-truck' viewBox='0 0 16 16'>
  <path d='M0 3.5A1.5 1.5 0 0 1 1.5 2h9A1.5 1.5 0 0 1 12 3.5V5h1.02a1.5 1.5 0 0 1 1.17.563l1.481 1.85a1.5 1.5 0 0 1 .329.938V10.5a1.5 1.5 0 0 1-1.5 1.5H14a2 2 0 1 1-4 0H5a2 2 0 1 1-3.998-.085A1.5 1.5 0 0 1 0 10.5v-7zm1.294 7.456A1.999 1.999 0 0 1 4.732 11h5.536a2.01 2.01 0 0 1 .732-.732V3.5a.5.5 0 0 0-.5-.5h-9a.5.5 0 0 0-.5.5v7a.5.5 0 0 0 .294.456zM12 10a2 2 0 0 1 1.732 1h.768a.5.5 0 0 0 .5-.5V8.35a.5.5 0 0 0-.11-.312l-1.48-1.85A.5.5 0 0 0 13.02 6H12v4zm-9 1a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm9 0a1 1 0 1 0 0 2 1 1 0 0 0 0-2z'/>
</svg> Livraison d'ici le <span style='color:red !important'> 13 Mai 2022</span></div>";
	return $price .$edd_estimated_delivery_date   ;

}

Ensuite, visualisez vos produits sur votre site, vous devriez voir ceci :

Le filtre ‘woocommerce_get_price_html’, permet d’ajouter un préfixe au prix des produits WooCommerce.

D’accord, mais il y a un problème, le message est affiché pour TOUS mes produits, qu’ils soient virtuels ou physiques. Et l’objectif est bien évidemment de l’afficher uniquement aux produits physiques. Je complète ma fonction ainsi :

add_filter( 'woocommerce_get_price_html', 'edd_add_description_after_price' );

function edd_add_description_after_price($price){
    //$product = new WC_Product( get_the_ID() );
    global $product;
    
        $product = wc_get_product(get_the_id());

        $edd_estimated_delivery_date = "<br/>
<div><svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor' class='bi bi-truck' viewBox='0 0 16 16'>
  <path d='M0 3.5A1.5 1.5 0 0 1 1.5 2h9A1.5 1.5 0 0 1 12 3.5V5h1.02a1.5 1.5 0 0 1 1.17.563l1.481 1.85a1.5 1.5 0 0 1 .329.938V10.5a1.5 1.5 0 0 1-1.5 1.5H14a2 2 0 1 1-4 0H5a2 2 0 1 1-3.998-.085A1.5 1.5 0 0 1 0 10.5v-7zm1.294 7.456A1.999 1.999 0 0 1 4.732 11h5.536a2.01 2.01 0 0 1 .732-.732V3.5a.5.5 0 0 0-.5-.5h-9a.5.5 0 0 0-.5.5v7a.5.5 0 0 0 .294.456zM12 10a2 2 0 0 1 1.732 1h.768a.5.5 0 0 0 .5-.5V8.35a.5.5 0 0 0-.11-.312l-1.48-1.85A.5.5 0 0 0 13.02 6H12v4zm-9 1a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm9 0a1 1 0 1 0 0 2 1 1 0 0 0 0-2z'/>
</svg> Livraison d'ici le <span style='color:red !important'> 13 Mai 2022</span>
</div>";

        //if this is not a variable product: in this use case variable products are always virtual
        if (!$product->is_type('variable')) {


            //if the product is NOT virtual, add the delivery date
            if (!$product->is_virtual()) {
                return $price . $edd_estimated_delivery_date;
            }

        }
        
}

Dans le cas d’utilisation ci-dessus, je pars du principe que tous les produits variables de ma boutique sont forcément virtuels, donc je les exclus. Ensuite, parmi les produits restants, je teste s’ils ne sont pas virtuels : !$product->is_virtual(). Si ils ne le sont pas, je retourne le prix et la date estimée de livraison. Dans tous les autres cas, je retourne uniquement le prix ! And voilà !

On constate que seuls les produits non variables et parmi ces derniers, les produits physiques de ma boutique possèdent la date de livraison estimée.

Ajouter une classe objet au plugin WordPress

Super ! Sauf que la date de livraison estimée est toujours codée en dur ! Il va falloir ajouter une belle fonction capable de calculer la date réelle de livraison estimée. Ajoutez un dossier « classes » dans le répertoire de votre plugin. A l’intérieur, nous allons créer la classe « BdDateTime », qui sera l’extension de la classe « DateTime » déjà présente dans php. Voici le code de cette classe :

<?php
namespace Classes;

class BdDateTime extends \DateTime
{
    private $periods;
    private $holidays;

    /**
     * @return array
     */
    public function getPeriods(): array
    {
        return $this->periods;
    }

    /**
     * @param array $periods
     */
    public function setPeriods(array $periods): void
    {
        $this->periods = $periods;
    }

    public function __construct(string $time = 'now', \DateTimeZone $timezone = null)
    {
        parent::__construct($time, $timezone);

        // Put periods in a var cache
        $this->periods = [
            1 => new \DateInterval('P1D'),
            2 => new \DateInterval('P2D'),
            3 => new \DateInterval('P3D'),
        ];
    }

    public function addBusinessDays(int $nb)
    {
        if($nb > 0) {
            for($a = 0; $a < $nb; $a++) {
                $this->addBusinessDay();
            }
        }

        return $this;
    }

    private function addBusinessDay()
    {
        if($this->isFriday()) {
            $this->add($this->periods[3]);
        } elseif($this->isSaturday()) {
            $this->add($this->periods[2]);
        } else {
            $this->add($this->periods[1]);
        }

        // Check for holidays
        while(!$this->isBusinnessDay()) {
            $this->addBusinessDay();
        }
    }

    public function getHolidays(): array
    {
        return $this->holidays;
    }

    /**
     * @param array $holidays
     * @return $this
     */
    public function setHolidays(array $holidays)
    {
        $this->holidays = array_fill_keys($holidays, true);

        return $this;
    }

    /**
     * @param $day dd-mm-yyyy
     * Ex: $this->addHoliday('06-12-2018');
     * @return $this
     */
    public function addHoliday($day)
    {
        if(preg_match('/^[0-9]{2}-[0-9]{2}-20[0-9]{2}$/', $day)) {
            $this->holidays[$day] = true;
        }

        return $this;
    }

    /**
     * @return bool
     */
    private function isBusinnessDay(): bool
    {
        $key = $this->format('d-m-Y');

        return !$this->isWeekend() && empty($this->holidays[$key]);
    }

    private function isFriday(): bool
    {
        return $this->format('N') == 5;
    }

    private function isSaturday(): bool
    {
        return $this->format('N') == 6;
    }

    public function isSunday(): bool
    {
        return $this->format('N') == 7;
    }

    public function isWeekend(): bool
    {
        return ($this->isSunday() || $this->isSaturday());
    }
}

Grosso-modo, cette classe étend la classe DateTime. Les 2 fonctions qui nous intéressent sont :

  • addBusinessDays qui prend en seul paramètre : le nombre de jours ouvrés à ajouter à la date
  • addBusinessDay, méthode sans paramètre qui va ajouter 1 jour ouvré en vérifiant avant si la date courante est vendredi ou samedi

Dans notre cas, nous utiliserons la fonction addBusinessDays. Nous devons l’utiliser dans le fichier « edd-functions.php ». Au début de ce fichier, il va falloir appeler la classe BdDateTime. Cela se fait en ajoutant les lignes suivantes :

use Classes\BdDateTime;
require_once plugin_dir_path( __DIR__ ) . 'classes/BdDateTime.php';

Tout d’abord, nous utilisons le namespace, un slash, puis le nom de la classe que l’on souhaite utiliser dans le fichier. En-dessous, il faut également référencer le chemin vers le fichier grâce à la méthode « require_once », suivi de « plugin_dir_path( __DIR__ ) », qui va vous placer à la racine du plugin, suivi du chemin vers ladite classe.

Une fois votre classe référencée, vous allez pouvoir l’instancier, c’est-à-dire créer un nouvel objet. Puis sur l’objet, utiliser les méthodes définies dans la classe. Comme ceci :

 //create an object
        $bdDateTime = new BdDateTime('now');
        //call methods using object
        $edd_delivery_date = $bdDateTime->addBusinessDays(1)->format('d/m/Y');

Et voilà ! Votre date n’est plus codée en dur, à une exception : nous avons mis en paramètre de la fonction addBusinessDays, le chiffre 1. Or, nous souhaiterions récupérer la valeur de l’input du formulaire.

Ajouter une table à la base de données WordPress

Les informations saisies par l’utilisateur dans le formulaire, devront être enregistrées en base de données. Pour cela, il convient, à l’activation de votre plugin, qu’une table se crée dans votre base WordPress. Complétez le fichier principal de votre plugin, estimated-delivery-day.php, de la manière suivante :

<?php
/*
Plugin Name: Estimated Delivery Day
Description: This plugin estimates the delivery day according to the woocommerce shipping zones and shipping methods you put in place, or custom
Author: Roxane Anquetil, Webstreet Agency
*/


require_once plugin_dir_path(__FILE__) . 'includes/edd-functions.php';
global $my_plugin_db_version;
$my_plugin_db_version = "1.0";


function edd_business_days_table()
{
    global $wpdb; // global to access all the functions inside this wp class
    $charset_collate = $wpdb->get_charset_collate();

    $table_name = $wpdb->prefix . 'edd_business_days';

    $sql = "CREATE TABLE IF NOT EXISTS $table_name  (
      `id` int(11) NOT NULL PRIMARY KEY,
      `days` tinyint,
       `display` boolean NOT NULL,
       `created_at` datetime NOT NULL,
       `updated_at` datetime NOT NULL
    ) $charset_collate;";

    require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
    dbDelta( $sql );

    //create a version
    add_option("edd_business_days_version",$my_plugin_db_version);
}

register_activation_hook(__FILE__,'edd_business_days_table');





Nous avons ajouté le fonction edd_business_days_table(). Tout d’abord, on crée une variable globale, global $wpdb. Dans WordPress, la classe wpdb est utilisée pour interagir avec une base de données : https://developer.wordpress.org/reference/classes/wpdb/. L’objet global $wpdb de WordPress donne accès à la base de données de WordPress. La méthode get_charset_collate(), permet à WordPress de retrouver le jeu de caractère en base de données, par exemple UNICODE, et donc d’afficher correctement les caractères sur votre page web.

Puis, nous créeons une table, si elle n’existe pas déjà, via une requête SQL. Incluez ensuite les 2 lignes suivantes :

 require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
    dbDelta( $sql );

La méthode suivante « add_option », permet de créer un numéro de version à la structure de la table créée. Cette information pourra être réutilisée plus tard, lorsque vous aurez besoin de mettre à jour votre table.

Pour que WordPress procède à la création de la table à l’activation du plugin, utilisez le hook suivant, le 2ème paramètre correspondant à la fonction de création de table :

register_activation_hook(__FILE__,'edd_business_days_table');

Maintenant, mettez à jour votre plugin et désactivez, puis réactivez le ! Connectez vous à votre base de données pour constater si oui ou non une table a été créée !

Création d’une table via un plugin WordPress

Intégrer un formulaire à son plugin WordPress

Maintenant, il est temps de créer votre formulaire. L’idée est la suivante : l’utilisateur va rentrer le nombre de jours ouvrés nécessaires avant la date de livraison, puis si oui ou non il souhaite afficher le message sur le site, sous chaque prix des produits. Rien de bien sorcier !

Nous avons besoin de 2 fonctions, une fonction pour afficher le formulaire dans la page d’administration. Pour cela nous complèterons la fonction edd_admin_Page() déjà créée. Puis, une fonction pour traiter le formulaire à sa soumission par l’utilisateur, que nous appellerons the_form_response().

Fonction pour l’affichage du formulaire

function edd_Admin_Page()
{
    global $wpdb;
    ?>
    <div class="wrap">
        <h1>Welcome to Estimated Delivery Day</h1>
        <h2>Settings</h2>
        <?php
        /**
         * The form to be loaded on the plugin's admin page only if the logged in user has the edit_users capability.
         */

        // Generate a custom nonce value for the form.
        $edd_add_meta_nonce = wp_create_nonce( 'edd_add_user_meta_form_nonce' );

        //check if the current user has the edit_users capability
        if( current_user_can( 'edit_users' ) )
        {
            //build the form, make it compatible with admin-post.php to use the event driven nature of wordpress
            //add the action hidden input so that we can trigger the more specific hook related to our contact form submission
            //custom action edd_form_response so we will have 4 hooks available: admin_post_nopriv, admin_post_nopriv_edd_form_response, admin_post, admin_post_edd_form_response
            //generated a custom nonce above by using wp_create_nonce() and here added it as a hidden form field.

            //try to get the form_data if any
            $id = 1;
            $form_data = $wpdb->get_row(  "SELECT * FROM wp_edd_business_days WHERE id = 1");
        ?>
        <form id="email-test-form" method="POST" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">

            <input type="hidden" name="id" value="1">

            <input type="hidden" name="action" value="edd_form_response">

            <input type="hidden" name="edd_add_user_meta_nonce" value="<?php echo $edd_add_meta_nonce ?>" />

            <div class="form-group">
            <label>In how many business days can you deliver your customers?</label>
            <input required id="business-days" type="number" name="business-days" value="<?php echo $form_data -> days; ?>" /> <span> business days</span><br>

            </div>

            <div class="form-group">
                <label for="exampleFormControlSelect1">Display the delivery message on all physical products</label>
                <select class="form-control" id="display" name="display" value="">
                    <option <?php if($form_data -> display ==1){echo 'selected="selected"';} ?> value="1">Yes</option>
                    <option <?php if($form_data -> display==0){echo 'selected="selected"';} ?> value="0" >No</option>
                </select>
            </div>
            <p class="submit"><input type="submit" name="submit" id="submit" class="button button-primary" value="Record settings"></p>
        </form>
        <?php
            //if the message is displayed
            if($form_data -> display ==1) {
                //create an object
                $bdDateTime = new BdDateTime('now');
                //call methods using object
                $edd_delivery_date = $bdDateTime->addBusinessDays($form_data -> days)->format('d/m/Y');

                $edd_estimated_delivery_date = " The message displayed on all physical products is the following: <br/>
                <div><svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor' class='bi bi-truck' viewBox='0 0 16 16'>
                  <path d='M0 3.5A1.5 1.5 0 0 1 1.5 2h9A1.5 1.5 0 0 1 12 3.5V5h1.02a1.5 1.5 0 0 1 1.17.563l1.481 1.85a1.5 1.5 0 0 1 .329.938V10.5a1.5 1.5 0 0 1-1.5 1.5H14a2 2 0 1 1-4 0H5a2 2 0 1 1-3.998-.085A1.5 1.5 0 0 1 0 10.5v-7zm1.294 7.456A1.999 1.999 0 0 1 4.732 11h5.536a2.01 2.01 0 0 1 .732-.732V3.5a.5.5 0 0 0-.5-.5h-9a.5.5 0 0 0-.5.5v7a.5.5 0 0 0 .294.456zM12 10a2 2 0 0 1 1.732 1h.768a.5.5 0 0 0 .5-.5V8.35a.5.5 0 0 0-.11-.312l-1.48-1.85A.5.5 0 0 0 13.02 6H12v4zm-9 1a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm9 0a1 1 0 1 0 0 2 1 1 0 0 0 0-2z'/>
                </svg> Livraison d'ici le <span style='color:red !important'> $edd_delivery_date</span>
                </div>";

                echo $edd_estimated_delivery_date;

            } else {
                echo "No delivery message is displayed on your store physical products. ";
            }
         }
        ?>
    </div>
    <?php
}

Quelques explications s’imposent ! Tout d’abord, nous générons un custom nonce pour le formulaire : $edd_add_meta_nonce = wp_create_nonce( 'edd_add_user_meta_form_nonce' );

Cette fonction WordPress crée un token cryptographique lié à une action spécifique. Ici, dans le cas du formulaire, nous créons un champ caché au sein même du formulaire, dont la valeur est le token cryptographique: <input type="hidden" name="edd_add_user_meta_nonce" value="<?php echo $edd_add_meta_nonce ?>" />

Puis, on vérifie si l’utilisateur courant a le droit « edit_users »: if( current_user_can( 'edit_users' ) ). Dans WordPress, ce doit permet l’accès aux écrans d’administration. Si c’est bien le cas pour l’utilisateur courant, alors on peut afficher le formulaire.

On tente de récupérer les informations en base de données :

$id = 1;             
$form_data = $wpdb->get_row(  "SELECT * FROM wp_edd_business_days WHERE id = 1");

Il se peut que le formulaire n’ait pas encore été soumis. Dans ce cas, les champs seront vides ou afficheront une valeur par défaut. Sinon, si l’on trouve des informations dans la 1ère ligne de la table, on les affiche, comme ceci : value="<?php echo $form_data -> days; ?>"

Dans le cas de ce plugin, on part du principe qu’il y aura toujours une seule et unique ligne dans notre table. C’est pour ça que la fonction $wpdb->get_row est utilisée. Elle doit être utilisée quand le résultat est unique.

Remarquez que le formulaire est envoyé ici : <?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>, dans la valeur de l’attribut « action ». Quand l’utilisateur cliquera sur « Submit », les requêtes POST ou GET seront disponibles via admin_post. Vous pouvez consulter la page du codex. Pour récupérer les valeurs, on utilisera la fonction add_action de wordpress, de cette manière : add_action( 'admin_post_edd_form_response', 'the_form_response');

Le 1er paramètre correspond à la page admin-post suivie de la valeur du champ caché action, dans notre exemple « edd_form_response ». Le 2ème paramètre, c’est la fonction qui va devoir traiter les valeurs récupérées, dans notre exemple the_form_response()

Fonction pour le traitement du formulaire

//process the request by registering the custom handler in the define_admin_hooks() method of class-init.php
//the callback function the_form_response is where we do the data processing and WHERE  $_GET/$_POST variable are available
add_action( 'admin_post_edd_form_response', 'the_form_response');

function the_form_response()
{
    global $wpdb;

     //on form submission
     if( isset( $_POST['edd_add_user_meta_nonce'] ) && wp_verify_nonce( $_POST['edd_add_user_meta_nonce'], 'edd_add_user_meta_form_nonce') ) {

        // sanitize and get the input
        $id =  $_POST['id'];
        $edd_business_days =  $_POST['business-days'];
        $display = $_POST['display'];

        //update or if not exists insert
        $result =
            $wpdb->update(
                'wp_edd_business_days',
                array( 'days' => $edd_business_days, 'display' => $display,'created_at' => current_time('mysql', 1), 'updated_at' => current_time('mysql', 1)),
                array('id' => $id)
        );

        //If nothing found to update, it will try and create the record.
        if ($result === FALSE || $result < 1) {

            $wpdb->insert(
                'wp_edd_business_days',
                array( 'id' => $id, 'days' => $edd_business_days, 'display' => $display,'created_at' => current_time('mysql', 1), 'updated_at' => current_time('mysql', 1))
            );
        }

        //I want the delivery message to be returned in the admin page

        //create an object
        $bdDateTime = new BdDateTime('now');
        //call methods using object
        $edd_delivery_date = $bdDateTime->addBusinessDays($edd_business_days)->format('d/m/Y');

        $edd_estimated_delivery_date = "<br/>
        <div><svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor' class='bi bi-truck' viewBox='0 0 16 16'>
          <path d='M0 3.5A1.5 1.5 0 0 1 1.5 2h9A1.5 1.5 0 0 1 12 3.5V5h1.02a1.5 1.5 0 0 1 1.17.563l1.481 1.85a1.5 1.5 0 0 1 .329.938V10.5a1.5 1.5 0 0 1-1.5 1.5H14a2 2 0 1 1-4 0H5a2 2 0 1 1-3.998-.085A1.5 1.5 0 0 1 0 10.5v-7zm1.294 7.456A1.999 1.999 0 0 1 4.732 11h5.536a2.01 2.01 0 0 1 .732-.732V3.5a.5.5 0 0 0-.5-.5h-9a.5.5 0 0 0-.5.5v7a.5.5 0 0 0 .294.456zM12 10a2 2 0 0 1 1.732 1h.768a.5.5 0 0 0 .5-.5V8.35a.5.5 0 0 0-.11-.312l-1.48-1.85A.5.5 0 0 0 13.02 6H12v4zm-9 1a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm9 0a1 1 0 1 0 0 2 1 1 0 0 0 0-2z'/>
        </svg> Livraison d'ici le <span style='color:red !important'> $edd_delivery_date</span>
        </div>";

        // add the admin notice
        $admin_notice = "admin.php?page=estimated-dday%2Fadmin-page.php";

        // redirect the user to the appropriate page
        wp_redirect( $admin_notice, 302);
        exit;
    }
}

Dans cette fonction « the_form_response() », on va tout simplement récupérer le résultat du formulaire et en faire quelque-chose ! Dans notre cas, on mettra à jour l’enregistrement dans la table de la base de données et, si l’enregistrement n’existe pas, on le créera. La redirection vers notre page de plugin est créée via la fonction wp_redirect de wordpress: wp_redirect( $admin_notice, 302);

Complétion de la fonction edd_add_description_after_price() pour aller chercher les informations en base de données

add_filter( 'woocommerce_get_price_html', 'edd_add_description_after_price' );

function edd_add_description_after_price($price){
    //$product = new WC_Product( get_the_ID() );
    global $product;
    global $edd_business_days;
    global $wpdb;

    $product = wc_get_product(get_the_id());


    //if this is not a variable product, in this use case variable products are always virtual
    if (!$product->is_type('variable')) {


        //if the product is NOT virtual
        if (!$product->is_virtual()) {

            //get the info of the form from db
            $form_data = $wpdb->get_row(  "SELECT * FROM wp_edd_business_days WHERE id = 1");

            //if the user asked the text to be displayed
            if ($form_data -> display != 0) {
                //create an object
                $bdDateTime = new BdDateTime('now');
                //call methods using object
                $edd_delivery_date = $bdDateTime->addBusinessDays($form_data -> days)->format('d/m/Y');

                $edd_estimated_delivery_date = "<br/>
                    <div><svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor' class='bi bi-truck' viewBox='0 0 16 16'>
                      <path d='M0 3.5A1.5 1.5 0 0 1 1.5 2h9A1.5 1.5 0 0 1 12 3.5V5h1.02a1.5 1.5 0 0 1 1.17.563l1.481 1.85a1.5 1.5 0 0 1 .329.938V10.5a1.5 1.5 0 0 1-1.5 1.5H14a2 2 0 1 1-4 0H5a2 2 0 1 1-3.998-.085A1.5 1.5 0 0 1 0 10.5v-7zm1.294 7.456A1.999 1.999 0 0 1 4.732 11h5.536a2.01 2.01 0 0 1 .732-.732V3.5a.5.5 0 0 0-.5-.5h-9a.5.5 0 0 0-.5.5v7a.5.5 0 0 0 .294.456zM12 10a2 2 0 0 1 1.732 1h.768a.5.5 0 0 0 .5-.5V8.35a.5.5 0 0 0-.11-.312l-1.48-1.85A.5.5 0 0 0 13.02 6H12v4zm-9 1a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm9 0a1 1 0 1 0 0 2 1 1 0 0 0 0-2z'/>
                    </svg> Livraison d'ici le <span style='color:red !important'> $edd_delivery_date</span>
                    </div>";

                //appeler ici le texte créé apres avoir soumis le formulaire
                return $price .   $edd_estimated_delivery_date;

            }
            //otherwise it means we should only display price
            else {
                return $price;
            }


        }
        else {
            return $price;
        }

    } else {
        return $price;
    }

}

Traduire votre plugin WordPress dans différentes langues

Super ! Mais mon site est multilingue ! De plus, je souhaite que mon plugin profite à n’importe-quel utilisateur, quelque-soit sa langue ! Nous allons voir ici comment rendre un plugin multilingue. Pour rendre un plugin multilingue, il faut utiliser les fonctions __() ou _e(). On utilise la fonction _e($text,$domain) pour afficher une chaîne de caractère traduite, $text représentant la chaîne à traduire et $domain représentant la clé qui sera utilisée pour rechercher la traduction dans les fichiers de langue. Voyons un exemple :

_e("Welcome to Estimated Delivery Day",'edd');

Nous remplacerons tous les textes à traduire de notre plugin en les encapsulant dans cette fonction. Si la chaîne à traduire ne doit pas être imprimée à l’écran, on utilisera la fonction __($text,$domain). Cela est notamment indispensable lorsque l’on souhaite par exemple concaténer la chaîne à traduire avec du code HTML et d’autres variables, afin de mettre cette nouvelle chaîne ainsi créée dans une variables, comme ci-dessous :

  $deliverydate = esc_html__('Delivery by','edd');
                $edd_estimated_delivery_date = "<div><svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor' class='bi bi-truck' viewBox='0 0 16 16'>
                        <path d='M0 3.5A1.5 1.5 0 0 1 1.5 2h9A1.5 1.5 0 0 1 12 3.5V5h1.02a1.5 1.5 0 0 1 1.17.563l1.481 1.85a1.5 1.5 0 0 1 .329.938V10.5a1.5 1.5 0 0 1-1.5 1.5H14a2 2 0 1 1-4 0H5a2 2 0 1 1-3.998-.085A1.5 1.5 0 0 1 0 10.5v-7zm1.294 7.456A1.999 1.999 0 0 1 4.732 11h5.536a2.01 2.01 0 0 1 .732-.732V3.5a.5.5 0 0 0-.5-.5h-9a.5.5 0 0 0-.5.5v7a.5.5 0 0 0 .294.456zM12 10a2 2 0 0 1 1.732 1h.768a.5.5 0 0 0 .5-.5V8.35a.5.5 0 0 0-.11-.312l-1.48-1.85A.5.5 0 0 0 13.02 6H12v4zm-9 1a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm9 0a1 1 0 1 0 0 2 1 1 0 0 0 0-2z'/>
                    </svg> <strong>".$deliverydate."</strong><span style='color:red !important'>".$edd_delivery_date."</span>
                </div>";



                //appeler ici le texte créé apres avoir soumis le formulaire
                return
                    $price . $edd_estimated_delivery_date ;

Ou par exemple pour rendre le menu multilingue :

function edd_Add_Admin_Link()
{
    add_menu_page(
        __('Estimated Delivery Day','edd'), // Title of the page
        __('Estimated DDay','edd'), // Text to show on the menu link
        'manage_options', // Capability requirement to see the link
        'estimated-dday/admin-page.php', // The 'slug' - file to display when clicking the link
        'edd_Admin_Page', //the function handled when clicking the link
        'dashicons-calendar', //it is the icon URL, here using dashicons
        100 // the order of the menu item into the dashboard menu
    );
}

Et voici ce que donne la fonction edd_Admin_Page() du plugin avec la prise en compte du multilingue :

function edd_Admin_Page()
{
    global $wpdb;
    ?>
    <div class="wrap">
        <h1><?php esc_html_e('Welcome to Estimated Delivery Day','edd');?></h1>
        <h2><?php esc_html_e('Settings','edd');?></h2>
        <?php
        /**
         * The form to be loaded on the plugin's admin page only if the logged in user has the edit_users capability.
         */

        // Generate a custom nonce value for the form.
        $edd_add_meta_nonce = wp_create_nonce( 'edd_add_user_meta_form_nonce' );

        //check if the current user has the edit_users capability
        if( current_user_can( 'edit_users' ) )
        {
            //build the form, make it compatible with admin-post.php to use the event driven nature of wordpress
            //add the action hidden input so that we can trigger the more specific hook related to our contact form submission
            //custom action edd_form_response so we will have 4 hooks available: admin_post_nopriv, admin_post_nopriv_edd_form_response, admin_post, admin_post_edd_form_response
            //generated a custom nonce above by using wp_create_nonce() and here added it as a hidden form field.

            //try to get the form_data if any
            $id = 1;
            $form_data = $wpdb->get_row(  "SELECT * FROM wp_edd_business_days WHERE id = 1");
        ?>
        <form id="email-test-form" method="POST" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">

            <input type="hidden" name="id" value="1">

            <input type="hidden" name="action" value="edd_form_response">

            <input type="hidden" name="edd_add_user_meta_nonce" value="<?php echo $edd_add_meta_nonce ?>" />

            <div class="form-group">
            <label><?php esc_html_e('In how many business days can you deliver your customers?','edd');?></label>
            <input required id="business-days" type="number" name="business-days" value="<?php echo $form_data -> days; ?>" /> <span> <?php esc_html_e('business days','edd');?></span><br>

            </div>

            <div class="form-group">
                <label for="exampleFormControlSelect1"><?php esc_html_e('Display the delivery message on all physical products','edd');?></label>
                <select class="form-control" id="display" name="display" value="">
                    <option <?php if($form_data -> display ==1){echo 'selected="selected"';} ?> value="1"><?php esc_html_e('Yes','edd');?></option>
                    <option <?php if($form_data -> display==0){echo 'selected="selected"';} ?> value="0" ><?php esc_html_e('No','edd');?></option>
                </select>
            </div>
            <p class="submit"><input type="submit" name="submit" id="submit" class="button button-primary" value="<?php esc_html_e('Record settings','edd');?>"></p>
        </form>
        <?php
            //if the message is displayed
            if($form_data -> display ==1) {
                //create an object
                $bdDateTime = new BdDateTime('now');
                //call methods using object
                $edd_delivery_date = $bdDateTime->addBusinessDays($form_data -> days)->format('d/m/Y');

                $edd_estimated_delivery_date = esc_html_e('The message displayed on all physical products is the following:','edd');?><br/>
                <div><svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor' class='bi bi-truck' viewBox='0 0 16 16'>
                    <path d='M0 3.5A1.5 1.5 0 0 1 1.5 2h9A1.5 1.5 0 0 1 12 3.5V5h1.02a1.5 1.5 0 0 1 1.17.563l1.481 1.85a1.5 1.5 0 0 1 .329.938V10.5a1.5 1.5 0 0 1-1.5 1.5H14a2 2 0 1 1-4 0H5a2 2 0 1 1-3.998-.085A1.5 1.5 0 0 1 0 10.5v-7zm1.294 7.456A1.999 1.999 0 0 1 4.732 11h5.536a2.01 2.01 0 0 1 .732-.732V3.5a.5.5 0 0 0-.5-.5h-9a.5.5 0 0 0-.5.5v7a.5.5 0 0 0 .294.456zM12 10a2 2 0 0 1 1.732 1h.768a.5.5 0 0 0 .5-.5V8.35a.5.5 0 0 0-.11-.312l-1.48-1.85A.5.5 0 0 0 13.02 6H12v4zm-9 1a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm9 0a1 1 0 1 0 0 2 1 1 0 0 0 0-2z'/>
                     </svg> <strong><?php esc_html_e('Delivery by','edd'); ?></strong><span style='color:red !important'><?php echo $edd_delivery_date ?></span>
                </div>

                    <?php

                echo $edd_estimated_delivery_date;

            } else {
                echo esc_html_e('No delivery message is displayed on your store physical products.','edd');
            }
         }
        ?>
    </div>
    <?php
}

Ce n’est pas tout ! Il faut également dire à wordpress, de charger les fichiers de langue du plugin, lors de l’instation de celui-ci. On ajoute au fichier estimated-delivery-day.php, le code suivant :

//Load languages on plugin load
add_action('plugins_loaded', 'plugin_init');

function plugin_init() {
    load_plugin_textdomain( 'edd', false, dirname( plugin_basename( __FILE__ ) ) . '/lang' );
}

Créez ensuite un dossier « lang » à la racine du plugin et insérez dedans un fichier .pot. Vous pouvez créer un fichier .pot soit manuellement, soit en utilisant la version payante du logiciel PoEdit ! Ensuite, à l’aide du logiciel PoEdit, vous pourrez créer des fichiers de langue en cliquant sur Fichier => Nouveau à partir d’un fichier POT/PO

Créer une nouvelle traduction pour votre plugin

Allez chercher le fichier .pot du plugin. Pour ma part, je n’utilise pas la version pro de PoEdit, j’ai créé le fichier .pot de cet exemple manuellement, mais il est possible d’automatiser sa création à l’aide d’un script que je vous donnerai dans un prochain tuto ! PoEdit, une fois le fichier .pot sélectionné, vous demande la langue du fichier de traduction, choisissez la langue et commencez à traduire ! A la fin, enregistrez bien votre fichier dans le dossier « lang ». PoEdit génèrera le .po et le .mo, c’est le fichier de traduction compilé.

Maintenant téléchargez votre code sur votre serveur et et activez votre plugin. Si votre wordpress est en français, vous devriez voir le plugin traduit en français !

Conclusion

Dans ce tutoriel, je vous ai appris à créer un plugin WordPress de A à Z ! Vous pouvez retrouver l’intégralité du code de ce plugin ici :

Télécharger le plugin Estimated Delivery Day

Vous adorez ce plugin et souhaitez profiter de toutes ses fonctionnalités ? Sachez que dans la version payante, vous pourrez également :

  • Intégrer les jours fériés aux jours ouvrés
  • Afficher le message de livraison sur les produits variables non virtuels
  • Paramétrer la phrase d’affichage
  • Paramétrer le format de la date d’affichage
  • Styliser votre message de livraison

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.

Ce site web utilise des cookies pour vous offrir une meilleure expérience.