Création d’un module Magento de formulaire d’abonnement Mailjet

Cet article explique comment créer un module Magento de formulaire d’abonnement à une newsletter pour Mailjet.

Le module Feub Mailjetform dans l'interface d'admin de Magento
Le module Feub Mailjetform dans l’interface d’admin de Magento

Cette semaine j’ai du effectuer une migration (c’est un bien grand mot) de Mailchimp vers Mailjet, le leader européen en matière de service pour l’emailing marketing, principalement pour des raisons de coût, car il faut l’avouer, il n’y a pas photo avec Mailchimp qui est vite cher pour des petits/moyens volumes.

Bref, après la configuration du back office, une des choses les plus naturelles à faire est d’intégrer un formulaire d’abonnement, et bien qu’elle ne fut pas ma surprise de ne rien trouver du côté de Mailjet. Il existe bien un petit générateur de widget très minimaliste qui crée un bout de code iframe à insérer dans son code, un peu léger car pas moyen de personnaliser l’apparence du formulaire. L’autre solution, c’est de taper dans l’API et d’écrire son propre code.

J’ai donc cherché pas mal en ligne pour trouver un module pour Magento, en vain. Je me suis rabattu sur du PHP lambda à intégrer, un bout de code pour ajouter un banal formulaire de souscription à une newsletter Mailjet. Rien, même après plusieurs heures.

J’ai donc décidé que j’allais écrire mon propre module Magento en utilisant l’API de Mailjet.

Architecture du module

L’architecture du module est typique Magento / Zend, sous app/, créer l’arborescence suivante :

  • code/local/Feub/Mailjetform/
    • controllers/AjaxController.php
    • etc/
      • config.xml
      • system.xml
    • Helper/Data.php
    • Model/
      • Listsoptions.php
      • Mailjetform.php
      • Options.php
  • design/frontend/default/default/template/page/html/mailjetform.phtml
  • etc/modules/Feub_Mailjetform.xml

A noter que pour aller plus vite, je n’ai pas crée de block / layout intégré à mon template, mais j’insère un shortcode dans un bloc statique qui fera le rendu du template mailjetform.phtml.

Feub_Mailjetform.xml

On commence par déclarer notre nouveau module. Peu importe le nom du fichier dans app/etc/modules, tous les fichiers XML sont lus, mais il est toujours mieux de suivre les conventions.

<?xml version="1.0"?>
<config>
    <modules>
        <Feub_Mailjetform>
            <active>true</active>
            <codePool>local</codePool>
        </Feub_Mailjetform>
    </modules>
</config>

config.xml

Le fichier de configuration globale du module.

<?xml version="1.0"?>
<config>
    <modules>
        <Feub_Mailjetform>
            <version>0.0.1</version>
        </Feub_Mailjetform>
    </modules>
    <frontend>
        <routers>
            <mailjetform>
                <use>standard</use>
                <args>
                    <module>Feub_Mailjetform</module>
                    <frontName>mailjetform</frontName>
                </args>
            </mailjetform>
        </routers>
    </frontend>
    <global>
        <helpers>
            <mailjetform>
                <class>Feub_Mailjetform_Helper</class>
            </mailjetform>
        </helpers>
        <models>
             <mailjetform>
                <class>Feub_Mailjetform_Model</class>
             </mailjetform>
        </models>
    </global>
    <adminhtml>
        <acl>
            <resources>
                <admin>
                    <children>
                        <system>
                            <children>
                                <config>
                                    <children>
                                        <mailjetform_options>
                                            <title>Formulaire Mailjet</title>
                                        </mailjetform_options>
                                    </children>
                                </config>
                            </children>
                        </system>
                    </children>
                </admin>
            </resources>
        </acl>
    </adminhtml>
    <default>
        <mailjetform_options>
            <conf_api>
                <conf_api_key_field>Clé API</conf_api_key_field>
                <conf_api_secret_field>Clé secrète</conf_api_secret_field>
                <conf_api_debug_field>1</conf_api_debug_field>
            </conf_api>
        </mailjetform_options>
    </default>
</config>

system.xml

Le fichier system.xml permet de configurer le back office Magento de notre module.

<?xml version="1.0"?>
<config>
    <tabs>
        <mailjetform translate="label" module="mailjetform">
            <label>Feub</label>
            <sort_order>2</sort_order>
        </mailjetform>
    </tabs>
    <sections>
        <mailjetform_options translate="label" module="mailjetform">
            <label>Formulaire Mailjet</label>
            <tab>mailjetform</tab>
            <frontend_type>text</frontend_type>
            <sort_order>1</sort_order>
            <show_in_default>1</show_in_default>
            <show_in_website>1</show_in_website>
            <show_in_store>1</show_in_store>
            <groups>
                <conf_api translate="label">
                    <label>Configuration Mailjet</label>
                    <frontend_type>text</frontend_type>
                    <sort_order>1</sort_order>
                    <show_in_default>1</show_in_default>
                    <show_in_website>1</show_in_website>
                    <show_in_store>1</show_in_store>
                    <fields>
                        <conf_api_key_field>
                            <label>Clé d'API</label>
                            <frontend_type>text</frontend_type>
                            <sort_order>1</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                            <comment>Votre clé API disponible sur votre compte Mailjet à cette URL https://fr.mailjet.com/account/api_keys</comment>
                        </conf_api_key_field>
                        <conf_api_secret_field>
                            <label>Clé secrete</label>
                            <frontend_type>text</frontend_type>
                            <sort_order>2</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                            <comment>Votre clé secrète disponible sur votre compte Mailjet à cette URL (https://fr.mailjet.com/account/api_keys</comment>
                        </conf_api_secret_field>
                        <conf_api_list_id_field>
                            <label>ID de la liste</label>
                            <frontend_type>select</frontend_type>
                            <source_model>mailjetform/listsoptions</source_model>
                            <sort_order>3</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                            <comment>Il s'agit de l'ID de la liste de contact où ajouter les emails.</comment>
                        </conf_api_list_id_field>
                        <conf_api_debug_field>
                            <label>Debug mode</label>
                            <frontend_type>select</frontend_type>
                            <source_model>mailjetform/options</source_model>
                            <sort_order>4</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                            <comment>Mode de debug.</comment>
                        </conf_api_debug_field>
                    </fields>
                </conf_api>
            </groups>
        </mailjetform_options>
    </sections>
</config>

AjaxController.php

Un contrôleur basique est nécessaire pour gèrer la requête Ajax de traitement du formulaire.

class Feub_Mailjetform_AjaxController extends Mage_Core_Controller_Front_Action
{
    public function indexAction() {
        $mj = Mage::getModel('mailjetform/mailjetform');

        $email = $this->getRequest()->getPost('email');

        if (isset($email) && !empty($email)) {
            $params = array(
                'method'    => 'POST',
                'contact'   => trim($email),
                'id'        => $mj->list_id
            );

            $response = $mj->listsAddContact($params);

            $contact_id = $response->contact_id;

            if (!empty($contact_id)) {
                echo 'Merci de vous être abonné à notre newsletter!';
            } else {
                echo 'Merci de vérifier votre adresse email ou d\'essayer plus tard. Merci.';
            }
        }
    }
}

Data.php

Ce fichier est requis bien que nous ne l’utiliserons pas.

class Feub_Mailjetform_Helper_Data extends Mage_Core_Helper_Abstract
{
}

Mailjetform.php

Il s’agit du modèle reprenant – à l’arrache – la classe de l’API PHP fournie par Mailjet afin de l’intégrer dans une architecture Magento.

class Feub_Mailjetform_Model_Mailjetform extends Mage_Core_Model_Abstract
{
    public $version = '0.1';
    public $output = 'json';
    public $apiUrl;
    public $apiKey;
    public $secretKey;
    public $list_id;
    public $secure = true;
    public $debug;

    public function _construct() {
        $this->apiKey       = Mage::getStoreConfig('mailjetform_options/conf_api/conf_api_key_field');
        $this->secretKey    = Mage::getStoreConfig('mailjetform_options/conf_api/conf_api_secret_field');
        $this->list_id      = Mage::getStoreConfig('mailjetform_options/conf_api/conf_api_list_id_field');
        $this->debug        = Mage::getStoreConfig('mailjetform_options/conf_api/conf_api_debug_field');
        $this->apiUrl       = (($this->secure) ? 'https' : 'http').'://api.mailjet.com/'.$this->version.'';
    }

    public function __call($method, $args) {

        # params
        $params = (sizeof($args) > 0) ? $args[0] : array();

        # request method
        $request = isset($params["method"]) ? strtoupper($params["method"]) : 'GET';

        # unset useless params
        if(isset($params["method"])) unset($params["method"]);

        # Make request
        $result = $this->sendRequest($method,$params,$request);

        # Return result
        $return = ($result === true) ? $this->_response : false;

        if( $this->debug == 2 || ( $this->debug == 1 && $return == false ) ){
            $this->debug();
        }

        return $return;
    }

    public function requestUrlBuilder($method,$params=array(),$request) {
        $query_string = array('output'=>'output='.$this->output);

        foreach($params as $key=>$value) {
            if($request == "GET" || in_array($key,array('apikey','output'))) $query_string[$key] = $key.'='.urlencode($value);
            if($key == "output") $this->output = $value;
        }

        $this->call_url = $this->apiUrl.'/'.$method.'/?'.join('&',$query_string);

        return $this->call_url;

    }

    public function sendRequest($method = false,$params=array(),$request="GET") {
        # Method
        $this->_method = $method;
        $this->_request = $request;

        # Build request URL
        $url = $this->requestUrlBuilder($method,$params,$request);

        # Set up and execute the curl process
        $curl_handle = curl_init();
        curl_setopt($curl_handle, CURLOPT_URL, $url);
        curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl_handle, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl_handle, CURLOPT_SSL_VERIFYHOST, 2);
        curl_setopt($curl_handle, CURLOPT_USERPWD, $this->apiKey.':'.$this->secretKey);

        $this->_request_post = false;
        if($request == 'POST') :
            curl_setopt($curl_handle, CURLOPT_POST, count($params));
            curl_setopt($curl_handle, CURLOPT_POSTFIELDS, http_build_query($params, '', '&'));
            $this->_request_post = $params;
        endif;


        $buffer = curl_exec($curl_handle);

        if($this->debug>2) var_dump($buffer);

        # Response code
        $this->_response_code = curl_getinfo($curl_handle,CURLINFO_HTTP_CODE);

        # Close curl process
        curl_close($curl_handle);

        # RESPONSE
        $this->_response = ($this->output == 'json') ? json_decode($buffer) : $buffer;

        return ($this->_response_code == 200) ? true : false;

    }

    public function debug() {
        echo '<style type="text/css">';
        echo '

        #debugger {width: 100%; font-family: arial;}
        #debugger table {padding: 0; margin: 0 0 20px; width: 100%; font-size: 11px; text-align: left;border-collapse: collapse;}
        #debugger th, #debugger td {padding: 2px 4px;}
        #debugger tr.h {background: #999; color: #fff;}
        #debugger tr.Success {background:#90c306; color: #fff;}
        #debugger tr.Error {background:#c30029 ; color: #fff;}
        #debugger tr.Not-modified {background:orange ; color: #fff;}
        #debugger th {width: 20%; vertical-align:top; padding-bottom: 8px;}

        ';
        echo '</style>';

        echo '<div id="debugger">';

        if(isset($this->_response_code)) :

            if($this->_response_code == 200) :

                echo '<table>';
                echo '<tr class="Success"><th>Success</th><td></td></tr>';
                echo '<tr><th>Status code</th><td>'.$this->_response_code.'</td></tr>';

                if(isset($this->_response)) :
                    echo '<tr><th>Response</th><td><pre>'.utf8_decode(print_r($this->_response,1)).'</pre></td></tr>';
                endif;

                echo '</table>';

            elseif($this->_response_code == 304) :

                echo '<table>';
                echo '<tr class="Not-modified"><th>Error</th><td></td></tr>';
                echo '<tr><th>Error no</th><td>'.$this->_response_code.'</td></tr>';
                echo '<tr><th>Message</th><td>Not Modified</td></tr>';
                echo '</table>';

            else :

                echo '<table>';
                echo '<tr class="Error"><th>Error</th><td></td></tr>';
                echo '<tr><th>Error no</th><td>'.$this->_response_code.'</td></tr>';
                if(isset($this->_response)) :
                    if( is_array($this->_response) OR  is_object($this->_response) ):
                        echo '<tr><th>Status</th><td><pre>'.print_r($this->_response,true).'</pre></td></tr>';
                    else:
                        echo '<tr><th>Status</th><td><pre>'.$this->_response.'</pre></td></tr>';
                    endif;
                endif;
                echo '</table>';

            endif;

        endif;

        $call_url = parse_url($this->call_url);

        echo '<table>';
        echo '<tr class="h"><th>API config</th><td></td></tr>';
        echo '<tr><th>Protocole</th><td>'.$call_url['scheme'].'</td></tr>';
        echo '<tr><th>Host</th><td>'.$call_url['host'].'</td></tr>';
        echo '<tr><th>Version</th><td>'.$this->version.'</td></tr>';
        echo '</table>';

        echo '<table>';
        echo '<tr class="h"><th>Call infos</th><td></td></tr>';
        echo '<tr><th>Method</th><td>'.$this->_method.'</td></tr>';
        echo '<tr><th>Request type</th><td>'.$this->_request.'</td></tr>';
        echo '<tr><th>Get Arguments</th><td>';

        $args = explode("&",$call_url['query']);
        foreach($args as $arg) {
            $arg = explode("=",$arg);
            echo ''.$arg[0].' = <span style="color:#ff6e56;">'.$arg[1].'</span><br/>';
        }

        echo '</td></tr>';

        if($this->_request_post){
            echo '<tr><th>Post Arguments</th><td>';

            foreach($this->_request_post as $k=>$v) {
                echo $k.' = <span style="color:#ff6e56;">'.$v.'</span><br/>';
            }

            echo '</td></tr>';
        }

        echo '<tr><th>Call url</th><td>'.$this->call_url.'</td></tr>';
        echo '</table>';

        echo '</div>';
    }
}

 

Options.php

Cette classe sert simplement à définir les options du select de debug dans l’admin de Magento.

class Feub_Mailjetform_Model_Options
{
    public function toOptionArray() {
        return array(
            array('value' => 0, 'label' => 'Non'),
            array('value' => 1, 'label' => 'Seulement les erreurs'),
            array('value' => 2, 'label' => 'Oui pour tout')
        );
    }
}

 

Listsoptions.php

Cette classe est responsable du remplissage des options de l’élément select avec les listes de contacts de Mailjet côté admin.

class Feub_Mailjetform_Model_Listsoptions
{
    public function toOptionArray() {
        $options = array();

        $mj         = Mage::getModel('mailjetform/mailjetform');
        $all_lists  = $mj->listsAll();
        $lists      = $all_lists->lists;

        foreach ($lists as $list) {
            $options[] = array(
                'value' => $list->id,
                'label' => $list->label
            );
        }

        return $options;
    }
}

 

mailjetform.phtml

C’est dans ce fichier que l’on va avoir notre code HTML pour le formulaire, je l’ai réduit au minimum pour les besoins de l’article.

<form action="" method="post" id="mailjet-form">
    <div class="msg-output"></div>
    <label for="newsletter">Entrez votre email :</label>
    <input type="text" name="email" id="newsletter" />
    <button type="submit" title="Abonnez-vous" class="btn-submit-newsletter">Ok</button>
</form>

Il manque le code javascript qui sera placé dans ce même fichier. Je l’ai séparé afin d’être plus lisible.

<script>
$(document).ready(function() {
    $("#mailjet-form").on("submit", function(event) {
        event.preventDefault();

        $.ajax({
            type:   "POST",
            url:    "mailjetform/ajax/index",
            data:   {
                email: $("#newsletter").val()
            }
        })
        .done(function(msg) {
            $(".msg-output").html(msg);
        });
    });
});
</script>

Voilà, tout est prêt, il ne reste en principe plus qu’à vider le cache, se déconnecter, puis se reconnecter à l’admin de Magento. Un nouveau groupe de menu Feub est maintenant visible dans la barre latèrale avec l’entrée Formulaire Mailjet (voir la capture d’écran en début d’article). Il vous suffit de rentrer vos informations Mailjet, à savoir la clé d’API et la clé secrête, la liste de vos listes (jolie celle-là) doit apparaitre, faites votre choix. Il y a même un petit mode debug.

Le frontend

C’est bien tout ça, mais où est le formulaire? Comme je l’ai indiqué plus haut, étant un peu pressé et mon template ne le requiérant pas, je n’ai pas crée de réel block (au sens MVC Magento), mais j’utilise un shortcode du type {{block type= » » template= » »}} pour insérer le formulaire dans un bloc statique de mon template (Admin > CMS > Blocs statiques).

{{block type="page/html/mailjetform" template="page/html/mailjetform.phtml"}}

Et voilà tout devrait fonctionner maintenant, vos visiteurs peuvent s’abonner à votre newsletter Mailjet.

Le formulaire d'inscription en place
Le formulaire d’inscription en place

Vous pouvez télécharger une archive avec tous les fichiers de ce tutoriel Module Magento Feub Mailjetform.

Conclusion

Voilà une façon relativement simple et rapide que j’ai utilisé pour intégrer un formulaire d’inscription à une newsletter Mailjet. Cela pourrait être beaucoup plus propre, je ne connais pas encore toutes les ficelles du développement Magento, donc n’hésitez pas à donner vos conseils et à commenter cet article.

3 thoughts on “Création d’un module Magento de formulaire d’abonnement Mailjet”

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *