Développer un plugin pour WordPress
3 – Création de la page des paramètres
1 septembre 2016.
Premier contact
Glissons dextrement le dossier text-floating-image dans le répertoire wp-content\plugins de notre installation WordPress et rendons nous pour voir un peu sur la page des extensions de notre back-end. Là, on joue la surprise extasiée que, quand même, c’est trop génial, notre plugin à nous est bien là avec une ch’tite description qui dit rien mais quand même et puis tiens puisqu’on est là à s’esbaudir ne nous retenons pas plus longtemps et activons la bête !
Bon, à ce moment précis du film, on est un peu déçu forcément parce que si la bête est bel est bien activée, elle n’a pas rugi pour autant, rien n’a bougé, les trompettes de la renommée sont restées cruellement coites et même la terre continue de tourner qu’à bien y réfléchir c’est quand même préférable…
En même temps, faut bien admettre que jusqu’ici on ne s’est pas franchement foulé…
Il est d’ailleurs plus que temps de nous y mettre car la route est encore longue !
Une description qui va bien
On va commencer tout doucement en donnant une description idoine à notre plugin. La chose se fait très simplement dans la classe principale text-floating-image.php logée à la racine du dossier de notre extension. Il suffit de renseigner de façon éclairante la ligne Description qui figure au sein des commentaires introductifs du fichier :
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<?php /** * The plugin bootstrap file * * This file is read by WordPress to generate the plugin information in the plugin * admin area. This file also includes all of the dependencies used by the plugin, * registers the activation and deactivation functions, and defines a function * that starts the plugin. * * @link onfaitdessites.fr * @since 1.0.0 * @package Text_Floating_Image * * @wordpress-plugin * Plugin Name: Text Floating Image * Plugin URI: onfaitdessites.fr * Description: This is a short description of what the plugin does. It's displayed in the WordPress admin area. * Version: 1.0.0 * Author: Lui * Author URI: onfaitdessites.fr * License: GPL-2.0+ * License URI: http://www.gnu.org/licenses/gpl-2.0.txt * Text Domain: text-floating-image * Domain Path: /languages */ // If this file is called directly, abort. if ( ! defined( 'WPINC' ) ) { die; } |
Ainsi donc, en ce qui nous concerne, la ligne Description devient :
13 14 15 16 17 18 19 20 21 22 |
/** ..... * Plugin Name: Text Floating Image * Plugin URI: onfaitdessites.fr * Description: A TinyMCE plugin for verticaly align text and image. * Version: 1.0.0 ..... */ |
Alors oui bon je sais je sais je sais : depuis le fondement de mon trou breton j’entends monter vos hurlements outrés que c’est du grand n’importe quoi cet english de cuisine, et pis qu’on est en France et qu’en France on cause français Môssieur ! Ce à quoi je réponds que d’abord et avant tout je fais ce que je veux, je parle comme je veux et anglais comme je peux et qu’ensuite, tout ça c’est pour la bonne cause because (ah ! ah !) ce plugin, mes p’tits gars, il a la grande classe internationale et que si on le pense d’emblée en british sauce mondialisée ça ne nous empêchera surtout pas d’étudier le comment de la traduction que même ce sera un excellent exercice ! Ah mais !
Ceci étant dit et plutôt que de ressasser vos ronchonneries que c’est mauvais pour l’ulcère qui vous guette du coin de son œil qu’il a mauvais, vous pouvez vous assurer que la description a bien été prise en compte en actualisant sans plus traîner la page des extensions de WordPress.
Ajout d’une entrée dans le menu Réglages
Continuons notre périple en nous efforçant d’ajouter une entrée Text Floating Image dans le menu Réglages du tableau de bord de WordPress pour ouvrir un accès à la page des options paramétrables de notre belle extension.
Le chose se réalise en s’appuyant sur le hook admin_menu que nous allons employer pour lancer une fonction add_plugin_admin_menu() écrite de nos petites mains. Celle-ci appellera la fonction add_options_page() de WordPress, laquelle est justement dédiée à l’ajout d’une entrée dans le menu Réglages. Pour finir, add_options_page() aura pour callback une fonction display_plugin_setup_page() qui se chargera d’inclure la page partials/text-floating-image-admin-display.php, prévue d’office par notre boilerplate et destinée à renfermer le contenu de notre page de paramètres.
Comme nous l’avons vu au cours de l’épisode précédent, la gestion des hooks est déléguée à la classe admin/includes/class-text-floating-image-loader.php dans laquelle nous n’avons rien à faire si ce n’est y jeter un œil pour mieux comprendre son mécanisme.
Pour la partie administration du blog qui nous intéresse ici et maintenant, les hooks doivent être définis dans la fonction define_admin_hooks() contenue dans includes/class-text-floating-image.php (pour ce qui concerne le front-end, c’est la fonction define_public_hooks() de cette même classe qui se charge du boulot).
Quant à notre fonction add_plugin_admin_menu chargée de réaliser la tâche au final, nous la rangerons soigneusement à la place qui lui revient, c’est-à-dire dans la classe admin/class-text-floating-image-admin.php.
Commençons donc par définir notre hook admin_menu :
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
private function define_admin_hooks() { $plugin_admin = new Text_Floating_Image_Admin( $this->get_plugin_name(), $this->get_version() ); $this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_styles' ); $this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_scripts' ); /* Ajout de l'entrée Text Floating Image dans le menu Réglages : Sur le hook admin_menu, on appelle la fonction add_plugin_admin_menu contenue dans admin/class-text-floating-image-admin.php Documentation : - http://christianelagace.com/wordpress/les-hooks-dans-wordpress/ - https://www.sitepoint.com/wordpress-hook-system/ - https://codex.wordpress.org/Plugin_API/Action_Reference/admin_menu - https://codex.wordpress.org/Administration_Menus */ $this->loader->add_action( 'admin_menu',//Le hook auquel nous avons recours $plugin_admin,//Une référence à la classe admin de notre plugin 'add_plugin_admin_menu'//La fonction appelée //laquelle se situe très logiquement dans la classe admin de notre plugin ); } |
Et continuons avec la fonction add_plugin_admin_menu() et sa suite :
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
/** * Ajout de l'entrée Text Floating Image dans le menu Réglages. * La fonction add_plugin_admin_menu est appelée sur le hook admin_menu * depuis la fonction define_admin_hooks() de includes/class-text-floating-image.php * Documentation : * - https://codex.wordpress.org/Plugin_API/Action_Reference/admin_menu * - https://codex.wordpress.org/Administration_Menus * - https://codex.wordpress.org/Function_Reference/add_options_page * * @since 1.0.0 */ public function add_plugin_admin_menu() { add_options_page( 'Text Floating Image Settings',//Le titre de la page 'Text Floating Image',//Le nom de l'entrée dans le menu Réglages 'manage_options',//la capacité requise pour avoir accès à la page //Documentation : https://codex.wordpress.org/Roles_and_Capabilities#manage_options $this->plugin_name,//Le petit nom du plugin array($this, 'display_plugin_setup_page')//La fonction appelée pour construire la page des paramètres ); } /** * Rendu de la page des paramètres. * * @since 1.0.0 */ public function display_plugin_setup_page() { include_once( 'partials/text-floating-image-admin-display.php' ); } |
Vous pouvez dès à présent constater que le menu Réglages comporte désormais une nouvelle entrée Text Floating Image, laquelle vous amène d’un clic sur une page encore désespérément vide mais que nous ne manquerons pas de remplir quand le moment sera venu.
Quoi, il n’est pas encore arrivé ce foutu moment ?
Ben non !
Pas t’encore petits scarabées !
Parce que si nos futurs utilisateurs disposent bien désormais d’un accès à notre page d’options, ils seraient sans conteste au comble de l’extase si nous songions à leur en offrir un autre sur la page du tableau de bord listant les extensions. Les occasions extatiques se faisant rares par les temps qui courent, il serait particulièrement cruel de les en priver d’autant que la chose est plutôt aisée à réaliser.
Or donc…
Ajout d’un lien vers les options sur la page des extensions
On s’appuie cette fois sur le filtre plugin_action_links_(plugin file name) dont la mission consiste très justement à réaliser ce que l’on désire si ardemment, c’est à dire obtenir un truc qui ressemble à ça :
Nous nous en retournons donc dans la fonction define_admin_hooks() de la classe includes/class-text-floating-image.php pour y rajouter ces lignes :
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
/** * Ajout d'un lien direct vers la gestion des paramètres du plugin sur la page des extensions * aux côtés des liens Désactiver et Modifier. * Sur le hook plugin_action_links_, on appelle la fonction add_plugin_action_links * contenue dans admin/class-text-floating-image-admin.php * Documentation : * https://codex.wordpress.org/Plugin_API/Filter_Reference/plugin_action_links_(plugin_file_name) * * La fonction plugin_basename retourne le chemin de notre extension depuis le dossier des plugins * En clair : * plugin_dir_path(__DIR__).$this->plugin_name.'.php' renvoie le chemin complet du fichier * text-floating-image.php situé à la racine du dossier de l'extension. * Et : * $plugin_basename = text-floating-image/text-floating-image.php. */ $plugin_basename = plugin_basename(plugin_dir_path(__DIR__).$this->plugin_name.'.php'); $this->loader->add_filter('plugin_action_links_'.$plugin_basename, $plugin_admin, 'add_plugin_action_links'); |
Et nous allons derechef insérer la fonction add_plugin_action_links() dans la classe admin/class-text-floating-image-admin.php :
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
/** * Ajout d'un lien direct vers la gestion des paramètres du plugin sur la page des extensions * aux côtés des liens Désactiver et Modifier. * La fonction add_plugin_action_links est appelée sur le hook plugin_action_links_ * depuis la fonction define_admin_hooks() de includes/class-text-floating-image.php * Documentation : * https://codex.wordpress.org/Plugin_API/Filter_Reference/plugin_action_links_(plugin_file_name) * * @param array $links : tableau des liens enregistrés dans WordPress * @return array : tableau augmenté de notre lien * @since 1.0.0 */ public function add_plugin_action_links($links) { /* * Documentation admin_url : https://codex.wordpress.org/Function_Reference/admin_url * Documentation __ : https://codex.wordpress.org/Function_Reference/_2 * */ $settings_link = array( '<a href="'.admin_url('options-general.php?page='.$this->plugin_name).'">'.__('Settings', $this->plugin_name).'</a>', ); return array_merge($settings_link, $links); } |
Un petit tour sur la page des extensions pour nous assurer que tout fonctionne et nous continuons valeureusement notre long chemin…
Cahier des charges
Avant que de nous lancer enfin tête baissée dans la réalisation effective de la page des options de notre extension, il nous faut encore lister les paramètres déterminants qui méritent le privilège d’y figurer, leur attribuer une valeur par défaut et trouver le moyen d’en informer WordPress.
Nul besoin de se torturer longuement le peu d’esprit dont nous disposons pour conclure que l’image est déterminée de prime abord par sa largeur, exprimée en pourcentage de la largeur de la page. Voilà donc qui constituera le premier des facteurs à renseigner.
Cependant, il est fréquent, et c’est d’ailleurs le cas pour ce blog, que le thème définisse pour le contenu une largeur relative par rapport au body. Dans cette configuration, cette largeur est couramment limitée par un max-width.
Ainsi, pour notre blog à nous, nous avons assez classiquement :
1 2 3 4 5 6 7 |
#main{ max-width: 1000px; width:90%; margin:auto; } |
Jusqu’à il y a peu, nous n’aurions pas franchement eu à nous soucier de ces détails. Mais, WordPress a eu l’excellente idée d’introduire dans sa version 4.4 la gestion responsive des images. Dans ce contexte, ces détails deviennent déterminants pour nous permettre de calculer les valeurs à insérer dans l’attribut sizes et il nous faut donc donner à l’utilisateur la possibilité de nous préciser ces paramètres.
Par ailleurs, il est indispensable de donner à ce même utilisateur l’opportunité de déterminer si, par défaut, l’alignement s’opère à gauche ou bien à droite.
Et dernier point tout au moins pour l’instant : il nous faut songer à donner accès aux marges gauche et droite de l’image et ce en fonction de l’alignement. Classiquement, dans le cas d’un alignement à gauche, on aura tendance à ménager une marge à droite pour que le texte évite de coller au bord de l’image. Et réciproquement…
Pour résumer, nous devrions avoir :
- Un premier groupe de trois champs permettant de définir :
- La largeur en pourcentage de l’image (une valeur de 45% par défaut me parait judicieuse).
- La largeur en pourcentage de la page (la valeur par défaut sera fixée à 100%).
- La largeur maximale de la page (une valeur de zéro signifiera que cette largeur n’est pas limitée et sera définie comme valeur par défaut).
- Une case à cocher fixant un alignement à droite (par défaut, l’alignement sera posé à gauche et la case non cochée).
- Un groupe définissant les marges gauche et droite de l’image dans le cas d’un alignement à gauche (marge gauche fixée à 0 et marge droite à 20px par défaut).
- Un groupe définissant les marges gauche et droite de l’image dans le cas d’un alignement à droite (marge gauche fixée à 20px et marge droite à 0 par défaut).
Initialisation des valeurs par défaut
Pour informer WordPress des valeurs par défaut affectées aux paramètres de notre extension, nous allons recourir à son API options. Par ce même biais, nous enregistrerons les modifications éventuellement apportées à ces valeurs par l’utilisateur. Il nous faut faire en sorte que WordPress garde une trace de nos valeurs par défaut de façon à ce que l’utilisateur puisse rétablir celles-ci s’il s’aperçoit qu’il a lui-même fait n’importe quoi.
Autrement dit, nous allons travailler avec un tableau de cette forme :
1 2 3 4 5 6 7 8 9 10 11 12 |
array( imageWidth=>45,//Largeur de l'image en pourcentage pageWidth=>100,//Largeur du contenu en pourcentage pageMaxWidth=>0,//largeur maximale du contenu alignRight=>0,//Alignement de l'image : 0 = alignement à gauche; 1 = alignement à droite left_marginLeft=>0,//Marge gauche dans le cas d'un alignement à gauche left_marginRight=>20,//Marge droite dans le cas d'un alignement à gauche right_marginLeft=>20,//Marge gauche dans le cas d'un alignement à droite right_marginRight=>0//Marge droite dans le cas d'un alignement à droite ) |
Lors de la première activation de notre plugin, nous enregistrerons ce tableau dans une option portant le nom de notre extension. Cette donnée sera un tableau de la forme :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
array( default=>(//Nos valeurs par défaut sont regroupées dans un tableau default imageWidth=>45, pageWidth=>100, pageMaxWidth=>0, alignRight=>0, left_marginLeft=>0, left_marginRight=>20, right_marginLeft=>20, right_marginRight=>0 ), //Les valeurs modifiables par l'utilisateur imageWidth=>45, pageWidth=>100, pageMaxWidth=>0, alignRight=>0, left_marginLeft=>0, left_marginRight=>20, right_marginLeft=>20, right_marginRight=>0 ) |
La façon la plus triviale de passer ces valeurs à WordPress reste de les enregistrer dans une page judicieusement nommée default-settings.php et soigneusement rangée dans le dossier includes de notre extension :
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php $default = array( 'imageWidth'=>45, 'pageWidth'=>100, 'pageMaxWidth'=>0, 'alignRight'=>0, 'left_marginLeft'=>0, 'left_marginRight'=>20, 'right_marginLeft'=>20, 'right_marginRight'=>0, ); |
Nous n’avons plus alors qu’à mettre en place la procédure d’activation du plugin dans le fichier class-text-floating-image-activator.php prévu à cet effet :
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
class Text_Floating_Image_Activator { /** * Enregistrement des paramètres par défaut de notre plugin * * @since 1.0.0 */ public static function activate() { $plugin_name = 'text-floating-image'; //Les valeurs par défaut sont stockées dans un tableau nommé $default //initialisé dans la page includes/default-settings.php require_once plugin_dir_path(dirname(__FILE__ )).'includes/default-settings.php'; if (get_option($plugin_name)) { //Si l'extension a déjà été activée par le passé //on récupère les options enregistrées $options = get_option($plugin_name); //On écrase les valeurs par défaut $options['default'] = $default; //On merge les tableaux //Documentation : https://codex.wordpress.org/Function_Reference/wp_parse_args $options = wp_parse_args($options, $default); //On met à jour la base de données update_option($plugin_name, $options); } else { //S'il s'agit d'une première activation $options = $default; $options['default'] = $default; //On enregistre dans la base de données add_option($plugin_name, $options); } } } |
Après désactivation (si elle était activée) et réactivation de l’extension, vous devriez découvrir en fouillant la table wp_options de la base de donnée de votre installation WordPress une nouvelle ligne text-floating-image dont la valeur remise en forme pour être plus lisible ressemble à ça :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
a:9:{ s:19:"imageWidth";i:45; s:13:"pageWidth";i:100; s:8:"pageMaxWidth";i:0; s:10:"alignRight";i:0; s:16:"left_marginLeft";i:0; s:17:"left_marginRight";i:20; s:17:"right_marginLeft";i:20; s:18:"right_marginRight";i:0; s:7:"default";a:8{ s:19:"imageWidth";i:45; s:13:"pageWidth";i:100; s:8:"pageMaxWidth";i:0; s:10:"alignRight";i:0; s:16:"left_marginLeft";i:0; s:17:"left_marginRight";i:20; s:17:"right_marginLeft";i:20; s:18:"right_marginRight";i:0; } } |
Du ménage à faire
Nous venons de créer une nouvelle entrée dans la base de WordPress. Le moins que l’on puisse faire en cas de suppression de notre extension est de songer à effacer cette donnée sans plus d’utilité. Une très légère intervention sans douleur dans le fichier uninstall.php logé à la racine du dossier de notre plugin et le tour est joué :
27 28 29 30 31 32 33 34 35 36 37 |
// If uninstall not called from WordPress, then exit. if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) { exit; } else { //On supprime de la table wp_options de la base de données de Wordpress //la ligne text-floating-image chargée de stocker les valeurs par défaut //et les paramètres utilisateur delete_option( 'text-floating-image' ); } |
Avant que de vous précipiter vous assurer de la validité de la chose en supprimant l’extension comme ça pour voir, n’oubliez pas de faire un back-up du dossier text-floating-image au risque de perdre tout votre travail : WordPress ne fait pas de détail et détruit sans complexe mais à raison le dossier d’une extension lorsque celle-ci est supprimée !
Construction de la page
Tout semble enfin prêt désormais pour nous attaquer à l’écriture de notre page d’options. Oui, je sais, il serait plus que temps !
Je vous livre ici l’intégralité des codes php, css et js commentés ainsi qu’un aperçu du résultat.
Rendez-vous après tout ça pour un petit debriefing.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
<?php /** * Provide a admin area view for the plugin * * This file is used to markup the admin-facing aspects of the plugin. * * @link onfaitdessites.fr * @since 1.0.0 * * @package Text_Floating_Image * @subpackage Text_Floating_Image/admin/partials */ ?> <div class="<?php echo $this->plugin_name;?>-wrapper"> <h2><?php esc_attr_e("Text Floating Image Settings", $this->plugin_name); ?> </h2> <form method="post" name="<?php echo $this->plugin_name;?>-options_form" action="options.php"> <?php //Récupération des paramètres enregistrés $options = get_option($this->plugin_name); $imageWidth = $options['imageWidth']; $pageWidth = $options['pageWidth']; $pageMaxWidth = $options['pageMaxWidth']; $alignRight = $options['alignRight']; $left_marginLeft = $options['left_marginLeft']; $left_marginRight = $options['left_marginRight']; $right_marginLeft = $options['right_marginLeft']; $right_marginRight = $options['right_marginRight']; settings_fields($this->plugin_name); ?> <!-- Fieldset Général --> <fieldset> <legend><?php esc_attr_e("General", $this->plugin_name); ?></legend> <!-- Image Width --> <p> <label for="<?php echo $this->plugin_name;?>-imageWidth"> <?php esc_attr_e("Image width in percent", $this->plugin_name); ?> </label> <span> : <input type="number" name="<?php echo $this->plugin_name;?>[imageWidth]" value="<?php echo $imageWidth; ?>" data-default="<?php echo $options['default']['imageWidth']; ?>" min="1" max="100" onfocus="this.select()" autofocus /> % </span> <span> (<?php esc_attr_e('Default', $this->plugin_name); ?> : <?php echo $options['default']['imageWidth']; ?>%) </span> </p> <!-- Page Width --> <p> <label for="<?php echo $this->plugin_name;?>-percent_width"> <?php esc_attr_e('Page width in percent', $this->plugin_name); ?> </label> <span> : <input type="number" name="<?php echo $this->plugin_name;?>[pageWidth]" value="<?php echo $pageWidth; ?>" data-default="<?php echo $options['default']['pageWidth']; ?>" min="1" max="100" onfocus="this.select()" /> % </span> <span> (<?php esc_attr_e('Default', $this->plugin_name); ?> : <?php echo $options['default']['pageWidth']; ?>%) </span> </p> <!-- Page Width --> <p> <label for="<?php echo $this->plugin_name;?>-pageMaxWidth"> <?php esc_attr_e('Page max width', $this->plugin_name ); ?> </label> <span> : <input type="number" name="<?php echo $this->plugin_name;?>[pageMaxWidth]" value="<?php echo $pageMaxWidth; ?>" data-default="<?php echo $options['default']['pageMaxWidth']; ?>" onfocus="this.select()" /> px </span> <span> <?php echo '('.$options['default']['pageMaxWidth'].' '; esc_attr_e('if the page width is not limited', $this->plugin_name); echo '. '; esc_attr_e('Default', $this->plugin_name); echo ' : '.$options['default']['pageMaxWidth'].')'; ?> </span> </p> </fieldset> <!-- Fieldset Alignment --> <fieldset> <legend><?php esc_attr_e('Alignment', $this->plugin_name ); ?></legend> <label for="<?php echo $this->plugin_name;?>-alignRight"> <?php esc_attr_e('Align to the right', $this->plugin_name ); ?> : <input type="checkbox" name="<?php echo $this->plugin_name;?>[alignRight]" data-default="<?php echo $options['default']['alignRight']; ?>" <?php if ($alignRight == 1) echo "checked";?> /> </label> </fieldset> <!-- Wrapper Fieldsets Margins --> <div> <!-- Fieldset Left margins --> <fieldset> <legend><?php esc_attr_e('Left margins', $this->plugin_name ); ?></legend> <p> <?php esc_attr_e('Margins in pixels when aligned to the left.', $this->plugin_name ); ?> </p> <div> <!-- Left --> <p> <label for="<?php echo $this->plugin_name;?>-left_marginLeft"> <?php esc_attr_e("Left", $this->plugin_name); ?> </label> <span> : </span> <input type="number" name="<?php echo $this->plugin_name;?>[left_marginLeft]" value="<?php echo $left_marginLeft; ?>" data-default="<?php echo $options['default']['left_marginLeft']; ?>" min="0" onfocus="this.select()" /> </p> <!-- Right --> <p> <label for="<?php echo $this->plugin_name;?>-left_marginRight"> <?php esc_attr_e("Right", $this->plugin_name); ?> </label> <span> : </span> <input type="number" name="<?php echo $this->plugin_name;?>[left_marginRight]" value="<?php echo $left_marginRight; ?>" data-default="<?php echo $options['default']['left_marginRight']; ?>" min="0" onfocus="this.select()" /> </p> </div> </fieldset> <!-- Fieldset right margins --> <fieldset> <legend><?php esc_attr_e('Right margins', $this->plugin_name ); ?></legend> <p> <?php esc_attr_e('Margins in pixels when aligned to the right.', $this->plugin_name ); ?> </p> <div> <!-- Left --> <p> <label for="<?php echo $this->plugin_name;?>-right_marginLeft"> <?php esc_attr_e("Left", $this->plugin_name); ?> </label> <span> : </span> <input type="number" name="<?php echo $this->plugin_name;?>[right_marginLeft]" value="<?php echo $right_marginLeft; ?>" data-default="<?php echo $options['default']['right_marginLeft']; ?>" min="0" onfocus="this.select()" /> </p> <!-- Right --> <p> <label for="<?php echo $this->plugin_name;?>-right_marginRight"> <?php esc_attr_e("Right", $this->plugin_name); ?> </label> <span> : </span> <input type="number" name="<?php echo $this->plugin_name;?>[right_marginRight]" value="<?php echo $right_marginRight; ?>" data-default="<?php echo $options['default']['right_marginRight']; ?>" min="0" onfocus="this.select()" /> </p> </div> </fieldset> </div> <a class="button-secondary" href="#" title="Reset">Reset</a> <?php submit_button(); ?> </form> </div> |
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
/** * All of the CSS for your admin-specific functionality should be * included in this file. */ .text-floating-image-wrapper { margin: 2em 2em 0 1em; font-weight: bold; max-width: 630px; /*On cache le wrapper le temps de calculer la largeur des labels*/ position: absolute; top:-20000px; } .text-floating-image-wrapper fieldset{ border: 1px #888888 solid; border-radius: 5px; padding: 0.5em 1em 1em 1em; margin-top: 2em; } .text-floating-image-wrapper legend{ font-size: 1.2em; } .text-floating-image-wrapper p{ margin: 1em 0; } .text-floating-image-wrapper input[type='number'] { font-size: 1em; width: 4em; height: 2em; text-align: right; padding: 0; } /*General Fieldset*/ .text-floating-image-wrapper form > fieldset:nth-of-type(1) > p label { display: inline-block; } .text-floating-image-wrapper fieldset:nth-of-type(1) > p span { white-space: nowrap; display: inline-block; width: 90px; vertical-align: middle; } .text-floating-image-wrapper fieldset:nth-of-type(1) > p span:last-child { font-weight: normal; font-style: italic; display: inline; vertical-align: middle; } /*Alignment Fieldset*/ .text-floating-image-wrapper fieldset:nth-of-type(2) { width:45%; min-width: 230px; } .text-floating-image-wrapper fieldset:nth-of-type(2) > label { margin:0.5em 0; } /*Margin Fieldset*/ .text-floating-image-wrapper div { display: flex; justify-content: space-between; flex-wrap: wrap; } .text-floating-image-wrapper div fieldset { min-width: 230px; width:45%; text-align: center; } .text-floating-image-wrapper div fieldset > p:nth-child(2){ font-weight: normal; font-style: italic; margin-top: 0.5em; } .text-floating-image-wrapper div fieldset div{ display: flex; justify-content: space-between; flex-wrap: wrap; text-align: center; } .text-floating-image-wrapper div fieldset div p{ margin:0.5em auto; text-align: left; /* http://stackoverflow.com/questions/20626685/better-way-to-set-distance-between-flexbox-items/20695377#20695377 */ border-left: 0.5em solid transparent; border-right: 0.5em solid transparent; } .text-floating-image-wrapper div fieldset label{ display: inline-block; overflow: hidden; } .text-floating-image-wrapper div fieldset span, .text-floating-image-wrapper div fieldset input[type='number']{ vertical-align: middle; } .text-floating-image-wrapper .button-secondary { margin-top: 2em; } @media screen and (max-width: 350px){ .text-floating-image-wrapper fieldset:nth-of-type(1) > p span:last-child { white-space: normal; } } |
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
(function($) { 'use strict'; $( window ).load(function() { //Reset $('.button-secondary').on('click',function(){ $('[data-default]').each(function(){ var $this = $(this); $this.val($this.data('default')); }); var $checkbox = $('input[type=checkbox]'); var align = $checkbox.data('default') $checkbox.prop('checked',(align == 1)); }); //Calcul de la largeur des labels setLabelWidth($('.text-floating-image-wrapper fieldset').first()); setLabelWidth($('.text-floating-image-wrapper div').first()); //On montre le wrapper $('.text-floating-image-wrapper').css('position','static'); }); function setLabelWidth($el) { var labelWidth = 0; $el.find('label').each(function(){ labelWidth = Math.max(labelWidth,$(this).width()) }).css('width',labelWidth); } })(jQuery); |
Mouais ! Ça fait beaucoup d’un coup !
Reprenons donc calmement et dans l’ordre.
- La structure html du fichier php est parfaitement classique : un div wrapper encadre un formulaire lequel contient un titre, 4 groupes de champs (des fieldsets, quoi !), un bouton Reset et un bouton submit pour conclure. Coté php, on démarre en récupérant les paramètres enregistrés via la fonction get_options() de WordPress et en appelant la fonction setting_fields() (dont vous constaterez qu’elle est remarquablement documentée). Les petits curieux auront sans doute remarqué l’utilisation répétée de la fonction esc_attr_e qui prépare notre extension à l’internationalisation. Chaque champ est caractérisé par son nom de la forme text-floating-image[nom_option]. Son attribut value reprend la donnée correspondante enregistrée tandis qu’un attribut data-default stocke sa valeur par défaut de manière à faciliter le reset.
- En ce qui concerne la partie css, rien de particulier à signaler me semble t-il si ce n’est qu’à l’initialisation le div wrapper est positionné en absolute avec un top à -20000px afin de le dissimuler aux regards le temps pour le fichier javascript d’opérer quelques menus calculs.
- Le volet javascript justement se charge d’assurer le reset, d’établir la largeur maximale pour chaque groupe de labels afin de réaliser un alignement au cordeau et d’afficher le tout en rétablissant la position du div wrapper en static.
Enregistrement des options
Dans l’état actuel, si vous faites mumuse avec cette page et tentez d’enregistrer vos modifications, vous allez au devant d’une cruelle déception. Vous devriez en effet vous retrouver face à une page listant toutes les options de WordPress sans aucun rapport avec vos attentes. Le fait est que nous n’avons encore rien dit au cœur de WordPress quant à ce que nous souhaitions faire de toutes ces valeurs. Pour y remédier, il nous faut recourir à la fonction register_setting() non sans avoir au préalable assurer une validation sans faille des données.
Retour donc dans notre classe admin/class-text-floating-image-admin.php pour y ajouter les lignes qui suivent :
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 |
/** * Validation des données de la page d'options. * La fonction est appelée en callback par la fonction options_update() qui suit * @param array $input : tableau des valeurs renvoyées par le formulaire * @return array $valid : tableau des valeurs éventuellement corrigées * * @since 1.0.0 */ public function validate($input) { $valid = array(); if (isset($input['imageWidth']) && is_numeric($input['imageWidth'])) { $round = round($input['imageWidth']); if ($round > 0 && $round < 101) $valid['imageWidth'] = $round; } if (isset($input['pageWidth']) && is_numeric($input['pageWidth'])) { $round = round($input['pageWidth']); if ($round > 0 && $round < 101) $valid['pageWidth'] = $round; } if (isset($input['pageMaxWidth']) && is_numeric($input['pageMaxWidth'])) { $round = round($input['pageMaxWidth']); if ($round >= 0) $valid['pageMaxWidth'] = $round; } $valid['alignRight'] = (isset($input['alignRight']))?1:0; if (isset($input['left_marginLeft']) && is_numeric($input['left_marginLeft'])) { $round = round($input['left_marginLeft']); if ($round >= 0) $valid['left_marginLeft'] = $round; } if (isset($input['left_marginRight']) && is_numeric($input['left_marginRight'])) { $round = round($input['left_marginRight']); if ($round >= 0) $valid['left_marginRight'] = $round; } if (isset($input['right_marginLeft']) && is_numeric($input['right_marginLeft'])) { $round = round($input['right_marginLeft']); if ($round >= 0) $valid['right_marginLeft'] = $round; } if (isset($input['right_marginRight']) && is_numeric($input['right_marginRight'])) { $round = round($input['right_marginRight']); if ($round >= 0) $valid['right_marginRight'] = $round; } $valid = wp_parse_args($valid, get_option($this->plugin_name)); return $valid; } /** * Mise à jour des options. * La fonction options_update est appelée sur le hook admin_init * depuis la fonction define_admin_hooks() de includes/class-text-floating-image.php * Documentation : * https://codex.wordpress.org/Function_Reference/register_setting * * @since 1.0.0 */ public function options_update() { register_setting($this->plugin_name, $this->plugin_name, array($this, 'validate')); } |
On enchaîne sans traîner en éditant une fois de plus la fonction define_admin_hooks() de notre classe maîtresse includes/class-text-image-floating.php :
191 192 193 194 195 196 197 198 |
/** * Mise en place de l'enregistrement des options sur le hook admin_init * qui appelle la fonction options_update() définie dans * admin/class-text-floating-image-admin.php */ $this->loader->add_action('admin_init', $plugin_admin, 'options_update'); |
Et le tour est joué ! Enfin ! Notre extension dispose d’une page de paramètres parfaitement fonctionnelle !
Je vous invite néanmoins à torturer la chose avec l’application d’un psychopathe zélé afin d’en débusquer les éventuelles failles et/ou limites.
Conclusion provisoire
Récapitulons !
En résumé, nous avons jusqu’ici :
- affiché une description digne de ce nom pour notre extension;
- introduit un premier accès à la page d’options dans le menu Réglages;
- établi un second accès direct à ces mêmes options depuis la page des extensions du tableau de bord;
- créé une nouvelle entrée dans la base de données de WordPress pour y stocker les valeurs utilisateur ainsi que les valeurs par défaut de nos options;
- prévu l’élimination de ladite entrée en cas de suppression de l’extension;
- construit la page d’options;
- assuré la validation et l’enregistrement des modifications apportées par l’utilisateur.
C’est un bon début mais ce n’est qu’un début…
Si vous avez encore quelque énergie en réserve, la soif de savoir et de solides notions d’anglais, je vous invite à les mettre à profit en picorant ici et là dans la courte bibliographie que voici :
L’API Settings selon le Codex de WordPress.
Un tutorial de Mossieur Otto qui date un peu mais fait toujours référence.
Un tutorial plus récent, rédigé par David hayes.
Et quand vous aurez fini de digérer, je vous invite à poursuivre avec moi notre longue route…