La nouvelle version 1.7 de Prestashop introduit de gros changements dans la gestion backoffice des fiches produits.
Cette page utilise les nouvelles méthodes symfony et tout les modules souhaitant ajouter des informations produits doivent se mettre à jour pour utiliser les nouvelles méthodes.
Comme d’habitude la documentation prestashop n’est pas exhaustive et je n’ai à date trouvé aucune information ni tutoriel sur le sujet.

Nous allons donc voir ensemble comment rajouter des nouveaux champs produits et les gérer dans l’administration avec Prestashop 1.7
Pour cela nous allons créer un module hhproduct.

Celui-ci ajoutera des nouveaux champs à notre entité produit.

  • custom_field
  • custom_field_lang
  • custom_field_lang_wysiwyg

Nous allons donc de surcharger l’objet Product afin de lui ajouter ces nouveaux champs.
Pour cela créer un fichier Product.php avec le contenu suivant dans le dossier override/classes du module.

<?php
class Product extends ProductCore {
 
    public $custom_field;
    public $custom_field_lang;
    public $custom_field_lang_wysiwyg;
 
    public function __construct($id_product = null, $full = false, $id_lang = null, $id_shop = null, \Context $context = null) {
        //Définition des nouveaux champs
        self::$definition['fields']['custom_field'] = [
            'type' => self::TYPE_STRING,
            'required' => false, 'size' => 255
        ];
        self::$definition['fields']['custom_field_lang']     = [
            'type' => self::TYPE_STRING,
            'lang' => true,
            'required' => false, 'size' => 255
        ];
        self::$definition['fields']['custom_field_lang_wysiwyg']     = [
            'type' => self::TYPE_HTML,
            'lang' => true,
            'required' => false,
            'validate' => 'isCleanHtml'
        ];
        parent::__construct($id_product, $full, $id_lang, $id_shop, $context);
    }
}

lors de l’installation du module ce fichier sera automatiquement placé dans le dossier des overrides par Prestashop.

Contrairement aux autres formulaires Prestashop les hooks spécifiques d’ajout produit sont situés dans un fichier twig,s situé sur le chemin suivant :
src/PrestaShopBundle/Resources/views/Admin/Product/form.html.twig

Les hooks disponibles sont les suivants :

  • displayAdminProductsExtra
  • displayAdminProductsMainStepLeftColumnMiddle
  • displayAdminProductsMainStepLeftColumnBottom
  • displayAdminProductsMainStepRightColumnBottom
  • displayAdminProductsQuantitiesStepBottom
  • displayAdminProductsPriceStepBottom
  • displayAdminProductsOptionsStepTop
  • displayAdminProductsOptionsStepBottom

Vous pouvez voir leurs emplacements sur les captures ci-dessous.


prestashop-product-field-1

prestashop-product-field-2


prestashop-product-field-3


prestashop-product-field-4

Nous pouvons donc greffer notre module sur l’ensemble de ces hooks ou uniquement sur celui sur lequel vous souhaitez afficher vos champs.

Pour l’exemple nous utiliserons le hook AdminProductsMainStepLeftColumnMiddle
Dans cette fonction nous allons récupérer et afficher les nouvelles informations produit.

Comme vous pouvez le voir dans le fichier twig , la fonction récupère en paramètre l’identifiant du produit édité.

{{ renderhook('displayAdminProductsMainStepLeftColumnMiddle', { 'id_product': id_product }) }}

Voici le contenu de la fonction

/**
* Affichage des informations supplémentaires sur la fiche produit
* @param type $params
* @return type
*/
public function hookDisplayAdminProductsMainStepLeftColumnMiddle($params) {
$product = new Product($params['id_product']);
$languages = Language::getLanguages($active);
$this->context->smarty->assign(array(
'custom_field' => $product->custom_field,
'custom_field_lang' => $product->custom_field_lang,
'customer_field_lang_wysiwyg' => $product->custom_field_lang_wysiwyg,
'languages' => $languages,
'default_language' => $this->context->employee->id_lang,
)
);
 
return $this->display(__FILE__, 'views/templates/hook/extrafields.tpl');
}

Note : Pour l’instant je n’ai pas trouvé de helper spécifique pour générer le contenu du formulaire, nous allons donc devoir le réaliser à la main dans le fichier extrafields.tpl qui sera situé dans le dossier views/templates/hook/ du module

Voici son contenu :

<div class="m-b-1 m-t-1">
<h2>{l s='Custom Attribute from module' mod='hhproduct'}</h2>
 
<fieldset class="form-group">
<div class="col-lg-12 col-xl-4">
 
{*Champ Standard *}
<label class="form-control-label">{l s='my custom field' mod='hhproduct'}</label>
<input type="text" name="custom_field" class="form-control" {if $custom_field && $custom_field != ''}value="{$custom_field}"{/if}/>
 
{* Champ langue avec une structure particulière *}
<label class="form-control-label">{l s='my custom lang field' mod='hhproduct'}</label>
<div class="translations tabbable">
<div class="translationsFields tab-content">
{foreach from=$languages item=language }
<div class="tab-pane translation-label-{$language.iso_code} {if $default_language == $language.id_lang}active{/if}">
<input type="text" name="custom_field_lang_{$language.id_lang}" class="form-control" {if isset({$custom_field_lang[$language.id_lang]}) && {$custom_field_lang[$language.id_lang]} != ''}value="{$custom_field_lang[$language.id_lang]}"{/if}/>
</div>
{/foreach}
</div>
</div>
</div>
 
{* Champ wysiwyg avec TinyMce *}
<div class="col-lg-12 col-xl-12">
<label class="form-control-label">{l s='my custom lang field wysiwyg' mod='hhproduct'}</label>
<div class="translations tabbable">
<div class="translationsFields tab-content bordered">
{foreach from=$languages item=language }
<div class="tab-pane translation-label-{$language.iso_code} {if $default_language == $language.id_lang}active{/if}">
<textarea name="custom_field_lang_wysiwyg_{$language.id_lang}" class="autoload_rte">{if isset({$custom_field_lang_wysiwyg[$language.id_lang]}) && {$custom_field_lang_wysiwyg[$language.id_lang]} != ''}{$custom_field_lang_wysiwyg[$language.id_lang]}{/if}</textarea>
</div>
{/foreach}
</div>
</div>
</div>
 
</fieldset>
 
<div class="clearfix"></div>
</div>

Pour la gestion des langues,nous pouvons voir dans le fichier admin-dir/themes/default/js/bundle/product/form.js qu’il faut respecter une certaine structure d’affichage pour que le changement de langue soit géré.

function switchLanguage(iso_code) {
$('div.translations.tabbable > div > div.tab-pane:not(.translation-label-' + iso_code + ')').removeClass('active');
$('div.translations.tabbable > div > div.tab-pane.translation-label-' + iso_code).addClass('active');
}

Une fois notre module installé le résultat obtenu sera le suivant :

Champs produits supplémentaire prestashop 1.7

Pour finir voici le contenu complet du fichier hhproduct.php

<?php
class HhProduct extends Module {
 
     public function __construct() {
 
        $this->name = 'hhproduct';
        $this->tab = 'others';
        $this->author = 'hhennes';
        $this->version = '0.1.0';
        $this->need_instance = 0;
        $this->bootstrap = true;
 
        parent::__construct();
 
        $this->displayName = $this->l('hhproduct');
        $this->description = $this->l('add new fields to product');
        $this->ps_versions_compliancy = array('min' => '1.7.1', 'max' => _PS_VERSION_);
    }
 
   public function install() {
        if (!parent::install() || !$this->_installSql()
                //Pour les hooks suivants regarder le fichier src\PrestaShopBundle\Resources\views\Admin\Product\form.html.twig
                || ! $this->registerHook('displayAdminProductsExtra')
                || ! $this->registerHook('displayAdminProductsMainStepLeftColumnMiddle')       
        ) {
            return false;
        }
 
        return true;
    }
 
     public function uninstall() {
        return parent::uninstall() && $this->_unInstallSql();
    }
 
    /**
     * Modifications sql du module
     * @return boolean
     */
    protected function _installSql() {
        $sqlInstall = "ALTER TABLE " . _DB_PREFIX_ . "product "
                . "ADD custom_field VARCHAR(255) NULL";
        $sqlInstallLang = "ALTER TABLE " . _DB_PREFIX_ . "product_lang "
                . "ADD custom_field_lang VARCHAR(255) NULL,"
                . "ADD custom_field_lang_wysiwyg TEXT NULL";
 
        $returnSql = Db::getInstance()->execute($sqlInstall);
        $returnSqlLang = Db::getInstance()->execute($sqlInstallLang);
 
        return $returnSql && $returnSqlLang;
    }
 
    /**
     * Suppression des modification sql du module
     * @return boolean
     */
    protected function _unInstallSql() {
       $sqlInstall = "ALTER TABLE " . _DB_PREFIX_ . "product "
                . "DROP custom_field";
        $sqlInstallLang = "ALTER TABLE " . _DB_PREFIX_ . "product_lang "
                . "DROP custom_field_lang,DROP custom_field_lang_wysiwyg";
 
        $returnSql = Db::getInstance()->execute($sqlInstall);
        $returnSqlLang = Db::getInstance()->execute($sqlInstallLang);
 
        return $returnSql && $returnSqlLang;
    }
 
    public function hookDisplayAdminProductsExtra($params)
    {
 
    }
 
    /**
     * Affichage des informations supplémentaires sur la fiche produit
     * @param type $params
     * @return type
     */
    public function hookDisplayAdminProductsMainStepLeftColumnMiddle($params) {
        $product = new Product($params['id_product']);
        $languages = Language::getLanguages($active);
        $this->context->smarty->assign(array(
            'custom_field' => $product->custom_field,
            'custom_field_lang' => $product->custom_field_lang,
            'customer_field_lang_wysiwyg' => $product->custom_field_lang_wysiwyg,
            'languages' => $languages,
            'default_language' => $this->context->employee->id_lang,
            )
           );
        /** 
         * @Todo Faire marcher le champ langue
         */
        return $this->display(__FILE__, 'views/templates/hook/extrafields.tpl');
    }
}

Le processus pourra surement être amélioré lors des prochaines mise à jour de prestashop, n’hésitez pas à remonter vos astuces.