Depuis la version 1.6 de Prestashop, il est possible de rajouter rapidement et facilement le formulaire d’édition d’un objet dans l’administration via un module personnalisé.
Et ceci sans surcharge particulière en utilisant tout simplement les hooks existants.

Les objets éditables via cette méthodes sont notamment les suivants :

  • Catégories Produits
  • Adresses clients
  • Clients
  • … ( Presque tous les éléments admin sauf les produits sous Prestashop 1.7 )

Cette modification est réalisable via les hooks dynamiques suivants :

Dans la fonction renderForm de la classe AdminController

Hook::exec('action'.$this->controller_name.'FormModifier')

Dans la fonction postProcess de la classe AdminController via aux choix les hooks suivants :

//Avant l'exécution de l'action du controller admin
Hook::exec('actionAdmin'.ucfirst($this->action).'Before', array('controller' => $this));
Hook::exec('action'.get_class($this).ucfirst($this->action).'Before', array('controller' => $this));
 
 //Après l'exécution de l'action du controller admin
 Hook::exec('actionAdmin'.ucfirst($this->action).'After', array('controller' => $this, 'return' => $return));
 Hook::exec('action'.get_class($this).ucfirst($this->action).'After', array('controller' => $this, 'return' => $return));

Vu comme ça les hooks paraissent un peu barbares mais il n’en est rien :-), ce sera beaucoup plus parlant avec un exemple.

Exemple

Pour illustrer comment réaliser cela nous allons modifier le formulaire d’édition d’une catégorie produit.
Nous souhaitons rajouter plusieurs paramètres personnalisés puis les sauvegarder ensuite.

Le controller admin concerné pour les catégorie est AdminCategories.
Les hooks à implémenter seront donc les suivants :

  • actionAdminCategoriesFormModifier ($this->controller_name = AdminCategories  => Modification du formulaire )
  • actionAdminCategoriesControllerSaveBefore ( get_class($this) = AdminCategoriesController // $this->action = Save  => Exécutée avant l’action « Save du controller » )
  • actionAdminCategoriesControllerSaveAfter ( get_class($this) = AdminCategoriesController // $this->action = Save  => Exécutée avant l’action « Save du controller » )

Nous pourrions également utiliser les hooks généraux

  • actionAdminSaveBefore
  • actionAdminSaveAfter

Cependant je ne le recommande pas dans ce cas, car il sont exécutés lors des enregistrements de l’ensemble des entités en back office.
Dans notre cas il vaut mieux cibler plus précisément l’action.

Mise en oeuvre

Pour mettre en oeuvre ces concepts, nous allons créer un module Hh_SampleAdminForm

Voici la base ( déclaration / installation / désinstallation )

public function __construct()
    {
        $this->name = 'hh_sampleadminform';
        $this->tab = 'others';
        $this->version = '0.1.0';
        $this->author = 'hhennes';
        $this->bootstrap = true;
        parent::__construct();
 
        $this->displayName = $this->l('Sample Admin form');
        $this->description = $this->l('Sample module for admin form hooks');
        $this->ps_versions_compliancy = array('min' => '1.6', 'max' => _PS_VERSION_);
    }
 
    /**
     * Installation du module
     * @return bool
     */
    public function install()
    {
        if ( ! parent::install()
            || !$this->registerHook('actionAdminCategoriesControllerSaveAfter')
            || !$this->registerHook('actionAdminCategoriesFormModifier')
        ) {
            return false;
        }
 
        return true;
    }
 
    /**
     * Désinstallation du module
     * @return bool
     */
    public function uninstall()
    {
        return parent::uninstall();
    }

Affichage des nouveaux champs

Passons ensuite à l’affichage de nos nouveaux paramètres.
Il existe plusieurs possibilités :

  • Ajouter au formulaire existant
  • Créer un nouveau fieldset

Les codes reprennent l’utilisation d’un helperForm Standard.
Les paramètres passés à la fonction étant les suivants :

Hook::exec('action'.$this->controller_name.'FormModifier', array(
                'fields' => &$this->fields_form,
                'fields_value' => &$fields_value,
                'form_vars' => &$this->tpl_form_vars,
            ));

Attention au fait que les variables sont passées par référence ( signe & ) ce qui signifie qu’on peut les modifier directement dans le hook.

public function hookActionAdminCategoriesFormModifier($params)
    {
 
        //Ajout d'un champ au fieldset par défaut
        $params['fields'][0]['form']['input'][] =  array(
                        'type' => 'text',
                        'label' => $this->l('Custom field 1'),
                        'name' => $this->name.'_newfield1',
                    );
 
        //Création d'un nouveau fieldset
        $params['fields'][$this->name] = array(
            'form' => array(
                'legend' => array(
                    'title' => $this->l('Sample Category Fieldset'),
                    'icon' => 'icon-tags',
                ),
                'description' => $this->l('New sample fieldset'),
                'input' => array(
                    array(
                        'type' => 'text',
                        'label' => $this->l('Custom field New Fieldset 1'),
                        'name' => $this->name.'_newfieldset1',
                    ),
                    array(
                        'type' => 'text',
                        'label' => $this->l('Custom field New Fieldset 2'),
                        'name' => $this->name.'_newfieldset2',
                    ),
                )
            )
        );
 
        //Pour remonter les valeurs des champs
        $params['fields_value'][$this->name.'_newfield1'] = 'Custom value 1';
        $params['fields_value'][$this->name.'_newfieldset1'] = 'Custom value fieldset 1';
        $params['fields_value'][$this->name.'_newfieldset2'] = 'Custom value fieldset 2';
    }

Le rendu est le suivant :

Nouveaux champs admin prestashop

Enregistrement des données

Il est temps à présent de passer à l’enregistrement des données.
Les hooks actionAdminCategoriesControllerSaveAfter et actionAdminCategoriesControllerSaveBefore étant redondants pour notre example je n’utiliserais que l’After
Pour le traitement des données nous n’auront qu’a récupérer les variables posts envoyées par le formulaire

 public function hookActionAdminCategoriesControllerSaveAfter($params)
    {
        //Récupération des variables custom soumises via le formulaire
        $custom1 = Tools::getValue($this->name.'_newfield1');
        $fiedlset1 = Tools::getValue($this->name.'_newfieldset1');
        $fiedlset2 = Tools::getValue($this->name.'_newfieldset2');
 
        //Faites ensuite le traitement souhaité
    }

Et voila nous avons rajouté facilement des informations à un formulaire admin sans faire de surcharge de classe 😉