Associer un nom de domaine à un site d’un réseau WordPress (multisite)

Associer un nom de domaine à un site d’un réseau WordPress (multisite)

Dans le premier article de cette série « « , nous avons vu comment créer un réseau de sites sur une seule installation de WordPress et une seule base de données. Jusqu’à présent, les sites du réseau ont tous une url sous la forme d’un sous-domaine du site principal (http(s)://prefix.domain-principal.com et le site principal est http(s)://domain-principal.com). Je veux qu’un des sites du réseau utilise un autre nom de domaine, et pas un sous-domaine du domaine principal.

Pour celà, l’usage est d’utiliser une extension de « domain mapping », telle que WordPress MU Domain Mapping. Dans ce billet, je vais parler de cette extension et d’une méthode encore plus simple.

Préparation du nom de domaine à associer

Le site WordPress multisite dans lequel je veux insérer un nouveau domaine est dans un répertoire intitulé « multi-test ». Le domaine que je veux y insérer est  test1.parcours-performance.com

Sur l’espace client OVH, dans l’hébergement qui contient le multisite, cliquer sur l’onglet « multisites » puis sur le bouton « ajouter un domaine ou un sous-domaine ».

Association d'un domaine tiers à un WordPress multisite - 1

Là je n’aurais pas dû cocher « créer également … www… ». Je l’ai supprimé après pour ne pas multiplier les noms de domaine dans mon espace client…

Association d'un domaine tiers à un WordPress multisite - 2

Association d'un domaine tiers à un WordPress multisite - 3

Mon site WordPress multisite avant

J’ai déjà créé les sites test1.potentiel-web.com et test2.potentiel-web.com selon la méthodologie décrite dans l’article précédent de cette série . Je vais les laisser tels quels.

Je pars donc d’un réseau de sites contenant 3 sites :

  • le site principal (potentiel-web.com)
  • deux sites ayant pour nom un sous-domaine du site principal (test1.potentiel-web.com et test2.potentiel-web.com).

Je viens de créer un sous-domaine, test1.parcours-performance.com, dans mon espace client OVH et il est relié à l’hébergement du multisite.

J’ai maintenant deux options pour créer un site dans le réseau multisite :

  1. avec l’extension  WordPress MU Domain Mapping ;
  2. Sans extension – c’est la solution que je recommande.

Avec une extension de « domain mapping »

On installe WordPress MU Domain Mapping de façon normale avec « admin du réseau » > « extensions » > « ajouter » puis on cliquer sur « activer sur le réseau ».

Configurer WordPress MU Domain Mapping

Pour être certaine de comprendre les instructions d’installation de l’extension, j’ai également lu WordPress 3.0: Multisite Domain Mapping Tutorial.

Modification de fichiers

  1. Avec Filezilla (ou autre client FTP), aller dans /multi-test/wp-content/plugins/wordpress-mu-domain-mapping  et déplacer sunrise.php  pour le mettre dans /multi-test/wp-content .
  2. éditer wp-config.php  et décommenter ou ajouter la ligne suivante, au dessus de dernier « require_once ».
/* for the multisite WordPress MU Domain Mapping extension */
define( 'SUNRISE', 'on' );

Réglages de l’extension

Dans « admin du réseau » > « Tableau de bord », on voit dans les menus à gauche « Réglages ». Cliquer sur son sous-menu « domain mapping ».

Configuration du domain mapping

L’adresse IP se trouve à droite du nom de l’hébergement dans l’espace client OVH. Dans WordPress, « Réglages » > « Domains », on saisit cette adresse IP puis on définit les options du domaine.

Spontanément, je n’aurais coché que la case 2, comme dans la copie d’écran ci-dessus.

Mais après quelques essais, j’ai vu que je dois cocher la case 5, « Disable primary domain check. Sites will not redirect to one domain name. May cause duplicate content issues.« .  En effet, si j’utilise des domaines externes (qui ne sont pas des sous-domaines du site principal), l’internaute voit le nom du site d’origine car la redirection est visible. Ainsi, après avoir « mappé » https://test1.parcours-performance.com à https://test2.potentiel-web.com (opération décrite plus loin),  si je tape https://test1.parcours-performance.com dans un navigateur, le site s’ouvre mais l’url visible est devenue https://test2.potentiel-web.com…

Il faut donc cocher la case 5 si on veut que la redirection soit invisible pour les internautes.

Je coche donc les cases 2 et 5.

Mapper un site à un autre

En tant que super administrateur, je vais dans  « admin du réseau » > « Sites » et je vois la liste des sites déjà créés :

WordPress multisite : liste des sites

Lorsqu’on passe la souris sur le nom d’un des sites, son adresse complète apparaît tout en bas du navigateur et on peut relever son ID :

WordPress multisite : obtenir l'ID d'un site

Ici le site test1.potentiel-web.com affiche l’adresse « https://potentiel-web.com/wp-admin/network/site-info.php?id=3 ». L’ID est donc 3.

Maintenant, je vais dans « Réglages » > « Domains » et pour l’ID 3, je définis le domaine comme « test1.parcours-performance.com » :

WordPress multisite : map a domain

Ensuite si je retourne dans la liste des sites et que je cliques sur « modifier » en  dessous de test1.potentiel-web.com, je vois que l’adresse du site est restée https://test1.potentiel-web.com/ mais la liste indique un « mapping » vers test1.parcours-performance.com

Dans un navigateur, si je tape :

  • https://test1.potentiel-web.com/ m’affiche le site correspondant, dont le titre est test 1;
  • https://test1.parcours-performance.com, j’accède bien au site correspondant (dont le titre est toujours test1…) et son url visible dans le navigateur est restée https://test1.parcours-performance.com, si j’ai coché la case 5 des options de domaine (voir réglages ci-dessus).

Bilan de cette solution avec extension

Cette solution parait simple mais elle a deux inconvénients majeurs selon moi :

  • on est obligé de cocher l’option 5 si on veut que l’internaute ne voit pas la redirection. Ca génère un risque de contenu dupliqué pour les moteurs de recherche et ça ne me paraît pas acceptable.
  • Pour chaque domaine externe, on doit créer un sous-domaine du site principal ET le domaine externe. Ca prend un peu plus de temps et le risque d’erreur s’accroît.

C’est pour ces raisons que lorsque j’ai lu  un sujet épinglé par l’auteur de l’extension qui expliquait qu’on n’a même pas besoin de l’extension, j’ai sauté dessus et je suis aller explorer la solution.

Sans extension – solution recommandée

créer un nouveau site

En tant que super administrateur, je vais dans  « admin du réseau » > « Sites » et je vois la liste des sites déjà créés :

WordPress multisite : liste des sites

Je veux créer un nouveau site dans le réseau, avec l’url https://test1.parcours-performance.com. Dans la fenêtre des sites, je clique sur « ajouter » et je définis l’adresse web du site à RIEN (!) :

WordPress multisite : ajouter un nouveau site (1)

J’ai créé un site rien.potentiel-web.com, qui ne peut évidemment pas fonctionner puisque je n’ai pas créé ce sous-domaine dans mon espace client OVH. Il est visible dans la liste des sites du réseau WordPress :

WordPress multisite : ajouter un nouveau site (2)

Si je passe ma souris sur rien.potentiel-web.com, je vois apparaître « modifier ». Je clique dessus et dans « adresse web du site (URL) je remplace http://rien.potentiel-web.com/ par https://test1.parcours-performance.com. Après avoir sauvegardé la modification, je peux visiter le site et il fonctionne :

WordPress multisite : ajouter un nouveau site (3)

Maintenant un internaute peut accéder au site  https://test1.parcours-performance.com. Mais je ne peux pas accéder à son tableau de bord pour l’instant !

Régler wp-config.php

Je ne peux pas accéder au tableau de bord du nouveau site car il y a un problème de « cookies » qui interdit la connexion. Dans le navigateur Chrome ou Firefox, j’obtiens un message « ERREUR  les cookies sont bloqués ou ne sont pas reconnus par votre navigateur ». La seule solution est de modifier wp-config.php  comme indiqué dans cet article de Tom McFarlin.

Dasn wp-config.php, les lignes relatives au multisite sont maintenant les suivantes, avec les 4 lignes surlignées qui règlent le problème de cookies :

/* Multisite */
define('WP_ALLOW_MULTISITE', true);

define('MULTISITE', true);
define('SUBDOMAIN_INSTALL', true);
define('DOMAIN_CURRENT_SITE', 'potentiel-web.com');
define('PATH_CURRENT_SITE', '/');
define('SITE_ID_CURRENT_SITE', 1);
define('BLOG_ID_CURRENT_SITE', 1);

/* HTTPS only for admin access */
define( 'FORCE_SSL_ADMIN', true );

define('ADMIN_COOKIE_PATH', '/');
define('COOKIE_DOMAIN', '');
define('COOKIEPATH', '');
define('SITECOOKIEPATH', '');

/* That's all, stop editing! Happy blogging. */

Une troisième solution pour ajouter un site

Dans le tableau de bord WordPress, je supprime le site test2.potentiel-web.com mais je le laisse associé à l’hébergement potentiel-web.com dans mon espace client OVH.

Si je tape https://test2.potentiel-web.com dans un navigateur, je suis redirigée vers l’url https://potentiel-web.com/wp-signup.php?new=test2

Si je ne suis pas connectée en tant que super administrateur (c’est le cas dans le navigateur Firefox ci-dessous), je tombe sur une page m’informant que les inscriptions sont désactivées.

WordPress multisite : ajouter un nouveau site (4)

Lorsque les inscriptions sont désactivées, c’est que dans le tableau de bord du réseau de site, dans Réglages > Réglages du réseau, j’ai coché la case « Les inscriptions ne sont pas autorisées pour le moment ». Comme je ne prévois pas de laisser des utilisateurs externes créer des sites, et que mon hébergement OVH me contraint à aller créer les noms de domaine un à un (pas de « wildcard » *), je n’ai aucun intérêt à changer ce réglage.

Et maintenant ?

Dans les prochains articles de cette série , nous verrons comment sauvegarder un multisite, y insérer un site existant ou en sortir un.

migration d’un site WordPress en http vers https (SSL)

migration d’un site WordPress en http vers https (SSL)

Dans un précédent article (WordPress avec un SSL Let’s encrypt sur OVH mutualisé) j’ai exploré la création de zéro d’un site encrypté. Maintenant, je veux voir ce qu’il se passe si je transforme un site existant.

Pour minimiser les risques, j’ai cloné un site existant http://monsite.com dans http://prefix.monsite.com. J’ai d’abord essayé tout ce qui suit avant de le refaire sur un site opérationnel. Et je recommande à toute personne qui veut faire la même chose de faire d’abord un essai sur un site sans risque avant de se lancer sur un site en activité.

Quelques lectures avant de commencer !

Avant de démarrer, j’ai lu les 2 documents suivants :

Nota 1 : Dans l’article de référence, une bonne partie des 23 actions concernent les CDN (content delivery network selon Wikipedia). Comme je ne suis pas concernée, je les ai shuntées. Mais j’y ai ajoutée la création du certificat SSL.

Nota 2 : pour un site qui utilise un cache, il faut le vider avant de procéder aux étapes qui suivent.

étape 1 : créer un certificat ssl pour le site

Comme dans l’article (WordPress avec un SSL Let’s encrypt sur OVH mutualisé), je vais dans l’espace client de l’hébergement (OVH ici).

Pour chaque domaine et sous-domaine concerné, dans hébergement, onglet « multisite », j’édite le nom de domaine et je coche SSL. ATTENTION : il faut impérativement que le sous-domaine www soit également couvert par le certificat si on veut ensuite pouvoir faire une rédirection de www vers non www (ça n’est pas logique mais c’est comme ça) ! Une fois que j’ai modifié tous les domaines, je clique sur le bouton « régénérer le certificat ssl ». Si on vient juste de créer un domaine ou d’activer le ssl sur un domaine, il faut attendre plusieurs heures avant que le site puisse être lu en https.

A ce stade, si on ne fait pas les étapes suivantes, le site fonctionne parfaitement en http (http://nom-de-mon-site.com). On a intérêt à attendre que le certificat SSL soit régénéré avant de commencer les étapes suivantes.

Une fois que le certificat SSL est régénéré, si on tape https://nom-de-mon-site.com, le site s’affiche sans message d’erreur mais il n’y a pas le petit verrou vert à gauche du lien. Avec l’inspecteur de Chrome, je vois qu’il y a du « mixed content« . Le site est en https mais fait appel à des contenus issus de http. Le navigateur considère que le site n’est pas complètement sécurisé. Nous allons donc supprimer ces liens http et les remplacer par des https.

étape 2 : des liens https dans la base de données

L’article How to Migrate from HTTP to HTTPS – Complete Tutorial propose d’utiliser « Database search and replace script in php« , d’Interconnect IT. L’intérêt est que les contenus « sérialisés », comme les options ne sont pas altérés par le changement. J’essaie donc.

Tout est expliqué en français dans cet article de Grégoire Noyelle : WordPress :: Migrer son site avec le script d’Interconnectit.

  1. Répertoire search-replace-db-masterSauvegarder la base de données du site !
  2. Télécharger le script d’Interconnectit ;
  3. L’extraire et placer le répertoire Search-Replace-DB-master  dans un sous-répertoire du répertoire WordPress du site à modifier, c’est à dire un répertoire au même niveau que wp-content, wp-admin ou wp-includes. Renommer le répertoire, de  Search-Replace-DB-master vers par exemple migrer comme dans la copie d’écran à droite.
  4. On lance le script en tapant http://nom-de-mon-site.com/migrer/
  5. On cherche http://nom-de-mon-site.com, à remplacer par https://nom-de-mon-site.com
  6. Lancer dryrun pour voir ce qui va être modifier sans procéder à la modification
  7. Si tout semble correct (et que la base de données a été sauvegardée avant), lancer « live run » pour réaliser effectivement les modifications. Dans mon cas, 712 entrées ont été modifiées.
  8. Lorsqu’on a cloné un autre site, il est utile aussi de remplacer d’éventuels liens vers l’autre site par https://nom-de-mon-site.com. Dans mon cas, ça a modifié 8294 entrées

Ca y est, le petit verrou vert est maintenant à gauche du lien lorsque je visionne https://nom-de-mon-site.com !

Si vous avez du « mixed content », la solution merveilleuse est whynopadlock, qui scanne le site et nous dit quels sont les contenus en http et ce qui les charge.

Mais si je clique sur un article du site de test, j’ai un message d’erreur indiquant que le lien n’existe pas.

SUPPRIMER le répertoire « migrer » avant de continuer !

étape 3 : changer les adresses du site

Dans le tableau de bord WordPress, menu « Réglages » > « Général », modifier les liens « Adresse web de WordPress (URL) » et « Adresse web du site (URL) » en remplaçant l’adresse http par https.

Si on rafraichit (F5) le navigateur, les liens du site devraient fonctionner mais ce n’est pas le cas. Il faudra attendre l’étape 5 pour que ça fonctionne !

étape 4 : mise à jour des permaliens

Dans le tableau de bord WordPress, menu « Réglages » > « Permaliens », vérifier que la case cochée est la bonne puis cliquer sur « enregistrer les modifications », même si on n’en a pas fait.

Si on rafraichit (F5) le navigateur, les liens du site devraient fonctionner mais ce n’est pas le cas. Il faudra attendre l’étape 5 pour que ça fonctionne !

étape 5 : MAJ des librairies JS ou Ajax

J’ai vérifié avec les parties « scripts » et « styles » de l’extension Query Monitor (cf cet article, sur ce site, sur les outils de débogage) et aucun script ou style externe n’est appelé par une url non encryptée. Je n’ai donc pas besoin de réaliser cette étape.

étape 6 : ajouter des redirections 301

On veut que les sites en www.mondomaine.com soient redirigés vers https://mondomaine.com et que les http:// soient redirigés vers https.

Pour celà, ajouter ces instructions dans le fichier .htaccess, au dessus de la ligne # BEGIN WordPress  :

RewriteEngine on

RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]

RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

Note : Cette instruction ne fonctionne que si le certificat ssl a également été généré pour la version www du site. 
Le meilleur moyen de vérifier est de cliquer sur un élément du menu vers une page existante. Elle va s’afficher en https. Ensuite, dans le navigateur, enlever « https:// » et taper <entrée>. L’adresse non https entrée doit renvoyer vers l’adresse https. 

Et voilà, mon site fonctionne correctement en https !

étape 7 : forcer l’accès SSL pour l’admin

Dans wp-config.php, ajouter les lignes

/* HTTPS only for admin access and login */
define( 'FORCE_SSL_ADMIN', true );

Ainsi, personne ne pourra accéder au tableau de bord WordPress en mode non sécurisé et tous les login seront en https.

A ce stade le site est parfaitement configurer pour fonctionner de manière sécurisée.

étape 8 : régler les réseaux sociaux et autres

Ma référence est toujours l’article How to Migrate from HTTP to HTTPS – Complete Tutorial et je suis sur un site réel, auquel des réseaux sociaux font des liens, que google analytics suit et qui est paramétré dans Google Webmaster Tools.

mettre à jour les sitemaps

Avec Yoast SEO, les sitemaps sont maintenant automatiquement en https, par exemple « https://nom-de-mon-site.com/page-sitemap.xml ».

Mettre à jour le compte Google Analytics

Dans votre compte Google Analytics, il faut modifier l’url du site.

Cliquer sur l’onglet « Administration ». Dans cet onglet, on voit trois colonnes, « compte », « propriété » et « vue ».

Passer en HTTPS sur Google AnalyticsDans la colonne « propriété », cliquer sur « Paramètres de la propriété ». Modifier l’adresse du site comme sur la copie d’écran à droite puis cliquer sur « enregistrer ». Comme ça on ne perd pas l’historique de l’ancien site non sécurisé. Attention, dans le cas présent, j’ai dû régler « vue par défaut », juste en dessous à « toutes les données du site web » pour que ça fonctionne correctement (affichage « opération réussie » après avoir cliqué sur « enregistrer »).

Faire la même chose dans la colonne « vue », en cliquant sur « Paramètres de la vue » pour modifier l’adresse du site.

Dans la colonne « propriété », cliquer sur « Paramètres de la propriété », puis tout en bas, dans « Paramétrer la search console », vérifier que c’est bien le site en https qui est la cible. Cette opération relie les comptes google webmasters tools et google analytics du site.

Attention, on reçoit un message disant que l’ancien site (http) est déconnecté. Il ne faut pas en tenir compte.

créer un nouveau site sur google webmaster tools

Il semblerait que l’on soit obligé de faire ça. Dans Google Webmaster Tools, ajouter un nouveau site en cliquant sur le bouton « ajouter une propriété ». On ajoute le site https://nom-de-mon-site.com. Ensuite, on suit les instructions reçues dans un mail. En particulier, il faut sélectionner le pays cible.

Soumettre les sitemaps à Google Webmaster tools

Il faut soumettre les sitemaps à Google Webmaster tools pour le nouveau site en https. On vérifie ainsi qu’il n’y a pas d’erreurs.

 

Vérifier que les robots peuvent circuler dans le site

Dans le menu « explorer » > « explorer comme Google » de Google Webmasters Tools, cliquer sur le bouton « explorer ». Il ne doit pas y avoir d’erreur.

Il pourrait être utile de cliquer ensuite sur « envoyer pour indexation » mais je ne le fais pas…

 

Soumettre les sitemaps à d’autres moteurs de recherche

On peut les soumettre à Bing Webmaster Tools ou à Yandex (“How to Submit Your Website to Yandex Webmaster Tools“).

Autres éléments à mettre à jour

Il faudra mettre l’adresse en htpps partout où elle est en http :

  • Compte Youtube : modifier le nom de domaine associé (copie d’écran ci-dessous)
  • Campagnes Maichimp (ou autre outil marketing) : modifier l’url ;
  • page Facebook
  • compte Twitter, Pinterest, Google+,
  • liens de signature des mails, liens des pieds de page de courriers, …

Modifier le compte associé à Youtube

Et voilà !

Un site « multisite » WordPress sur OVH mutualisé

Un site « multisite » WordPress sur OVH mutualisé

WordPress est habituellement utilisé pour un seul site. C’est plus simple mais ça présente aussi des inconvénients :

  • si vous un hébergement mutualisé (Pro OVH par exemple) avec seulement 4 bases de données, vous ne pouvez pas créer plus de 4 sites.
  • Si vous gérez 4 sites, il faudra faire autant de fois les installations de WordPress, les mises à jour de WordPress et des extensions.

J’expérimente ici la création d’un site multisite à partir d’un nom de domaine « potentiel-web.com » sur un hébergement Pro mutualisé d’OVH. Ce site a déjà été créé, avec un certificat SSL « Let’s Encrypt » (voir l’article WordPress avec un SSL Let’s encrypt sur OVH mutualisé). Nous allons maintenant le rendre multisites. 

Qu’est-ce que WordPress multisite ?

Un réseau WordPress multisite, c’est un ensemble de sites internet distincts qui partagent une seule installation de WordPress. Le site WordPress.org, qui est composé de millions de sites en est un exemple. Chaque site du réseau est en fait un site virtuel, qui dispose cependant de son propre répertoire « upload » pour les médias et de ses propres tables dans la base de données.

Les extensions et thèmes sont installées au niveau de la tête de réseau mais chaque site peut les activer ou les désactiver.

Un réseau de sites peut fonctionner selon deux principes distincts :

  • en « sous-domaines » : les sites auront des url du type site1.domaine.com, site2.domaine.com ;
  • en « sous-répertoires » : les sites auront des url du type domaine.com/site1, domaine.com/site2.

A quoi ça sert ?

Un seul individu (ou entreprise) peut avoir plusieurs sites ou blogs. Ca devient vite compliqué de les gérer chacun individuellement, de les mettre à jour, d’ajouter la même extension dans chacun. On peut donc utiliser la fonctionnalité multi-sites de WordPress pour n’avoir qu’une seule installation de WordPress, des extensions et des thèmes pour plusieurs sites distincts.

Un développeur, ou une agence web, pourra aussi avoir un réseau de sites de clients installés et administrés d’un seul endroit. Les clients peuvent avoir un accès administrateur à leur propre site s’ils le souhaitent. L’avantage est qu’ils ne pourront pas ajouter des thèmes ou des extensions.

On peut également avoir un réseau dans lequel des gens peuvent ajouter leur propre site, gratuitement ou moyennant paiement.

Dans tous les cas, une extension spécialisée permet le « domain mapping » et autorise l’utilisation de noms de domaines différents pour chaque site du réseau.

étape 1 : régler WordPress

C’est WordPress qui gérera les sous-domaines, pas notre espace client OVH. Je ne crée donc pas de sous-domaine sur OVH.

Pour cette étape, je m’inspire des tutoriels suivants :

Activation du réseau: dans wp-config.php

Ajouter les deux lignes suivantes dans wp-config.php , juste avant la ligne « /* C’est tout, ne touchez pas à ce qui suit ! Bon blogging ! */ » :

/* Multisite */
define('WP_ALLOW_MULTISITE', true);

Créer le réseau, dans WordPress

Dans le menu « outils » du tableau de bord WordPress, il y a maintenant un menu « création du réseau ». Les extensions éventuellement présentes doivent avoir été désactivées avant.

Régler et activité un WordPress Multisite

Il faut (1) choisir entre le mode « sous-domaines » et le mode « sous-répertoires ». J’ai choisi « sous-domaines » car j’ai le sentiment que c’est mieux adapté, mais je ne suis pas certaine d’avoir tout compris. J’ai lu que c’était compliqué de transformer un site existant en mode multisite avec sous-répertoires car les anciennes url ne vont plus fonctionner correctement. Comme ces essai est un préalable à la transformation d’un site existant, il m’a semblé plus simple d’essayer tout de suite en sous-domaines.

Il faut également indiquer (2) le titre du réseau et (3) l’adresse email de l’administrateur du réseau (le super administrateur).

Ensuite, on clique sur « installer ». Pour cet essai, je pars d’un site vide, mais évidemment, si on part d’un site existant, il faut impérativement sauvegarder la base de données et les fichiers avant de réaliser cette modification.

Après avoir cliqué sur « installer », nous arrivons à une page assez effrayante…

Avant d'activer un WordPress Multisite

Dans l’écran qui s’affiche, on voit trois éléments :

  1. Une alerte « Attention ! L’enregistrement DNS générique (joker) peut ne pas être configuré correctement ! ». Pour l’instant, nous ne nous en préoccupons pas.
  2. du code qu’il faudra ajouter à  wp-config.php
  3. du code qu’il faudra ajouter au fichier .htaccess

Modifier wp-config.php

Je copie puis colle le contenu indiqué dans l’écran WordPress dans mon fichier  wp-config.php , sous la ligne contenant define(‘WP_ALLOW_MULTISITE’, true);

Modifier le fichier .htaccess

Le nouveau contenu de ce fichier est maintenant :

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]

# add a trailing slash to /wp-admin
RewriteRule ^wp-admin$ wp-admin/ [R=301,L]

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^(wp-(content|admin|includes).*) $1 [L]
RewriteRule ^(.*\.php)$ $1 [L]
RewriteRule . index.php [L]
</IfModule>

# END WordPress

Se reconnecter

Une fois les modifications faites, j’ai cliqué sur « reconnecter » en bas de la page WordPress qui contenait les instructions.

Mon tableau de bord WordPress contient maintenant un nouveau menu « mes sites ».

Le menu "mes sites" dans le tableau de bord WordPress Multisite

Créer un nouveau site dans le réseau

Attention : si on utilise un certificat SSL pour le site principal, voire pour les sites du réseau, il y a des spécificités. Voir plus bas le chapitre « Spécificités du SSL (https) »

Nous allons créer un sous-domaine test1.potentiel-web.com.

Dans le tableau de bord WordPress

Lorsque je me connecte à potentiel-web.com/wp-admin, j’ai une interface WordPress qui paraît identique à celle d’un site unique classique. Mais il y a des différences :

  • sous le menu « tableau de bord », il y a maintenant un menu « mes sites », comme vu précédemment.
  • Mais surtout, maintenant si je place ma souris tout en haut sur le titre du site, j’ai un sous-menu « admin du réseau » qui apparaît.

Menu "admin du réseau de WordPress mutisite

Si je vais dans le sous-menu « Sites », je peux créer, supprimer, modifier des sites du réseau, comme si c’était des articles ou des pages !

Je crée donc le site test1.potentiel-web.com :

Création d'un nouveau site dans un WordPress mutisite

Après avoir cliqué sur « ajouter un site », ce nouveau site apparaît dans la liste de mes sites. J’ai reçu aussi plusieurs mail :

  • des mails à mon adresse donnée lorsque j’ai créé le multisite, mon adresse de « super admin » !
  • des mails à l’adresse que je viens de donner comme administrateur de test1.potentiel-web.com. Ces mails m’informent de la création du site et indiquent où aller pour configurer mon mot de passe.

Mais si je met « test1.potentiel-web.com » dans un navigateur , j’obtiens une page d’erreur « Impossible de trouver l’adresse DNS du serveur test1.potentiel-web.com ». Il faut que je crée le nom de domaine dans OVH. 

Création du sous-domaine dans l’espace client OVH

dans l’espace client d’OVH. Je clique sur l’hébergement auquel est rattaché mon site multisite puis sur l’onglet « multisite ». Ensuite je clique sur le bouton « ajouter un domaine ou un sous-domaine ».

OVH ajouter un sous-domaine à un WordPress multisite - 2

Dans l’étape 2, il n’y a aucune raison de créer également le sous-domaine avec le www. Je ne le fais donc pas.

Le répertoire cible doit être celui du domaine principal du réseau de sites (multi-test pour moi – la copie d’écran ci-dessous indique www mais c’est multi-test qu’il faut lire, le répertoire où est installé potentiel-web.com).

Je choisis l’option SSL puisque je veux que tous mes sites soient encryptés.

Je choisis log séparé car c’est plus clair.

OVH ajouter un sous-domaine à un WordPress multisite - 3 OVH ajouter un sous-domaine à un WordPress multisite - 1

OVH affiche « La modification du ou des domaines associé(s) à votre hébergement mutualisé est en cours … » et quelques minutes plus tard, il devient possible d’accéder à http://test1.potentiel-web.com. Il n’est toujours pas possible d’accéder à  https://test1.potentiel-web.com (la version encryptée) car je n’ai pas encore régénéré le certificat ssl.

Accéder au nouveau site et le modifier

Si je me connecte au nouveau site test1 (j’ai été créée comme administrateur en tant que « test1 »), je perds ma connexion de super administrateur, ce qui est normal puisque j’ai indiqué un autre email que celui du super administrateur comme administrateur du site test1…

En tant qu’administrateur de test1.potentiel-web.com, je peux faire tout ce que peux faire un administrateur d’un site unique, sauf installer des thèmes ou des extensions. Ces installations, le super administrateur est seul habilité à les réaliser.

Modifier les utilisateurs en tant que super administrateur

Dans le menu « admin du réseau », sous-menu « Sites », je peux modifier les sites du réseau.

Si je clique sur « modifier » pour le site test1, j’ai accès à 4 onglets, dont l’onglet utilisateurs. Je peux ajouter un utilisateur existant ou un nouvel utilisateur.

J’y ajoute l’utilisateur que je suis en tant que super administrateur. Maintenant avec un seul utilisateur, je peux aussi bien agir dans le site test1, que dans le site principal ou administrer le réseau de site.

Installer des thèmes et extensions en tant que super administrateur

En tant que super administrateur, je peux installer un nouveau thème ou une nouvelle extension.

Installer un nouveau thème

soit avec « ajouter », dans le menu « admin du réseau » > « thèmes », pour un thème présent dans les thèmes de wordpress.org ou par ajout de fichiers dans le répertoire /racine/wp-content/themes  comme dans un site unique.

Activation d’un nouveau thème

Dans la liste des thèmes, chacun peut être activé ou désactivé pour le réseau dans le menu « admin du réseau » > « thèmes ».

Si je souhaite qu’un thème soit disponible pour tous les sites du réseau : je clique sur « activer pour le réseau ».

Si au contraire je ne souhaite mettre ce thème à disposition que de certains site, je vais dans le menu « admin du réseau » > « sites » et, pour chaque site, je clique sur modifier et je vais dans l’onglet thème.

Ainsi j’ai installé le thème stargazer et je l’ai activé pour tous les sites. Ensuite j’ai installé un thème enfant de stargazer (par transfert de fichiers) et je l’ai activé dans le site « test1 » seulement.

Installer une extension

dans le menu « admin du réseau » > « extensions », je peux ajouter une extension avec le bouton « ajouter » pour pour une extension présente dans les extensions de wordpress.org ou par ajout de fichiers dans le répertoire /racine/wp-content/plugins  comme dans un site unique.

Activation d’une extension

Attention, une extension qui ajoute des tables dans WordPress doit être compatible multisite pour fonctionner correctement (voir l’article Make WordPress Plugin compatible with Multisite). Si une extension n’est pas compatible multisite, on pourra l’activer dans chaque site du réseau mais pas pour tout le réseau.

J’installe l’extension « Yoast SEO » qui dit être compatible multisites et « HMS Testimonials » qui est ancienne et n’indique pas de compatibilité multisite, tout en créant des tables.

Lorsque j’active ces deux extensions sur le réseau, dans le menu « admin du réseau » > « extensions », je n’ai aucun message d’erreur.

Et lorsque je vais voir le contenu de la base de données du réseau de site, elle contient autant de tables que de sites, tous avec un préfixe du genre prefixe_nom_table : prefixe tout court pour le site principal, prefixe_1 pour le premier site ajouté, etc… Et HMS Testimonials a ajouté plusieurs tables pour chaque site. Il n’y a donc pas de souci.

Spécificités du SSL (https)

Comme le site principal est crypté, les liens vers les autres sites sont en https. Le certificat SSL doit donc les inclure : J’ai ajouté un deuxième site, test2.potentiel-web.com, j’ai attendu deux heures comme indiqué par OVH puis j’ai régénéré le certificat ssl sur mon espace client OVH.

La régénération est assez longue mais pendant ce temps les sites qui étaient déjà encryptés conservent leurs certificats SSL et fonctionnent donc correctement.

Au bout d’une dizaine de minutes le certificat est régénéré. Au départ, j’ai un problème car le site https://test1.potentiel-web.com est annoncé comme non sécurisé…

La solution : retourner dans le menu « admin du réseau » > « sites » et modifier l’adresse du site de destination. C’était http://test1.potentiel-web.com. J’ajoute un s à la fin de http, et ça y est c’est bon !

Il faut également effectuer des redirections lorsqu’une url est appelée sans rien devant ou en http. Mais on ne doit pas rediriger une url contenant à la fin wp-admin.*, wp-config.* ou wp-includes.*

Donc on modifie .htacess pour que (merci aux auteurs des réponses à cette question sur Stackoverflow) :

  • quand le port est 80 (si la connexion était sécurisée elle utiliserait le port 443. Quand elle utilise le port 80, elle est en http)
  • ET l’url appelée (%{REQUEST_URI} ) n’est ni wp-content, ni wp-admin, ni wp-includes suivi de n’importe quoi,
  • ALORS on redirige vers la version https de l’url.
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]

# add a trailing slash to /wp-admin
RewriteRule ^wp-admin$ wp-admin/ [R=301,L]

# direct everything to https
RewriteCond %{SERVER_PORT} 80
RewriteCond %{REQUEST_URI} !(wp-(content|admin|includes).*)$ 
RewriteRule ^(.*)$ https://%{SERVER_NAME}/$1 [R=301,L]

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^(wp-(content|admin|includes).*) $1 [L]
RewriteRule ^(.*\.php)$ $1 [L]
RewriteRule . index.php [L]
</IfModule>

# END WordPress

Noter qu’il faut parfois vider le cache du navigateur pour que la réécriture des url sans http se fasse correctement… J’ai Chrome réglé pour conserver les historiques et Firefox qui ne les conserve pas. Je teste donc dans Firefox puis quand ça fonctionne, j’efface les données de navigation de moins d’une heure dans chrome, en ne sélectionnant que « cookies et autres données » et « images en fichiers en cache ».

et dans wp-config.php , il est préférable d’ajouter une ligne qui force l’usage du SSL pour l’administration :

/* HTTPS only for admin access */
define( 'FORCE_SSL_ADMIN', true );

Et maintenant ?

J’ai donc réussi à créer un réseau de sites avec la fonctionnalité multi sites de WordPress. Ca me semble pratique. Je vais maintenant devoir migrer mes sites existants sur un réseau, apprendre à bien utiliser les réseaux multisite et surtout à les sauvegarder et restaurer si nécessaire…

Je prévois de faire les articles suivants pour compléter mon apprentissage des réseaux multisites WordPress :

Ces sujets feront l’objet de plusieurs articles pour cette série .

Finaliser notre extension comme base pour d’autres développements

Finaliser notre extension comme base pour d’autres développements

Dans les articles précédents de cette série (), nousavons construit les fondements d’une extension correcte, avec une page de réglages qui fonctionne correctement. Je veux maintenant modifier trois détails pour que cette extension serve plus facilement de base à d’autres extension :

  1. si un champs est de type « url » ou « email », il faudra qu’il y ait validation que les valeurs saisies sont bien soit des url soit des adresses mail ;
  2. Ajouter un champs de type « date » ;
  3. Les données à modifier pour adapter les bases de l’extension devraient être dans un fichier distinct, avec des commentaires pour faciliter l’adaptation par le développeur.

Nous allons réaliser toutes ces opérations, en commençant par la dernière.

De quoi partons-nous ?

A ce stade notre extension correspond au contenu de ce fichier zip : clea-add-button V0.2 (zip), telle qu’elle a été construite dans le précédent article de la série .

déplacer les données variables dans un autre fichier

Dans clea-add-button.php , ajouter les lignes suivantes :

// the sections and fields data for the settings page. 
require_once CLEA_ADD_BUTTON_DIR_PATH . 'admin/clea-add-button-admin-settings.php';

On dit donc au script principal de notre extension qu’il devra utiliser le script contenu dans /admin/clea-add-button-admin-settings.php . Ce script contient deux fonctions qui retournent respectivement le contenu des arrays de définition des sections et des champs. J’y ai simplement copié les deux fonctions clea_add_button_settings_sections_val()  et  clea_add_button_settings_fields_val() qui étaient auparavant à la fin du fichier clea-add-button-settings-page.php .

Attention : le fichier doit être encodé en utf-8 avant d’y écrire des caractères accentués en français par exemple. Sinon les texte sont affichés avec des � à la place des caractères « spéciaux ».

Ajouter un champ de type date

Je me suis inspirée de cette question sur stackoverflow.

Dans clea-add-button-admin-settings.php  , j’ai ajouté un cinquième champs dans la section 1, avec les éléments suivants :

array(
	'field_id' 		=> 'field-1-5', 
	'label'			=> __( 'Field 5 : date picker', 'clea-add-button' ), 
	'field_callbk'	=> 'clea_add_button_settings_field_callback', 
	'menu_slug'		=> 'my-plugin', 
	'section_name'	=> 'section-1',
	'type'			=> 'date-picker',
	'helper'		=> __( 'jj/mm/aaaa', 'clea-presentation' ),
	'default'		=> '',
),

Maintenant dans clea-add-button-settings-page.php , il faut que je dise comment traiter les champs de type « date-picker ». Dans la fonction clea_add_button_settings_field_callback( $arguments  ) , j’ajoute un cas « date-picker » :

case 'date-picker' : 
  printf( '<input type="date" id="%3$s" name="%2$s" value="%1$s" class="datepicker" />', sanitize_text_field( $value ), $name, $field, $arguments['default'] ) ;
  break ;

A ma grande surprise, je n’ai même pas eu à ajouter quoi que ce soit d’autre. Je m’attendais pourtant à devoir charger jquery-ui-datepicker pour cette page et aussi à devoir créer une fonction…

un "date picker" dans les réglages d'une extension WordPress

Si on veut ajouter des options, on pourra s’inspirer des deux articles suivants :

Valider des champs de type « url » ou « email »

On peut avoir à demander une adresse mail ou le lien d’un site internet. Dans ce cas, la validation et la sanitation du contenu du champs ne se font pas de la même manière que pour un simple texte.

La validation des champs est réalisée lorsqu’on affiche les champs. Jusqu’à présent l’utilisateur n’était pas informé s’il entrait une valeur non valide. C’est pourtant indispensable. Nous allons utiliser la fonction

 

La sanitation et l’affichage sont faits dans clea-add-button-settings-page.php , par le biais de la fonction clea_add_button_settings_field_callback( $arguments  ) .

Commençons par ajouter deux nouveaux champs, de type ‘url’ et ’email’ dans la section 1, définis dans clea-add-button-admin-settings.php :

array(
	'field_id' 		=> 'field-1-6', 
	'label'			=> __( 'Field 6 : email', 'clea-add-button' ), 
	'field_callbk'	=> 'clea_add_button_settings_field_callback', 
	'menu_slug'		=> 'my-plugin', 
	'section_name'	=> 'section-1',
	'type'			=> 'email',
	'helper'		=> __( 'aaaa@rrrr.ddd', 'clea-presentation' ),
	'default'		=> '',
),
array(
	'field_id' 		=> 'field-1-7', 
	'label'			=> __( 'Field 7 : url', 'clea-add-button' ), 
	'field_callbk'	=> 'clea_add_button_settings_field_callback', 
	'menu_slug'		=> 'my-plugin', 
	'section_name'	=> 'section-1',
	'type'			=> 'url',
	'helper'		=> __( 'http:// ou https://', 'clea-presentation' ),
	'default'		=> '',
),

Il faut maintenant que nous les validions, que les « nettoyons » (sanitation) et que nous les affichions en sécurité. Tout se fait dans une fonction que l’on appelle lors de l’étape « register_setting().

L’article qui m’a mis sur la bonne voie est « The WordPress Settings API« , de Konstantin Kovshenin.

Dans le fichier clea-add-button-settings-page.php , modifier la ligne qui réalise le « register_settings() » pour qu’elle appelle une nouvelle fonction :

register_setting( 'my-settings-group', 'my-plugin-settings', 'clea_add_button_sanitize_validate' ) ;

Et créer ensuite cette fonction :

function clea_add_button_settings_validate_and_sanitize( $input ) {

	$output = (array) get_option( 'my-plugin-settings' );
	
	// test the email in  'field-1-6'
	if ( is_email( $input['field-1-6'] ) ) {
		
		$output['field-1-6'] = $input['field-1-6'];

	} else {
		
		add_settings_error( 'my-plugin-settings', 'invalid-email', 'You have entered an invalid e-mail address.' );
	}

	// if ( $some_condition == $input['field_1_1'] )
		
	return $output;
}

Cette fonction va vérifier que le contenu du champ ‘field-1-6’ est bien un email. Si ce n’est pas le cas, une erreur s’affichera.

Ensuite, pour afficher le champs email, dans la fonction clea_add_button_settings_field_callback( $arguments  ) , on ajoute le cas « email » :

case 'email' :
	
	printf( '<input type="text" id="%3$s" name="%2$s" value="%1$s" />', sanitize_email( $value ), $name, $field );
	break ;

Noter que l’affichage se fait en utilisant sanitize_email().

Si je tape une adresse email invalide (par exemple « rgdfghhr »), un message « You have entered an invalid e-mail address. » s’affiche en haut de la page de réglages lorsque je clique sur « enregistrer les modifications ».

Ca fonctionne mais le gros inconvénient est qu’il faudra aller modifier cette fonction à chaque fois qu’on change le nom ou le type d’un champ. Par exemple, si je décide que le champ ‘field-1-6′ s’appellera ’email’, il faudra que j’aille changer le contenu de la fonction clea_add_button_settings_validate_and_sanitize.

Il faut donc que cette sanitation et validation se fasse sans se référer explicitement à un nom de champ. Pour celà, on va utiliser l’array de définition des champs, comme on a fait dans la fonction clea_add_button_admin_init().

function clea_add_button_settings_validate_and_sanitize( $input ) {

	$output = (array) get_option( 'my-plugin-settings' );

	$set_fields = clea_add_button_settings_fields_val() ;
	$types = array() ;
	// create an array with field names and field types
	foreach ( $set_fields as $fields ) {

		foreach( $fields as $field ){

			$types[ $field['field_id'] ] = $field['type'] ;

		}

	}	

	// now validate and sanitize each field
	foreach ( $types as $key => $type ) {
		

		switch( $type ){
			
			case 'wysiwig' :
				$output[ $key ] = wp_kses_post( $input[ $key ] ) ;
				break ;	
			case 'email' :
				if ( is_email( $input[ $key ] ) ) {
					
					$output[ $key ] = $input[ $key ];

				} else {
					
					$message = __( 'You have entered an invalid e-mail address in : ', 'clea-add-button' ) ;
					$message .= $key ;
					add_settings_error( 'my-plugin-settings', 'invalid-email', $message  );
				}
				break ;
			default : 
				$output[ $key ] = sanitize_text_field( $input[ $key ] ) ;
				
		}

		
	}
		
	return $output;
}

Au départ, je crée un array avec tous les noms de champs et leurs type, tels que définis dans la fonction clea_add_button_settings_fields_val() . Ensuite, pour chaque élément de cet array, nous faisons une sanitation et une validation différente selon son type.

Mettre à jour le numéro de version et le readme

Dans le fichier clea-add-button.php , j’ai modifié @version 0.3.0 . L’extension est maintenant en version 0.3.

Dans le README.md, j’ai ajouté la version 0.3 dans le « changelog » :

== Changelog ==

= 0.3 =
* the definition of sections and fields to display on the settings page is now in /admin/clea-add-button-admin-settings.php
* 3 new types of fields may be processed : date-picker, email and url
* validation and sanitation of user inputs is done and the user gets a notice in case of a bad email

Cette version 0.3 est maintenant sur GitHub et téléchargeable (zip) : clea-add-button V0-3 (Zip).

L’extension de base finale, clea-plugin-boilerplate est passée en version 1 et disponible ici sur github. Elle est identique à clea-add-button sauf que les noms de fichiers, de fonctions et de variables ont été changés et qu’un fichier pot a été généré pour les traductions.

Et maintenant

Notre page de réglages fonctionne, quel que soit le type de champs que l’on souhaite afficher. Nous disposons maintenant d’une extension de base, correctement codée, que l’on peut utiliser comme base (boilerplate) n’importe quelle extension. C’est la fin de cette série, .

WordPress avec un SSL Let’s encrypt sur OVH mutualisé

WordPress avec un SSL Let’s encrypt sur OVH mutualisé

Les internautes, et les moteurs de recherche, attachent de plus en plus d’importance au petit cadenas vert qui indique qu’un site internet est sécurisé. Lorsque le site est sécurisé, les données bancaires, les données personnelles ou les mots de passe sont cryptés. Les données sont donc mieux protégées.

J’expérimente ici la création d’un site « https://potentiel-web.com » sur un hébergement Pro mutualisé d’OVH. Je vais utiliser un certificat gratuit « Let’s Encrypt », disponible depuis quelques mois sur OVH.

étape 0 : dans l’espace client OVH

Il faut que j’associe le domaine potentiel-web.com à un hébergement. Les éléments qui suivent sont décrits avec plus de détails dans l’article Hébergement Pro OVH avec plusieurs sites.

Dans l’hébergement cible, choisir l’onglet « multisite » et cliquer sur le bouton « Ajouter un domaine ou sous domaine ».

J’ajoute le domaine potentiel-web.com, déjà enregistré chez OVH et dans le second panneau de paramétrages, je choisis  « créer également le sous domaine www.potentiel-web.com » et je coche l’option « SSL ». Dans le dernier panneau, je choisis « configuration automatique (recommandé) » et je valide.

Mon espace client affiche successivement « La modification du ou des domaines associé(s) à votre hébergement mutualisé est en cours … » puis « La modification du ou des domaines associé(s) à votre hébergement mutualisé a été effectuée avec succès. ».

Dans la liste des domaines de l’onglet multisites, je vois maintenant apparaître les deux sites (avec et sans www) :

Ajout d'un domaine à un hébergement mutualisé OVH

Pour l’instant, je ne m’occupe pas du SSL en orange.

étape 1 : créer un site WordPress classique

Créer la base de données associée

dans l’espace client OVH, partie hébergement, je vais dans l’onglet « base de données » et je clique sur le bouton « créer une base de données ».

Pour le mot de passe, j’utilise le générateur de mot de passe de LastPass, en mode A-Z, a-z et 0-9. La base s’installe.

Une fois que j’ai reçu un mail m’informant de la création de la base, je peux continuer.

Installer le module WordPress

Toujours dans l’espace client OVH, partie hébergement, je vais dans l’onglet « modules en 1 clic » pour installer WordPress.

Je clique sur le bouton « ajouter un module ». Je choisis WordPress et potentiel-web.com comme domaine associé. Je clique sur « installer en mode avancé ».

Je reçois un mail d’OVH, avec le nom d’utilisateur et le mot de passe associé, lorsque le module est installé.

Accéder à WordPress

Je vérifie que j’accède au site http://potentiel-web.com et au tableau de bord WordPress (http://potentiel-web.com/wp-admin, avec le nom d’utilisateur et le mot de passe défini lors de l’installation du module).

J’en profite pour créer un autre utilisateur administrateur, dont le mot de passe n’aura pas été transmis par mail. Evidemment je supprime ensuite le précédent utilisateur.

étape 2 : gestion du certificat SSL

A ce stade, si je tape https://potentiel-web.com/ pour accéder à mon site, mon navigateur (chrome) m’affiche un message d’alerte.

Alerte, votre connexion n'est pas privée

Par contre, http://potentiel-web.com/ s’affiche correctement. C’est normal puisque je n’ai pas « généré de certificat SSL » lors de l’étape 0. Je ne l’ai pas fait car lorsque j’ai essayé, l’espace client d’OVH m’a affiché un message disant que si j’avais crée un nouveau site depuis moins de deux heures, le certificat ne fonctionnerait pas.

Dans mon espace client OVH, je clique sur l’hébergement de potentiel-web.com et j’accède à l’onglet « informations générales ».

OVH régénérer le certificat SSL d'un hébergement

Je clique sur « régénérer le certificat SSL ». Selon le guide OVH « Les certificats SSL sur les hébergements web« , il faut maintenant attendre le protocole HTTPS quelques heures, « le temps de le déployer sur l’ensemble de l’infrastructure ».

Nota : pour un site existant, à transformer en https, le processus est légèrement différent, et également décrit dans le guide OVH ci-dessus.

Quelques heures plus tard, le site https://potentiel-web.com/ s’affiche correctement :

Un site WordPress en https, avec un certificat SSL de "Let's encrypt"

Redirection du http vers le https

Maintenant que le site fonctionne en https, il faut que j’élimine toute possibilité d’accéder en http :

  • pour éviter les problèmes de « duplicate contents » puisque les robots des moteurs de recherche considèrent les sites en http comme distincts des sites en https.
  • pour éviter aussi qu’un internaute se retrouve sur la version non sécurisée.

Pour y arriver, j’ai trois choses à faire :

  1. régler le nom du site dans le tableau de bord WordPress ;
  2. Modifier wp-config.php pour interdire l’accès au tableau de bord hors https
  3. rediriger vers l’url en https avec .htaccess

Modifier le nom du site

Dans le tableau de bord WordPress, menu « Réglages »  > « Général », régler « Adresse web de WordPress (URL) » et « Adresse web du site (URL) » pour qu’elles démarrent avec https et pas http.

Modifier wp-config.php

Modifier wp-config.php en y ajoutant :

/* HTTPS only for admin access and login */
define( 'FORCE_SSL_ADMIN', true );
define('FORCE_SSL_LOGIN', true);

Modifier le .htaccess

Ajouter :

# direct everything to https
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://%{SERVER_NAME}/$1 [R=301,L]

Il n’y a plus qu’à attendre un peu et ce sera bon ! Dans un navigateur, que l’on tape potentiel-web.com ou http://potentiel-web.com, on arrive dans tous les cas à https://potentiel-web.com.

Et maintenant ?

Je pense que la transformation d’un site existant doit être un peu différente, avec des problèmes spécifiques (cf le guide OVH, « Eviter les pièges du SSL avec mon site web« ). Il va donc falloir que je fasses des essais. Ce sera l’objet d’un autre article.

Un « color picker » dans les réglages de notre extension WordPress

Un « color picker » dans les réglages de notre extension WordPress

Nous allons améliorer la page de réglage de notre extension WordPress, en y ajoutant un champ de type « color picker » et en affichant les données complémentaires définies avec les champs. Dans les articles précédents de cette série (), nous avons progressivement construit l’extension et sa page de réglage. A la fin du précédent article, l’extension correspondait au contenu de ce fichier zip : clea-add-button avec éditeur wp_editor (zip).

Que voulons-nous faire ?

Notre page de réglages est capable d’afficher tous les types de champs sauf les choix de couleur. Nous voulons donc pouvoir choisir une couleur et même définir son opacité. Et pour simplifier la vie de l’administrateur du site, il faut qu’on lui dise quelles sont les couleurs utilisées par son thème, en les intégrant dans une palette sous le color picker.

Par ailleurs, notre page de réglages devra afficher les éléments complémentaires définis pour chaque champs, tels que « helper » qui contient un texte d’aide complémentaire.

Identifier les couleurs utilisées par le site

Les paramètres du thème courant sont stockés par WordPress et récupérables avec la fonction get_theme_mods(). Cette fonction nous donne un array contenant tous les paramètres, dont certains sont des couleurs.

Nous lisons donc l’array et pour chaque valeur, nous regardons s’il s’agit d’une couleur avec la fonction sanitize_hex_color_no_hash(). Cette fonction renvoie « NULL » si elle ne trouve pas un élément en hexadécimal à 3 ou 6 caractères. A chaque fois qu’elle trouve un élément non NULL, on le place dans l’array qui sera retourné pour former notre palette de couleurs.

/**********************************************************************

* find the colors used in the website's theme

**********************************************************************/
function clea_presentation_get_current_colors() {

	// to get all the current theme data in an array
	$mods = get_theme_mods();

	$color = array() ;
	
	foreach ( $mods as $key => $values ) {
		
		if ( !is_array( $values ) ) {
			
			if ( is_string( $values ) && trim( $values ) != '' ) {
				
				$hex = sanitize_hex_color_no_hash( $values ) ;
				
				if ( trim( $hex ) != '' ) {
					
					$color[ $key ] = $hex ;

				}

			}
		} 
	}

	// remove duplicate colors
	$current_colors = array_unique( $current_colors ) ;
	
	return $color ;
	
}

Pour vérifier que c’est une bonne solution, , nous ajoutons le code suivant à la fonction clea_add_button_options_page()   :

$colors = clea_add_button_get_current_colors() ;
echo "<hr /><p>Arguments</p><pre>";
print_r( $colors ) ;	
echo "</pre><hr />";

Ce code va afficher l’array de couleurs en bas de la page d’options :

Array
(
   [background_color] => ffffff
   [color_palette_primary] => 4c858d
   [color_palette_tertiary] => 423432
   [color_palette_dark_font] => ed693b
)

Nous disposons donc des informations pour constituer notre palette par défaut.

Afficher des champs « color picker »

Nous allons utiliser le « Alpha Color Picker for WordPress » développé par Braad Martin. Pour comprendre comment l’intégrer, j’ai utilisé à la fois les explications de Braad Martin et Add an Alpha RGBa Color Picker to a WordPress Plugin Input Field.

Le code pour afficher le color picker

On ajoute le cas ‘color’ comme suit :

case 'color' :

	// get the colors used by the theme
	$current_colors = clea_presentation_get_current_colors() ;
	$data_palette = "";
	
	// the color palette must be a string with colors and | separator
	// "#222|#444|#00CC22|rgba(72,168,42,0.4)" would be ok
	foreach ( $current_colors as $color ) {
		
		$data_palette .= $color . '|' ;
		
	}
	
	$data_palette = rtrim( $data_palette, '|' ) ;
	
	
	// uses https://github.com/BraadMartin/components/tree/master/alpha-color-picker
	printf( '<input type="text" class="alpha-color-picker" name="%2$s" value="%1$s" data-palette="%5$s" data-default-color="%4$s" data-show-opacity="true" />', sanitize_text_field( $value ), $name, $field, $arguments['default'], $data_palette  ) ;
	break ;	

A ce stade, celà affiche un champs de type ‘text’ avec à l’intérieur la couleur par défaut définie dans le champs. Il nous faut maintenant ajouter la feuille de style et le programme javascript conçus par le créateur de l’Alpha color Picker et un petit script en JQuery.

Les compléments à intégrer dans notre extension

Dans le répertoire « /admin » du plugin, créer les sous-répertoires « /css  » et « /js « .

Télécharger le fichier zip du dépôt « components » de Braad Martin ici sur un PC. Décompresser le fichier zip puis dans le sous-répertoire « alpha-color-picker » copier alpha-color-picker.css   et alpha-color-picker.js  respectivement dans les répertoires /admin/css  et /admin/js  de l’extension.

Les fichiers à créer

Nous devons créer deux fichiers :

  • un fichier (clea-add-button-color-trigger.js par exemple) qui contiendra le JQuery nécessaire à l’affichage
  • un fichier (clea-add-button-admin-enqueue.php par exemple) qui sera appelé par le fichier principal de l’extension et qui chargera la feuille de style et les scripts JavaScript nécessaires.

Le fichier /admin/js/clea-add-button-color-trigger.js  contient :

// source  https://github.com/BraadMartin/components/tree/master/alpha-color-picker
jQuery( document ).ready( function( $ ) {
    $( 'input.alpha-color-picker' ).alphaColorPicker();
});

Quant au fichier /admin/js/clea-add-button-admin-enqueue.php , il contient

add_action( 'admin_enqueue_scripts',  'clea_add_button_admin_enqueue_scripts' );


function clea_add_button_admin_enqueue_scripts( $hook ) {
	

	// to find the right name, go to the settings page and inspect it
	// the name is somewhere in the <body class="">
	// it will always begin with settings_page_
	if( 'settings_page_my-plugin' != $hook ) { 
	
        // echo "not the right page, this is : " ;
		// echo $hook ;
		return;
		
    }

    // for the alpha color picker
    // source : https://github.com/BraadMartin/components/tree/master/alpha-color-picker
    wp_enqueue_style(
        'alpha-color-picker',
        CLEA_ADD_BUTTON_DIR_URL . '/admin/css/alpha-color-picker.css', 
        array( 'wp-color-picker' ) // You must include these here.
    );

	wp_enqueue_script(
        'alpha-color-picker',
        CLEA_ADD_BUTTON_DIR_URL . '/admin/js/alpha-color-picker.js', 
        array( 'jquery', 'wp-color-picker' ), // You must include these here.
        null,
        true
    );
	
    // This is the JS file that will contain the trigger script.
    // Set alpha-color-picker as a dependency here.
    wp_enqueue_script(
        'clea-add-button-admin-color-js',
        CLEA_ADD_BUTTON_DIR_URL . '/admin/js/clea-add-button-color-trigger.js', 
        array( 'alpha-color-picker' ),
        null,
        true
    );
	
}

La condition if( ‘settings_page_my-plugin’ != $hook ) permet de ne pas charger le style et le JavaScript si on n’est pas sur la page d’options de notre extension.

Enfin, dans clea-add-button.php , nous ajoutons la ligne qui démarrera clea-add-button-admin-enqueue.php   :

// load styles and scripts for the admin
require_once CLEA_ADD_BUTTON_DIR_PATH . 'admin/clea-add-button-admin-enqueue.php';

le résultat

Notre page d’option affiche maintenant la couleur par défaut sous une forme différente :

Le champ "color" affiche bien une couleur maintenant.

Le champ « color » affiche bien une couleur maintenant.

Si on clique sur la couleur, un « color picker » s’ouvre. Il affiche la couleur par défaut définie dans le champ 3. On observe qu’il y a une palette de couleur en dessous, qui correspond effectivement aux couleurs du thème sur lequel j’essaie cette extension. Et en dessous, on voit une barre qui permet de gérer la transparence de la couleur choisie.

Le champ "color" affiche un "color picker" complet.

Le champ « color » affiche un « color picker » complet.

Ici nous sélectionnons la couleur orange du thème et nous demandons à ce que sa transparence soit 71%.

Choix d'une couleur de la palette puis réglage de la transparence

Choix d’une couleur de la palette puis réglage de la transparence

Ca fonctionne parfaitement et la nouvelle couleur s’enregistre correctement.

Afficher les informations complémentaires

Chaque champ affiché dans notre page d’options est défini par un array :

array(
	'field_id' 		=> 'field-2-3', 
	'label'			=> __( 'Field three : color', 'clea-add-button' ), 
	'field_callbk'	        => 'clea_add_button_settings_field_callback', 
	'menu_slug'		=> 'my-plugin', 
	'section_name'	        => 'section-2',
	'type'			=> 'color',
	'helper'		=> __( 'help 2-3', 'clea-presentation' ),
	'default'		=> 'rgba(0,0,0,0.85)'			
)

Nous utilisons toutes les clés de cet array sauf deux (‘label’ et ‘helper’). Ces deux clés contiennent respectivement le texte à afficher systématiquement pour expliciter ce qu’il faut faire et un texte d’aide complémentaire.

Pour l’afficher, avant le champs à remplir, j’ajoute le code suivant dans la fonction clea_add_button_settings_field_callback( $arguments  )  :

// If there is a help text and / or description
printf( '<span class="field_desc">' ) ;

if( isset( $arguments['helper'] ) && $helper = $arguments['helper'] ){
	printf( '<img src="%1$s/images/question-mark.png" class="alignleft" id="helper" alt="help" title="%2$s" data-pin-nopin="true">',CLEA_ADD_BUTTON_DIR_URL, $helper ) ;
}

// If there is a description
if( isset( $arguments['label'] ) && $description = $arguments['label'] ){
	printf( ' %s', $description ); // Show it
}

printf( '</span>' ) ;

La condition if( isset( $arguments[‘helper’] ) && $helper = $arguments[‘helper’] )  vérifie que $arguments[‘helper’] est défini ET qu’il n’est pas vide.

J’ai placé un fichier question-mark.png dans le répertoire /images de l’extension.

Le résultat n’est pas très joli :

Pages d'option pas très belle....

Il faut donc que j’ajoute une feuille de style pour améliorer la page d’options.

Créer une feuille de style pour la page d’options

Dans le fichier /admin/js/clea-add-button-admin-enqueue.php , nous ajoutons une ligne pour charger la feuille de style de notre page de réglages :

// options page style
wp_enqueue_style(
	'clea-add-button-admin-style',
	CLEA_ADD_BUTTON_DIR_URL . '/admin/css/clea-add-button-admin.css'
);

et dans le fichier /admin/css/clea-add-button-admin.css

/**
 * Settings page (admin)
 */
 
span.field_desc {
	display: block;
	font-style: italic;
	margin-bottom: 5px;
}

img#helper {
	margin-right: 5px;
}

Le résultat est lisible maintenant :

Page de réglage de l'extension avec feuille de style

Et maintenant ?

A ce stade notre extension correspond au contenu de ce fichier zip : clea-add-button V0.2 (zip).

Notre page de réglages fonctionne. Il ne reste plus que quelques améliorations à apporter. Ce sera l’objet du prochain article de cette série, .

page de réglages d’une extension WordPress : formats de champs différents

page de réglages d’une extension WordPress : formats de champs différents

Notre extension a été démarrée dans les premiers articles de cette série (). A ce stade, elle affiche uniquement des champs de type « texte » et n’affiche pas le contenu des arguments supplémentaires que l’on peut ajouter au champs.

Vous pouvez récupérer l’extension à ce stade dans ce fichier zip : clea-add-button V0.1 (zip)

Nous allons donc voir maintenant comment afficher des champs de type textarea, select, checkbox, radio button, wysiwig.

Modifier la fonction de restitution des champs

Dans le fichier « /admin/clea-add-button-settings-page.php « , il faut modifier la fonction clea_add_button_settings_field_callback( $arguments  )  pour qu’elle s’adapte à différents types de champs.

Nous utilisons la commande « switch » qui choisira l’action à réaliser selon le ‘type’ de champs à restituer :

switch( $arguments['type'] ){
	
	case 'text' : 
		echo "<input type='text' name='my-plugin-settings[$field]' value='$value' />";	
		break ;
	default : 
		printf( esc_html__( 'This field is type <em>%s</em> and could not be rendered.', 'clea-add-button' ), $arguments['type']  );
}

Ca fonctionne : le champs 1-1 est restitué comme un texte mais pas les autres puisque nous n’avons pas défini leur type pour l’instant.

Il va donc falloir que je modifie l’array qui définit les champs, dans la fonction clea_add_button_settings_fields_val() . Je veux que tous les champs soient définis par un array avec la forme suivante :

array(
	'field_id' 		=> 'field-1-1', 							
	'label'			=> __( 'Field One', 'clea-add-button' ), 	
	'field_callbk'	=> 'clea_add_button_settings_field_callback', 					
	'menu_slug'		=> 'my-plugin', 							
	'section_name'	=> 'section-1',
	'type'			=> 'text',
	'helper'		=> __( 'help 1-1', 'clea-presentation' ),
	'default'		=> ''			
)

J’en profite pour créer des champs avec tous les types que je vais définir dans cet article :

  • textarea,
  • select,
  • checkbox,
  • radio,
  • wysiwig
  • color picker

Et voici maintenant le nouveau contenu de la fonction clea_add_button_settings_fields_val()  :

function clea_add_button_settings_fields_val() {

	$section_1_fields = array (
		array(
			'field_id' 		=> 'field-1-1', 							
			'label'			=> __( 'Field One', 'clea-add-button' ), 	
			'field_callbk'	=> 'clea_add_button_settings_field_callback', 					
			'menu_slug'		=> 'my-plugin', 							
			'section_name'	=> 'section-1',
			'type'			=> 'text',
			'helper'		=> __( 'help 1-1', 'clea-presentation' ),
			'default'		=> ''			
		),	
		array(
			'field_id' 		=> 'field-1-2',
			'label'			=> __( 'Field Two : textarea', 'clea-add-button' ),
			'field_callbk'	=> 'clea_add_button_settings_field_callback', 
			'menu_slug'		=> 'my-plugin', 
			'section_name'	=> 'section-1',
			'type'			=> 'textarea',
			'helper'		=> __( 'help 1-2', 'clea-presentation' ),
			'default'		=> ''			
		),
	);
	
	$section_2_fields = array (
		array(
			'field_id' 		=> 'field-2-1', 
			'label'			=> __( 'Field One : radio', 'clea-add-button' ), 
			'field_callbk'	=> 'clea_add_button_settings_field_callback', 
			'menu_slug'		=> 'my-plugin', 
			'section_name'	=> 'section-2',
			'type'			=> 'radio',
			'helper'		=> __( 'help 2-1', 'clea-presentation' ),
			'default'		=> ''						
		),
		array(
			'field_id' 		=> 'field-2-2', 
			'label'			=> __( 'Field Two : wysiwig', 'clea-add-button' ), 
			'field_callbk'	=> 'clea_add_button_settings_field_callback', 
			'menu_slug'		=> 'my-plugin', 
			'section_name'	=> 'section-2',
			'type'			=> 'wysiwig',
			'helper'		=> __( 'help 2-2', 'clea-presentation' ),
			'default'		=> ''			
		),
				array(
			'field_id' 		=> 'field-2-3', 
			'label'			=> __( 'Field three : color', 'clea-add-button' ), 
			'field_callbk'	=> 'clea_add_button_settings_field_callback', 
			'menu_slug'		=> 'my-plugin', 
			'section_name'	=> 'section-2',
			'type'			=> 'color',
			'helper'		=> __( 'help 2-3', 'clea-presentation' ),
			'default'		=> ''			
		),
	);
	

	$section_fields = array(
		'section-1'	=> $section_1_fields,
		'section-2' => $section_2_fields
	) ;	

	
	
	return $section_fields ;
}

On a défini un champs pour chaque type qu’il faudra pouvoir afficher dans notre page de réglages.

Afficher des champs « textarea »

dans la fonction clea_add_button_settings_fields_val() , à l’intérieur du « switch », j’ajoute le cas ‘textarea’.

L’affichage d’un champs de type textarea nécessite les arguments suivants :

Pour l’affichage du contenu, on utilisera quelque chose comme :

<textarea name="whatever"><?php echo esc_textarea( $description ); ?></textarea>

Noter que l’on utilise la fonction esc_textarea() pour interdire qu’un caractère présent dans la variable $description  puisse être interprété comme du HTML.

Output en sécurité avec esc_…()

Pour plus de détails, voir cette page WordPress en anglais sur la sanitation et la validation de données.

Dans notre cas, nous restituerons les valeurs de la manière suivante :

Affichage du « textarea » plus précis

Dans la référence HTML5 du W3C, la page dédiée à <textarea> indique une multitude d’arguments pour définir sa forme. Et les attributs globaux, applicables à tous les éléments HTML5 contiennent entre autre « id » et « value ». Nous allons au minimum vouloir définir « rows » et « cols », respectivement le nombre de lignes et de colonnes de la zone de texte à définir. Au final, l’expression de notre textarea sera sous la forme : 

<textarea name="whatever" id="id" rows="4" cols="80" value=""><?php echo esc_textarea( $description ); ?></textarea>

Pour tous nos champs, les attributs devront prendre une valeur liée à la définition du champs. J’utilise printf pour rendre plus simple la définition de ce qui doit être affiché.

Et voici notre fonction modifiée pour utiliser esc_attr pour le cas ‘text’ et pour afficher correctement notre zone textarea :

function clea_add_button_settings_field_callback( $arguments  ) {

	$settings = (array) get_option( 'my-plugin-settings' );
	$field = $arguments['field_id'] ;
	$value = $settings[$field] ;

	// for development only
	if ( ENABLE_DEBUG ) {
		
		echo "<hr /><pre>";
		print_r( $arguments ) ;	
		echo "</pre><hr />";
	}
	
	$name = 'my-plugin-settings['. $field . ']' ;
	
	switch( $arguments['type'] ){
		
		case 'text' : 
			printf( '<input type="text" id="%3$s" name="%2$s" value="%1$s" />', esc_attr( $value ), $name, $field );
			break ;
		case 'textarea' : 
			printf( '<textarea name="%2$s" id="%3$s" rows="4" cols="80" value="%1$s">%1$s</textarea>', esc_textarea( $value ), $name, $field );
			break ;
		
		default : 
			printf( esc_html__( 'This field is type <em>%s</em> and could not be rendered.', 'clea-add-button' ), $arguments['type']  );
	}
}

A ce stade, notre page de réglages affiche :

Affichage correct d'un champs text et d'un champs textarea

Affichage correct d’un champs text et d’un champs textarea

Correction d’une notice PHP

Query Monitor (cf l’article précédent de cette série «  » indique 3 notices PHP. Ce sont des erreurs bénignes qu’il faut corriger.

Les trois notices portent sur des index indéfinis pour field-2-1, field-2-2 et field-2-3, sous la forme « Undefined index: field-2-1 ». Ces trois champs n’ont jamais été définis puisqu’on n’a pas encore pu leur attribuer une valeur. Cependant, il n’est pas normal que notre code traite des valeurs indéfinies sans « s’en rendre compte ».

Dans cet article de code.tutsplus, je vois qu’ils font deux vérifications avant de lire la valeur de l’option. La première consiste à vérifier qu’il existe bien des options pour notre réglage (‘my-plugin-settings’ pour moi, ‘sandbox_theme_display_options’ pour eux :

if( false == get_option( 'sandbox_theme_display_options' ) ) {  
    add_option( 'sandbox_theme_display_options' );
}

Cette vérification est réalisée au moment du ‘admin_init’, dans notre cas dans la fonction clea_add_button_admin_init()  modifiée comme suit :

function clea_add_button_admin_init() {
  
	if( false == get_option( 'my-plugin-settings' ) ) {  
		add_option( 'my-plugin-settings' );
	}
	
	register_setting( 'my-settings-group', 'my-plugin-settings' ) ;
	
	$set_sections = clea_add_button_settings_sections_val() ;
 
	// add_settings_section
	foreach( $set_sections as $section ) {
		
		add_settings_section( 
			$section[ 'section_name' ], 
			$section[ 'section_title' ] ,
			$section[ 'section_callbk' ], 
			$section[ 'menu_slug' ]
		);
		
	}	

	$set_fields = clea_add_button_settings_fields_val() ;
	
	// add the fields
	foreach ( $set_fields as $section_field ) {

		foreach( $section_field as $field ){

			add_settings_field( 
				$field['field_id'], 
				$field['label'], 
				$field['field_callbk'],  
				$field['menu_slug'], 
				$field['section_name'],
				$field
			);
		}

	}	
}

La seconde vérification porte sur l’option du champs en question :

// First, we read the social options collection
$options = get_option( 'sandbox_theme_social_options' );
     
// Next, we need to make sure the element is defined in the options. If not, we'll set an empty string.
$url = '';
if( isset( $options['twitter'] ) ) {
    $url = $options['twitter'];
} // end if

Cette partie là est réalisée dans la fonction « callback » du champs ‘twitter’.

Là dessus, j’ai longtemps bloqué car je dois vérifier si $settings[ $field ] est « isset » et pour une raison que j’ignorais ce n’était jamais le cas, même lorsqu’il y avait bien une valeur… Et puis je suis tombée sur cette question dans wordpress.stackexchange et j’ai enfin compris comment faire (mais pas franchement pourquoi !).

Ma fonction clea_add_button_settings_field_callback( $arguments ) contient maintenant une vérification au début. Si $options[ « $field » ] est « set », $value  prend la valeur de $settings[ $field ] . Dans le cas contraire, elle prend la valeur par défaut du champs.

function clea_add_button_settings_field_callback( $arguments  ) {


	$settings = (array) get_option( "my-plugin-settings" );
	$field = $arguments[ 'field_id' ] ;
	
	// for development only
	if ( ENABLE_DEBUG ) {
		
		echo "<hr /><p>Arguments</p><pre>";
		print_r( $arguments ) ;	
		echo "</pre><hr />";
		echo "<hr /><p>Options</p><pre>";
		print_r( $settings ) ;	
		echo "</pre><hr />";
	}
		
	// set a $options array with the field id as it's key
	if ( !empty( $settings ) ) {
		foreach ( $settings as $key => $option ) {
			$options[$key] = $option;
		}
	}	
	
	// now check if $options[ $field ] is set
	if( isset( $options[ "$field" ] ) ) {
			$value = $settings[ $field ] ;
	} else {
			// set the value to the default value
			$value = $arguments[ 'default' ] ;
	}	

	
	$name = 'my-plugin-settings['. $field . ']' ;

	switch( $arguments['type'] ){
		
		case 'text' : 
			printf( '<input type="text" id="%3$s" name="%2$s" value="%1$s" />', esc_attr( $value ), $name, $field );
			break ;
		case 'textarea' : 
			printf( '<textarea name="%2$s" id="%3$s" rows="4" cols="80" value="%1$s">%1$s</textarea>', esc_textarea( $value ), $name, $field );
			break ;
		
		default : 
			printf( esc_html__( 'This field is type <em>%s</em> and could not be rendered.', 'clea-add-button' ), $arguments['type']  );
	}
}

Les notices PHP pour les champs qui n’ont pas encore pu être saisis ont maintenant disparu.

Afficher des champs « select »

Notre champs select sera restitué sous la forme :

<select name="lenom" id="field-id" multiple="">
  <option value="volvo">Volvo</option>
  <option value="saab">Saab</option>
  <option value="vw">VW</option>
  <option value="audi" selected>Audi</option>
</select>

Si les options ne sont pas fixes (cas où il y a plusieurs champs select), il faut pouvoir les ajouter dans l’array de définition du champs. Je crée un troisième champs dans la section 1 avec les caractéristiques suivantes :

array(
	'field_id' 		=> 'field-1-3', 
	'label'			=> __( 'Field three : select', 'clea-add-button' ), 
	'field_callbk'	=> 'clea_add_button_settings_field_callback', 
	'menu_slug'		=> 'my-plugin', 
	'section_name'	=> 'section-1',
	'type'			=> 'select',
	'helper'		=> __( 'help 1-3', 'clea-presentation' ),
	'default'		=> '',
	'options'		=> array(
						__( 'Choix 1', 'clea-add-button' ) ,
						__( 'Choix 2', 'clea-add-button' )	,
						__( 'Choix 3', 'clea-add-button' )
					),				
),

Pour le visualiser, j’ajoute le cas ‘select’ comme suit :

case 'select': // If it is a select dropdown

	if( ! empty ( $arguments['options'] ) && is_array( $arguments['options'] ) ){
	
	printf( '<select id="%2$s" name="%1$s">', $name, $field );
	foreach( $arguments['options'] as $item ) {
		$selected = ( $value	 == $item ) ? 'selected="selected"' : '';
		echo "<option value='$item' $selected>$item</option>";
	}
	echo "</select>";	
	
	} else {
		echo __( 'Indiquer les options dans la définition du champs', 'clea-add-button' ) ;
	}
	break;

Et voilà maintenant la section 1 de ma page de réglage :

Affichage d'un champs "select"

Affichage d’un champs « select »

Afficher des champs « checkbox »

Notre champs checkbox sera restitué sous la forme :

<input type="hidden" name="my-plugin-settings[field-1-4]" id="field-1-4" value="0"> 
<input id="field-1-4" name="my-plugin-settings[field-1-4]" type="checkbox">

et si le champs est coché, il prendra la forme (observer le « checked » juste après « input » :

<input checked="checked" id="field-1-4" name="my-plugin-settings[field-1-4]" type="checkbox">

J’ajoute un quatrième champs dans la section 2 avec un type checkbox :

array(
	'field_id' 		=> 'field-1-4', 
	'label'			=> __( 'Field four : checkbox', 'clea-add-button' ), 
	'field_callbk'	=> 'clea_add_button_settings_field_callback', 
	'menu_slug'		=> 'my-plugin', 
	'section_name'	=> 'section-1',
	'type'			=> 'checkbox',
	'helper'		=> __( 'help 1-4', 'clea-presentation' ),
	'default'		=> '',
)

Pour le visualiser, j’ajoute le cas ‘checkbox’ comme suit :

case 'checkbox' : 
	printf( '<input type="hidden" name="%1$s" id="%2$s" value="0" />', $name, $field ) ;			
	$checked = '' ;
        if( $value ) { $checked = ' checked="checked" ' ; }
	printf( ' <input %3$s id="%2$s" name="%1$s" type="checkbox" />', $name, $field, $checked ) ;
	break ;

Et voilà maintenant la section 1 de ma page de réglage contient un champ texte, un champ textarea, un champ select et un champ checkbox :

Affichage d'un champs "checkbox"

Affichage d’un champs « checkbox »

Afficher des champs « radio button »

Notre champs radio sera restitué sous la forme :

<span class="radio">
	<label><input type="radio" value="Choix 1" name="my-plugin-settings[field-2-1]" checked=""> Choix 1</label><br>
	<label><input type="radio" value="Choix 2" name="my-plugin-settings[field-2-1]"> Choix 2</label><br>
	<label><input type="radio" value="Choix 3" name="my-plugin-settings[field-2-1]"> Choix 3</label><br>
</span>

Si les options ne sont pas fixes, il faut pouvoir les ajouter dans l’array de définition du champs. Je modifie le premier champ de la section 2 comme pour le champs de type radio, en y ajoutant des options.

Pour le visualiser, j’ajoute le cas ‘radio’ comme suit :

case 'radio' : // radio buttons
	if( ! empty ( $arguments['options'] ) && is_array( $arguments['options'] ) ){
		
		echo "<span class='radio'>" ;
		foreach( $arguments['options'] as $key => $label ){
			
			$items[] = $label ;
		}

		foreach( $arguments['options'] as $item) {
			$checked = ( $value == $item ) ? 'checked' : '';
			printf( '<label><input type="radio" value="%2$s" name="%1$s" %3$s> %2$s</label><br />', $name, $item, $checked );
		}
		echo "</span>" ;
	}
	break ;

Et voilà maintenant la section 2 de ma page de réglage contient un premier champs radio correctement présenté :

Affichage d'un champs "radio"

Affichage d’un champs « radio »

Afficher des champs « wysiwig « 

Notre champs wisiwig correspond à un éditeur, un peu comme lorsqu’on crée un article dans WordPress. Il est restitué par la fonction wp_editor de WordPress. Ici j’ai choisi de ne pas ajouter d’arguments spécifiques.

Pour le visualiser, j’ajoute le cas ‘wysiwig’ comme suit :

case 'wysiwig' :

	// sanitize data for the wp_editor
	$content = wp_kses_post( $value ) ;
	
	$args = array(
		'textarea_name' => $name
	) ;
	
	wp_editor( $content, $field, $args );		
	break ;

Le Codex pour wp_editor() indique que l’ID de l’éditeur ne peut contenir que des minuscules et des tirets bas (underscores). J’ai donc modifié le ‘field_id’ pour qu’il devienne field_2_2.

On notera que $value est nettoyé avec la fonction wp_kses_post(), qui permet entre autres d’avoir des images dans le texte.

Et voilà maintenant la section 2 contient un éditeur de texte :

Affichage d'un champs "wp-editor"

Affichage d’un champs « wp-editor »

Et maintenant

Nous verrons dans le prochain article de cette série () comment restituer le dernier champs comme un  color picker, et aussi comment afficher les arguments supplémentaires.

L’extension à ce stade est disponible, compressée en zip : clea-add-button avec éditeur wp_editor (zip)

Extension WordPress : méthodes pour le débogage

Extension WordPress : méthodes pour le débogage

Lorsqu’on crée une extension (ou un thème) WordPress, il est indispensable de prévoir des moyens de déboguer efficacement. Nous allons voir ici quelques méthodes applicables, telles que l’affichage du contenu de variables dans une page du tableau de bord WordPress, l’utilisation de debug.log de WordPress ou l’utilisation d’extensions WordPress telles que  Debug Bar et Query Monitor.

Tous les exemples qui suivent sont utilisés pour l’extension créée au fil des articles de cette série (). La version avec le débogage testé dans cet article est dans ce fichier zip : clea-add-button V0.1 clea-add-button V0.1 (zip).

Utiliser les outils de debogage WordPress

Sur un site de développement (mais jamais sur un site de « production » utilisable par nos internautes cibles), on modifie wp-config.php pour que le debogage soit réalisé et que les erreurs s’affichent lors de l’affichage des pages du site (front ou back). Par défaut, les paramètres suivants sont réglés sur « false » :

define('WP_DEBUG', false ); 
define('WP_DEBUG_DISPLAY', false);

Dans ce cas, s’il y a une erreur importante, notre page web affiche un contenu blanc, sans aucune indication du type d’erreur rencontré. Si je met ces paramètres à ‘true’, j’aurai un affichage de l’erreur à l’écran et je pourrai y remédier :

Erreur fatale avec wp-config.php réglé pour que debug trueExemple : je crée volontairement une erreur (par exemple en enlevant un « ; » à la ligne 45 de clea-add-button-settings-page.php. Je recharge la page d’options ou je vais sur le site et le site a disparu. A la place, il y a une page blanche, avec le message « Fatal error: syntax error, unexpected ‘$set_sections’ (T_VARIABLE) in /home/cecilebo/test1/wp-content/plugins/clea-add-button/admin/clea-add-button-settings-page.php on line 47″. Je sais immédiatement dans quel fichier aller corriger l’erreur. Je regarde les lignes qui précèdent la ligne 47 : la 46 est vide et c’est plutôt simple d’ajouter le « ; » manquant en ligne 45.

Donc, dès qu’on est sur un site de développement, on régle les paramètres de wp-config.php pour afficher les erreurs :

define('WP_DEBUG', true );  
define('WP_DEBUG_DISPLAY', true);

On peut aussi régler la ligne suivante à « true » :

define('WP_DEBUG_LOG', true);

Dans ce cas, les erreurs sont stockées dans un fichier debug.log situé dans le répertoire /wp-content. C’est pratique si on doit absolument intervenir sur un site de production et qu’on ne peut pas avoir WP_DEBUG_DISPLAY réglé à « true ». Mais ça oblige à aller sans arrêt éditer le contenu de debug.log pour voir ce qui se passe. Je n’aime pas beaucoup, sauf cas particuliers comme lorsque je veux afficher des contenus de variables dans un fichier (voir plus loin).

Utilisation d’extensions spécialisées

l’extension « Debug Bar »

j’utilise depuis longtemps l’extension ‘Debug Bar‘. Elle ajoute un élément « debug » à gauche du nom Jde l’utilisateur dans le tableau de bord WordPress. Si on clique dessus, et que WP_DEBUG est réglé à ‘true’, on voit s’afficher la liste des notices et warnings auxquels il faut qu’on fasse attention. Lorsqu’il y a des warnings, l’élément « debug » devient rouge pour nous alerter.

Avantages :

Inconvénients :

  • on doit jongler entre différents écrans pour visualiser ce qui se passe dans notre site.

Debug Bar est très bien, mais il y a encore mieux !

La solution idéale : l’extension ‘Query Monitor’

Depuis que j’ai découvert cette extension, je ne lui ai pas trouvé un seul défaut. Elle permet de recueillir toutes les informations nécessaires au développement tout en étant pratique. C’est surtout l’interface utilisateur qui fait la différence.

Pour plus d’informations, voir sur WordPress.org, ici. Je note que les FAQ indiquent que les compléments de Debug Bar puvent être utilisés avec Query Monitor, sans que Debug Bar soit présent. Et il existe aussi des compléments pour Query Monitor. Je note en particulier les compléments suivants, que je n’ai jamais essayés :

Pour développer et valider selon les utilisateurs

Il arrive que j’utilise « User Switching » lorsque j’ai besoin de tester avec différents rôles d’utilisateur.

Afficher le contenu d’une variable pour aider au développement / débogage

Ce n’est pas toujours simple de savoir ce que contient une variable définie par notre programme ou par WordPress. C’est en particulier difficile lorsque la variable est un array, dont on ne connait pas la structure, ou pire une chaîne de caractères « sérialisée » (« serialized data » en anglais) comme le contenu de get_option .

Pour afficher des variables, on a plusieurs options :

Afficher la variable directement dans la page que l’on crée

C’est une solution simple. Par exemple, dans clea-add-button-settings-page.php, pour définir le contenu de la fonction clea_add_button_settings_field_callback( $arguments  ), qui affiche les différents champs, j’ai affiché le contenu de l’array $arguments :

echo "<hr /><pre>";
print_r( $arguments ) ;	
echo "</pre><hr />";

l’ajout de <pre> et </pre> permet un affichage propre de l’array.

Mais l’inconvénient d’un tel choix est qu’on doit ensuite commenter toutes les lignes de débogage. J’ai donc fait le choix de définir une constante en début de fichier :

/**********************************************************************
* DEBUG ?
***********************************************************************/

define('ENABLE_DEBUG', true);	// if true, the script will echo debug data

et ma fonction function clea_add_button_settings_field_callback( $arguments )  contient :

function clea_add_button_settings_field_callback( $arguments ) {

$settings = (array) get_option( 'my-plugin-settings' );
$field = $arguments['field_id'] ;
$value = esc_attr( $settings[$field] );

// for development only
if ( ENABLE_DEBUG ) {

echo "<hr /><pre>";
print_r( $arguments ) ; 
echo "</pre><hr />";
}

echo "<input type='text' name='my-plugin-settings[$field]' value='$value' />"; 
}

Comme ça, si j’ai réglé ENABLE_DEBUG à true, je voies le contenu de l’array et sinon je suis en mode utilisation normale de l’extension :

C’est une bonne solution, que je n’ai trouvée que récemment. Mais elle ne fonctionne pas si je n’ai pas une page dédiée à l’extension dans le tableau de bord WordPress. Il peut donc être utile d’afficher ailleurs le contenu des variables. Dans ce cas, on utilisera une extension spécialisée.

Utiliser l’extension Query Monitor Extend

Installer Query Monitor Extend à partir de son fichier zip puis l’activer.

Utiliser l’extension Query Monitor: Checking Variable

Installer Query Monitor: Checking Variable puis l’activer.

Une page de réglage « check variables » apparaît dans « Réglages ».

Pour les deux exemples de réglage qui suivent, j’ai ajouté une ligne à la fonction clea_add_button_settings_section_callback( $args  ) :

console( $args );

On peut faire apparaître les variables dans le pied de page comme dans le réglage qui suit :

On peut aussi préférer afficher les variables dans Query Monitor comme dans le réglage qui suit :

C’est pratique comme système.

Et maintenant ?

Une fois qu’on sait ce que contiennent nos variables, tout devient plus simple !

Nous allons poursuivre le développement de l’extension « Add Button » et améliorer la page de réglage pour qu’elle puisse afficher des formats de champs autres que texte. Ce sera l’objet du prochain article de cette série .

Créer une page de réglage pour une extension WordPress

Créer une page de réglage pour une extension WordPress

Je poursuis le travail sur la création d’une extension « best practice » généré dans l’article précédent (Créer une extension WordPress ; Partie 1) de cette série. Une extension sur laquelle le webmaster ne peut pas intervenir n’est pas très intéressante puisqu’elle oblige à modifier le code à chaque fois qu’un paramètre change. J’explore donc ici la manière de créer une page de réglage pour l’extension. J’utilise l’API « settings » de WordPress car c’est une méthode plus sûre (la « sanitation » des données est assurée par WordPress).

Mes sources d’information

L’extension au départ

L’extension est au stade où je l’ai laissée dans le premier article de cette série :

Premier essai

J’ai fait plusieurs essais avant celui-ci mais à chaque fois j’avais un « petit » problème dont je n’arrivais pas trouver la solution. Je préfère donc repartir de zéro pour comprendre. J’ai tout simplement copié le contenu du « gist » de Anna et je l’ai placé dans un fichier « clea-add-button-settings-page.php  » du répertoire /admin. Dans le fichier principal de l’extension (clea-add-button.php), j’ai ajouté la ligne require_once CLEA_ADD_BUTTON_DIR_PATH . ‘admin/clea-add-button-settings-page.php’;  et j’ai rechargé la fenêtre de mon navigateur.

Une page de réglage « My Plugin Options » apparaît sous « réglages » (la copie d’écran correspond à ce qui est affiché une fois que j’ai enregistré une première fois des données) :

Essai 1 de page de réglage d'une extension

Essai 1 de page de réglage d’une extension

Et dans la base de données, la table « prefix-options » contient une nouvelle ligne (option_name = my-plugin-settings), qui contient :

a:4:{s:9:"field_1_1";s:4:"zzzz";s:9:"field_1_2";s:8:"ttttyyyy";s:9:"field_2_1";s:5:"hhhhh";s:9:"field_2_2";s:6:"mmmmmm";}

C’est donc exactement ce que je cherche à faire. Reste maintenant à le faire mieux !

Qu’est-ce que je veux faire ?

Je veux obtenir une page de réglage avec plusieurs sections et des champs qui pourraient être présentés sous forme de texte court, de texte long (textarea), de cases à cocher (radio ou checkbox), de liste déroulante, d’un éditeur wysiwig pour des textes sophistiqués et d’un sélecteur de couleur (color picker).

Je voudrais aussi pouvoir définir les sections et les champs dans des « arrays » (tableaux) et générer automatiquement la page de réglages.

Enfin, je voudrais qu’une case à cocher permette d’afficher des éléments de débogage à la fin de la page de réglages si je le souhaite.

Etape 1 : générer automatiquement l’exemple ci-dessus

Je vais modifier le gist de Anna pour générer automatiquement sa page de réglages avec moins de code.

Respecter les bonnes pratiques :

La première chose que je fais, c’est de remplacer ‘textdomain’ par ‘clea-add-button’ et de mettre un préfixe  clea_add_button_ devant toutes les fonctions.

regrouper la définition des sections et champs, automatiser la génération

J’ai regroupé la définition des sections à la fin, dans la fonction clea_add_button_settings_sections_val() . Idem pour la définition des champs, dans la fonction clea_add_button_settings_sections_val() .

Ainsi la fonction clea_add_button_admin_init()  ne contient plus qu’une boucle « foreach », qui lit les arrays de sections ou champs à générer et les génère.

<?php
/**
 *
 * Créer une page de settings pour l'extension

 *
 * @link       	
 * @since      	0.2.0
 *
 * @package    clea-add-button
 * @subpackage clea-add-button/includes
 * Text Domain: clea-add-button
 */

//  Based on Anna's gist https://gist.github.com/annalinneajohansson/5290405
// http://codex.wordpress.org/Settings_API

/**********************************************************************

* to set the title of the setting page see -- clea_add_button_options_page()
* to set the sections see -- clea_add_button_settings_sections_val()
* to set the fields see -- clea_add_button_settings_fields_val()

**********************************************************************/

// create the settings page and it's menu
add_action( 'admin_menu', 'clea_add_button_admin_menu' );

// set the content of the admin page
add_action( 'admin_init', 'clea_add_button_admin_init' );


function clea_add_button_admin_menu() {
	
    add_options_page( 
		__('Options de Clea Add Button', 'clea-add-button' ),	// page title (H1)	
		__('Options', 'clea-add-button' ),						// menu title
		'manage_options', 										// required capability
		'my-plugin', 											// menu slug (unique ID)
		'clea_add_button_options_page' );						// callback function
}

function clea_add_button_admin_init() {
  
  	register_setting( 'my-settings-group', 'my-plugin-settings' );
	
	$set_sections = clea_add_button_settings_sections_val() ;
 
	// add_settings_section
	foreach( $set_sections as $section ) {
		
		add_settings_section( 
			$section[ 'section_name' ], 
			$section[ 'section_title' ] ,
			$section[ 'section_callbk' ], 
			$section[ 'menu_slug' ]
		);
		
	}	

	$set_fields = clea_add_button_settings_fields_val() ;
	
	// add the fields
	foreach ( $set_fields as $section_field ) {

		foreach( $section_field as $field ){

			add_settings_field( 
				$field['field_id'], 
				$field['label'], 
				$field['field_callbk'],  
				$field['menu_slug'], 
				$field['section_name'] 
			);
		}

	}	
}


/**********************************************************************

* The actual page

**********************************************************************/
function clea_add_button_options_page() {
?>
  <div class="wrap">
      <h2><?php _e('My Plugin Options', 'clea-add-button'); ?></h2>
      <form action="options.php" method="POST">
        <?php settings_fields('my-settings-group'); ?>
        <?php do_settings_sections('my-plugin'); ?>
        <?php submit_button(); ?>
      </form>
  </div>
<?php }


function section_1_callback() {
	_e( 'Some help text regarding Section One goes here.', 'clea-add-button' );
}
function section_2_callback() {
	_e( 'Some help text regarding Section Two goes here.', 'clea-add-button' );
}


function field_1_1_callback() {
	
	$settings = (array) get_option( 'my-plugin-settings' );
	$field = "field_1_1";
	$value = esc_attr( $settings[$field] );
	
	echo "<input type='text' name='my-plugin-settings[$field]' value='$value' />";
}
function field_1_2_callback() {
	
	$settings = (array) get_option( 'my-plugin-settings' );
	$field = "field_1_2";
	$value = esc_attr( $settings[$field] );
	
	echo "<input type='text' name='my-plugin-settings[$field]' value='$value' />";
}
function field_2_1_callback() {
	
	$settings = (array) get_option( 'my-plugin-settings' );
	$field = "field_2_1";
	$value = esc_attr( $settings[$field] );
	
	echo "<input type='text' name='my-plugin-settings[$field]' value='$value' />";
}
function field_2_2_callback() {
	
	$settings = (array) get_option( 'my-plugin-settings' );
	$field = "field_2_2";
	$value = esc_attr( $settings[$field] );
	
	echo "<input type='text' name='my-plugin-settings[$field]' value='$value' />";
}
/*
* INPUT VALIDATION:
* */
function clea_add_button_settings_validate_and_sanitize( $input ) {
	$settings = (array) get_option( 'my-plugin-settings' );
	
	if ( $some_condition == $input['field_1_1'] ) {
		$output['field_1_1'] = $input['field_1_1'];
	} else {
		add_settings_error( 'my-plugin-settings', 'invalid-field_1_1', 'You have entered an invalid value into Field One.' );
	}
	
	if ( $some_condition == $input['field_1_2'] ) {
		$output['field_1_2'] = $input['field_1_2'];
	} else {
		add_settings_error( 'my-plugin-settings', 'invalid-field_1_2', 'You have entered an invalid value into Field One.' );
	}
	
	// and so on for each field
	
	return $output;
}

/**********************************************************************

* THE SECTIONS

**********************************************************************/

function clea_add_button_settings_sections_val() {

	$sections = array(
		array(
			'section_name' 	=> 'section-1', 
			'section_title'	=>  __( 'Section One', 'clea-add-button' ), 
			'section_callbk'=> 'section_1_callback', 
			'menu_slug'		=> 'my-plugin' ,								
		),
		array(
			'section_name' 	=> 'section-2',
			'section_title'	=>  __( 'Section Two', 'clea-add-button' ),
			'section_callbk'=> 'section_2_callback' ,
			'menu_slug'		=> 'my-plugin'
			),
	);	
	
	return $sections ;
	
}

/**********************************************************************

* THE FIELDS

**********************************************************************/
function clea_add_button_settings_fields_val() {



	$section_1_fields = array (
		array(
			'field_id' 		=> 'field-1-1', 							
			'label'			=> __( 'Field One', 'clea-add-button' ), 	
			'field_callbk'	=> 'field_1_1_callback', 					
			'menu_slug'		=> 'my-plugin', 							
			'section_name'	=> 'section-1', 							
		),	
		array(
			'field_id' 		=> 'field-1-2',
			'label'			=> __( 'Field Two', 'clea-add-button' ),
			'field_callbk'	=> 'field_1_2_callback', 
			'menu_slug'		=> 'my-plugin', 
			'section_name'	=> 'section-1'
		),
	);
	
	$section_2_fields = array (
		array(
			'field_id' 		=> 'field-2-1', 
			'label'			=> __( 'Field One', 'clea-add-button' ), 
			'field_callbk'	=> 'field_2_1_callback', 
			'menu_slug'		=> 'my-plugin', 
			'section_name'	=> 'section-2'			
		),
		array(
			'field_id' 		=> 'field-2-2', 
			'label'			=> __( 'Field Two', 'clea-add-button' ), 
			'field_callbk'	=> 'field_2_2_callback', 
			'menu_slug'		=> 'my-plugin', 
			'section_name'	=> 'section-2'
		),
	);
	

	$section_fields = array(
		'section-1'	=> $section_1_fields,
		'section-2' => $section_2_fields
	) ;	

	
	
	return $section_fields ;
}

Ajouter d’autres arguments pour les champs

Il faut que j’ajoute des arguments à chaque champs :

  • ‘type’ : dans l’exemple dont je pars, tous les champs sont des textes courts. Comme je ne veux pas avoir autant de fonctions que de champs pour les afficher, il faut que le programme sache quel est le type du champs pour savoir comment le restituer.
  • ‘helper’ : un texte qui aidera l’utilisateur à comprendre comment faire son réglage.
  • ‘default’ : qui permettra de définir une valeur si l’utilisateur n’en définit pas.

Chaque champs doit pouvoir être défini par un array contenant les 5 éléments obligatoires et les trois nouveaux.

array(
'field_id' => 'field-1-1', 
'label' => __( 'Field One', 'clea-add-button' ), 
'field_callbk' => 'field_1_1_callback', 
'menu_slug' => 'my-plugin', 
'section_name' => 'section-1',
'type' => 'text',
'helper' => __( 'help 1', 'clea-presentation' ),
'default' => '' 
),

Je me suis inspirée de cet article de Smashing Magazine pour faire ça.

Dans la fonction qui génère les champs, j’ajoute une dernière valeur qui correspondra à $args, le 6ème élément de la fonction add_settings_field.

// add the fields
foreach ( $set_fields as $section_field ) {

	foreach( $section_field as $field ){

		add_settings_field( 
			$field['field_id'], 
			$field['label'], 
			$field['field_callbk'],  
			$field['menu_slug'], 
			$field['section_name'],
			$field
		);
	}

}	

Et dans la fonction field_1_1_callback() , j’ajoute $argument  comme élément reçu, ainsi que l’affichage du contenu de cette variable (c’est un array, j’utilise print_r)  :

function field_1_1_callback( $arguments ) {
	
	$settings = (array) get_option( 'my-plugin-settings' );
	$field = "field_1_1";
	$value = esc_attr( $settings[$field] );
	
	echo "<input type='text' name='my-plugin-settings[$field]' value='$value' />";
	echo "<hr /><pre>";
	print_r( $arguments ) ;
	echo "</pre><hr />";	
}

Et ça fonctionne !

Page de réglage d'une extension WordPress : affichage des arguments de add_settings_field

Page de réglage d’une extension WordPress : affichage des arguments de add_settings_field

Regrouper les fonctions « callback » pour les sections

Il n’y a pas beaucoup de sections en général mais ce n’est pas la peine de créer autant de fonctions que de sections.

Je crée donc une fonction clea_add_button_settings_section_callback( $args )  (que je n’oublie pas de déclarer comme ‘section_callbk’ dans la définition des sections) :

/**********************************************************************

* Section callback

**********************************************************************/

function clea_add_button_settings_section_callback( $args  ) {
	
	$sect_descr = array(

		'section-1' 	=> __( 'Text regarding Section One goes here.', 'clea-presentation' ),
		'section-2' 	=> __( 'Text regarding Section Two goes here.', 'clea-presentation' )
	);		

	$description = $sect_descr[ $args['id'] ] ;
	printf( '<span class="section-description">%s<span>', $description );
	
}

Et mes sections s’affichent correctement.

Regrouper les fonctions « callback » pour les champs

Je vais faire la même chose maintenant pour les champs, en remplaçant les 4 fonctions correspondant aux 4 champs par une seule.

En faisant afficher l’array des arguments transmis à la fonction « callback » des champs, j’ai vu que cet array est composé comme suit :

Array
(
    [field_id] => field-1-1
    [label] => Field One
    [field_callbk] => field_1_1_callback
    [menu_slug] => my-plugin
    [section_name] => section-1
    [type] => text
    [helper] => help 1
    [default] => 
)

une fonction « callback » pour les champs définis actuellement (des textes) contient les 4 lignes suivantes :

$settings = (array) get_option( 'my-plugin-settings' );
$field = "field_1_1";
$value = esc_attr( $settings[$field] );
	
echo "<input type='text' name='my-plugin-settings[$field]' value='$value' />";

Il va falloir que je remplace tout ce qui est spécifique au champs 1-1 par des variables, pour que ça s’applique à tous les champs :

$settings = (array) get_option( 'my-plugin-settings' );

Cette ligne va chercher la valeur enregistrée pour toutes les options d’un nom défini lorsque nous avons exécuté la commande ‘register_setting’, au début de la fonction clea_add_button_admin_init() . C’est une valeur fixe que je laisse telle quelle pour l’instant (ce n’est certainement pas une bonne idée de laisser un nom si générique, sans préfixe spécifique).

$field = "field_1_1";

Là on voit que « field_1_1 » correspond au contenu de $args[field_id].

$value = esc_attr( $settings[$field] );

Cette ligne lit la valeur attribuée à l’option et la met dans la variable « value ». On ne la change pas puisque $field n’est plus fixe.

echo "<input type='text' name='my-plugin-settings[$field]' value='$value' />";

Ne change pas non plus. Ma fonction clea_add_button_settings_field_callback( $args  ) va donc contenir quasiment la même chose qu’avant mais elle sera utilisable par tous les champs :

function clea_add_button_settings_field_callback( $args  ) {

	$settings = (array) get_option( 'my-plugin-settings' );
	$field = $args[field_id] ;
	$value = esc_attr( $settings[$field] );
	
	echo "<input type='text' name='my-plugin-settings[$field]' value='$value' />";	
	
}

Maintenant je supprime les 4 fonctions callback des 4 champs définis et dans la définition des champs, je remplace le contenu de ‘field_callbk’ par le nom de la fonction collective.

J’obtiens bien l’affichage de mon formulaire, mais pas des valeurs déjà enregistrées. Et il y a 4 PHP notices. La première notification signale Undefined index: field-1-1  en ligne 128 de clea-add-button-settings-page.php. Les trois autres sont identiques et portent sur les 3 autres champs.

C’est en fait « normal » : je me suis trompée en définissant l’array des champs. J’ai mis des id de type ‘field-1-1’ alors que Anna, l’auteure du Gist dont je m’inspire utilisais field_1_1… Il m’a suffi d’enregistrer une valeur pour que tout rentre dans l’ordre.

Et voilà, j’obtiens exactement le même résultat qu’Anna mais même si j’ajoute des dizaines de paramètres, les fonctions qui les restituent resteront uniques. C’est plus « élégant », mais surtout ça réduit fortement le risque d’erreur si j’ajoute un nouveau paramètre car le code est beaucoup plus lisible.

le fichier ‘clea-add-button-settings-page.php’ (le seul modifié) est dans ce « commit », sur github. Vous pouvez également récupérer l’extension à ce stade dans ce fichier zip : clea-add-button V0.1 (zip).

Et maintenant ?

Dans des articles à venir, il faudra voir comment ajouter d’autres types de champs, comment charger des feuilles de style, comment faire utiliser un template de l’extension…

Mais d’abord, il faut voir comment on peut plus facilement déboguer. C’est l’objet du prochain article de cette série [the-series).