Widgets

La création de nouveaux widgets ne pose pas de problèmes particuliers. Il faut créer une classe fille de la classe « WP_Widget » et y redéfinit quatre méthodes dont le constructeur.

Il faudra s’assurer que le thème accepte les blocs HTML dynamiques, sinon il sera impossible d’installer le widget dans le site (le menu Apparence / Widgets n’existant pas).

La structure globale est (outre l’en-tête habituelle) :

<?php

class Widget_pagesJMC extends WP_Widget {
  private $infos;

  function __construct() {
    /* ... */
  }

  public function widget($args, $instance) {
    /* ... */
  }

  public function form( $instance ) {
    /* ... */
  }

  public function update( $new_instance, $old_instance ) {
    /* ... */
  }
} // class Widget_pagesJMC

add_action('widgets_init',
           create_function('', 'return register_widget("Widget_pagesJMC");')
);

Pour notre exemple, la classe est nommée « Widget_pagesJMC », il s’agit d’un widget affichant le titre des dernières pages modifiées dans le site.

Pour notre exemple, on a placé aussi une propriété privée « $infos » qui est un tableau servant à partager des informations entre les méthodes. Les méthodes seront détailles plus loin.

A la fin du listing, on voit que la classe est enregistrée au moment « widget_init » par la fonction « register_widget » qui crée une instance de la classe.

Remarque

A partir de PHP 5.3, on aurait pu écrire plus simplement :

add_action( 'widgets_init',
    function() {
      register_widget( 'Widget_pagesJMC' );
    }
); 

Voici, pour notre exemple, le détail des méthodes.

Fonction «  __construct »

C’est le constructeur de la classe. Il s’agit essentiellement d’appeler le constructeur de la classe parente en lui donnant les informations nécessaires et, éventuellement, de placer quelques informations locales.

function __construct() {
  parent::__construct(
    'wPages_JMC',
    esc_html__( 'Pages récentes'),
    array('description'=>esc_html__( 'Affiche la liste des pages récentemment modifiées')) 
  );
  $this->infos= array (
    'nombre'=> '5',
  );
}

La fonction « esc_html__() » nettoie à partir de son paramètre les caractères qui on une signification particulière en HTML (comme ‘<« ). C’est proche de la fonction PHP htmlspecialchars.
De plus, un second paramètre peut être utilisé pour spécifier la traduction.

Le premier paramètre passé au constructeur parent est l’identificateur du widget (il sera enregistré sous ce nom, préfixé par « widget_ » dans la table « options » de la base de données et converti en minuscules). Le second paramètre est le nom du widget qui apparaitra dans le menu Apparence / Widgets du tableau de bord. Le troisième paramètre est un tableau d’options, en l’occurrence il s’agit de la description du widget dans le tableau de bord.

Pour notre exemple on a ajouté l’affectation à la propriété « $info[‘nombre’] » de la valeur 5. Ce sera le nombre par défaut de pages affichées.

Voir : https://developer.wordpress.org/reference/classes/wp_widget/__construct/

Fonction « widget »

Il s’agit là de la fonction qui affichera le widget dans le site.

Elle reçoit deux paramètres, le premier est le tableau des arguments du widget (chaînes comme avant / après le titre, avant / après le widget). Le second est l’instance qui contient les informations transmises par le formulaire du widget dans le tableau de bord.

Pour notre exemple, on a placé cet affichage dans un fichier séparé. On le verra en bas de cette page.

public function widget($args, $instance) {
  include plugin_dir_path( __FILE__ ).'/wid-pages.php';
}

Le fichier d’affichage du widget est « wid-pages.php ».

Fonction « form »

Cette fonction affiche le widget dans le tableau de bord, c’est donc généralement un formulaire.  La fonction reçoit un paramètre qui est l’instance de la classe, il s’agit d’un tableau qui contient les éventuelles valeurs précédentes du formulaire.

public function form( $instance ) {
  foreach ($this->infos as $k => $v) {
    if (!isset($instance[$k])) $instance[$k]= $v;
  }
  $title= !empty($instance['title']) ? $instance['title'] : esc_html__( 'Dernières pages');
 ?>
 <p>
 <label for="<?php echo esc_attr( $this->get_field_id('title') ); ?>">
   <?php esc_attr_e( 'Title:'); ?>
 </label>
 <input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"
        name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>"
        type="text" value="<?php echo esc_attr( $title ); ?>"
 >
 </p>
 <p>
 <label for="<?php echo esc_attr( $this->get_field_id('nombre') ); ?>">
   Nombre :
 </label>
 <input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'nombre' ) ); ?>"
        name="<?php echo esc_attr( $this->get_field_name( 'nombre' ) ); ?>"
        type="number" value="<?php echo esc_attr( $instance['nombre'] ); ?>"
 >
 </p>
 <?php
}

Au début on récupère, si elles existent les précédentes valeurs du formulaire et sinon on les initialise à partir des valeurs par défaut depuis la propriété « $info ».

Ensuite on a des champs de formulaire classiques. Il faut s’assurer que les attributs « name » et « id » sont conformes à ceux de l’instance par l’utilisation des méthodes « get_field_id » et « get_field_name ».

On remarquera que l’on a pas placé cela dans un élément « form » et qu’il n’y a pas de bouton de validation.

Fonction « update »

Cette dernière fonction contrôle les valeurs saisies dans le formulaire, éventuellement les nettoie. Elle reçoit un premier paramètre qui est l’instance ces valeurs saisies et un second qui est l’instance des valeurs qui existaient avant la mise à jour par le formulaire. Elle renvoie l’instance définitive à utiliser.

public function update( $new_instance, $old_instance ) {
 $instance= array();
 $instance['title']= (!empty($new_instance['title'])) ? strip_tags($new_instance['title']): '';
 $nbr= intval( strip_tags($new_instance['nombre'], 10) );
 $instance['nombre']= $nbr < 0 ? 0 : $nbr;
 return $instance;
}

On prépare une instance locale à partir des valeurs contrôlées et nettoyées du formulaire (1° paramètre). Le second paramètre n’est pas utilisé ici.

En savoir plus :
structure générale https://codex.wordpress.org/Widgets_API

la classe WP_Widget https://developer.wordpress.org/reference/classes/wp_widget/

Pour notre exemple, affichage du widget

Il s’agit donc d’afficher les pages les plus récentes. Le code est un peu long, c’est pourquoi il est placé dans un fichier séparé mais inclus, il appartient donc à l’instance de la classe et a accès aux paramètres de la fonction « widget » soient « $args » et « $instance ».

Pour notre exemple, pour « $args » seuls $args[‘before_title’] et $args[‘after_title’] sont utilisés.

<?php
  $nbr= intval($instance['nombre'], 10);
  if ($nbr > 0) {
    $tabPages= get_pages();
   $dateMod= array();
   foreach ($tabPages as $v) {
     $dateMod[] = $v->post_modified;
   }
   array_multisort($dateMod, SORT_DESC, $tabPages);
   $tabPages= array_slice($tabPages, 0, $nbr);
?>
<div class="widget liste-pages liste-pages-recentes">
 <?php
 if ( !empty( $instance['title'] ) ) {
   echo $args['before_title']
       . apply_filters( 'widget_title', $instance['title'] )
       . $args['after_title'];
 }
 ?>
 <ul>
 <?php
  foreach ($tabPages as $page):
     $dhT= date("d-m-Y à H\h i", strtotime ($page->post_modified));
 ?>
   <li>
     <a href="<?=get_page_link( $page->ID ) ?>"><?=$page->post_title ?></a><br>
     modifiée le <?=$dhT?>
   </li>
 <?php endforeach; ?>
 </ul>
</div>
<?php
  } //if ($nbr > 0)

On place dans « $nbr » le nombre de pages à afficher que l’on obtient depuis l’instance. Si ce nombre est supérieur à 0 on appelle la fonction WordPress « get_pages » pour avoir la liste des pages du site ordonnée selon les dates de dernière modification.

Ensuite on affiche le widget dont la liste des pages par la boucle « foreach ».