MVC avec Elementor et Timber

Dans cet article je vais vous montrer que l’ajout de Timber à vos widgets Elementor peut s’avérer particulièrement judicieux lorsqu’on souhaite pousser une architecture MVC dans notre WordPress.

Pour ceux qui ne connaissent pas Timber, je vous recommande l’article de GeekPress ou la présentation de Maxime Bernard-Jacquet. Je pars du principe que tout le monde connaît Elementor. Un page Builder qui monte de plus en plus.

Je travail depuis peu avec Elementor qui est un vrai atout en matière d’administration Front. C’est intuitif, simple et c’est ce que demande le client. L’ajout de widgets sur mesure est assez aisé. Mais c’est l’insertion du html dans le php qui me dérangeait le plus. J’utilise Timber de base sur tout mes projets WordPress et je trouvais dommage de ne pas aller plus loin avec. Notamment sur son utilisation au sein de mes plugins.

Je passe volontairement sur la création du plugin Elementor qui rendrait cet article imbuvable. J’ai déjà un style d’écriture qui ressemble à celui de mon chat, alors évitons de se faire plus de mal ensemble. Pour ceux qui seraient intéresse il y à l’article de Marie Comet qui décrit pas à pas comment s’y prendre. La structure de mon plugin ci-dessous est très similaire à la sienne du coup vous ne serez pas perdu.

/elementor-widgets
 /controllers
  - FrontControllers.php
 /views
  - button.twig
 /widgets
  - button.php
- elementor-widgets.php
- plugin.php
architecture

La première chose que nous allons faire c’est ajouter le dossier de nos vues pour indiquer à Timber ou trouver les fichiers twig de nos widgets. On fait ça lors de l’instanciation de notre plugin dans « elementor-widgets.php« 

    /**
     * Constructor
     *
     * @since 1.0.0
     * @access public
     * @author elementor-widgets
     */
    public function __construct() {

        // Load translation
        add_action( 'init', array( $this, 'i18n' ) );

        // Load Timber
        add_action( 'init', array( $this, 'timber' ) );

        require_once(__DIR__ . '/controllers/FrontController.php');
    }

    /**
     * Load Textdomain
     *
     * Load plugin localization files.
     * Fired by `init` action hook.
     *
     * @since 1.0.0
     * @access public
     * @author elementor-widgets
     */
    public function i18n() {
        load_plugin_textdomain( 'elementor-widgets' );
    }

    /**
     * Load Timber
     *
     * Load Class Timber.
     * Fired by `init` action hook.
     *
     * @since 1.0.0
     * @access public
     * @author elementor-widgets
     */
    public function timber() {

        // Timber twig file location
        if ( ! class_exists( 'Timber\Timber' )){
            return;
        }
        Timber::$locations = plugin_dir_path( __FILE__ ) . 'views/';
    }

Le nouveau répertoire est ajouté, maintenant reste à indiquer à Elementor qu’il doit utiliser Timber pour le rendu des widgets. On fait ça logiquement dans la fonction « render() » de ce dernier:

    /**
     * Render the widget output on the frontend.
     *
     * Written in PHP and used to generate the final HTML.
     *
     * @since 1.1.0
     *
     * @access protected
     * @author elementor-widgets
     */
    protected function render() {
        $settings = $this->get_settings_for_display();

        $frontController = new FrontController($settings);
        $frontController->display('button.twig');
    }

Ici à la différence d’écrire notre HTML, j’instancie l’objet FrontController dans lequel je lui passe le nom du fichier twig à utiliser pour la vue. Pour faire simple, j’ai simplement crée un controller « FrontController » qui me sert à récupérer les donnés du widget, les contrôler et les envoyer à la vue. Voici à quoi ressemble la classe :

<?php

namespace Jhiki\Controllers;

use Timber\Timber;

if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
class FrontController {

    private $settings = array();

    /**
     * FrontController constructor.
     *
     * @param $settings
     *
     * @access public
     *
     * @since 1.0.0
     *
     * @author elementor-widgets
     */
    public function __construct($settings)
    {
        $this->setSettings($settings);
    }

    /**
     * @param $template
     *
     * @access public
     *
     * @since 1.0.0
     *
     * @author elementor-widgets
     */
    public function display($template)
    {
        $context = Timber::get_context();

        $context['settings'] = $this->settings;
        Timber::render( array( $template ), $context );
    }

    /**
     * Setter settings
     *
     * @param $settings
     *
     * @access public
     *
     * @since 1.0.0
     *
     * @author elementor-widgets
     */
    public function setSettings($settings)
    {
        $this->settings = $settings;
    }
}

Dans cette classe on va juste se concentrer sur la méthode « display ». Celle-ci attends le nom du template comme paramètre.
Ensuite on charge le context de Timber pour y ajouter nos nouvelles données. Puis on utilise la méthode render pour les passer à la vue. Ce truc là on le fait de base sur notre thème donc absolument rien de nouveau ni de compliqué.

Et voilà ! On vient de mettre en place une vraie architecture MVC pour nos widgets Elementor. Je précise que le FrontController est une toute petite basounette qui ne demande qu’à être amélioré. J’y ai mis le strict minimum.

A vous de jouer.