A la suite de mon précédent article sur comment ajouter des champs produits dans l’administration de prestashop 1.7 : https://www.h-hennes.fr/blog/2017/10/19/prestashop-1-7-ajouter-des-champs-produit/ , nous allons à présent voir comment ajouter des champs dans le listing des produits de l’administration.

Cette page est gérée via les nouveaux controllers symfony et leur fonctionnement est donc différents des autres listing de l’administration.

 

Je ne détaille pas la base de la création du module qui pourra reprendre celle de l’article sur la création des champs produits.

Le module devra implémenter les hooks suivants :

  • actionAdminProductsListingFieldsModifier (hook natif )
  • displayAdminCatalogTwigListingProductFields ( hook custom)
  • displayAdminCatalogTwigProductFilter ( hook custom )
  • displayAdminCatalogTwigProductHeader ( hook custom )

Pour l’exemple nous allons ajouter un filtre sur les marques des produits, mais la logique s’applique à n’importe quel champ.

Modification des fichiers twigs pour la création des nouveaux hooks

Prestashop 1.7.2.x et inférieurs :

Avec les versions 1.7.2.x et inférieures il n’est pas possible de réaliser cette modification sans toucher à des fichiers « coeur » puisque la surcharge des templates symfony n’est pas encore gérée via les modules.

Pour autant la solution que je propose reste assez propre les seules lignes qui seront ajoutées le seront pour ajouter un appel de hook.

Les templates utilisés pour le listing des produits seront donc les suivants :

  • src\PrestaShopBundle\Resources\views\Admin\Product\catalog.html.twig
  • src\PrestaShopBundle\Resources\views\Admin\Product\list.html.twig

Prestashop 1.7.3.x et supérieur :

A partir de cette version il est possible de surcharger facilement les templates depuis votre module.
Vous pouvez trouver la source de l’information  sur le gist de Mickäel Andrieu : https://gist.github.com/mickaelandrieu/4a02ea05bb1113718aec5432ad418ee5
Dans notre cas il faut créer les fichiers de templates suivant dans le module

  • views/PrestaShop/Admin/Product/catalog.html.twig
  • views/PrestaShop/Admin/Product/list.html.twig

Vous pouvez reprendre l’intégralité du contenu des fichiers sources  et y appliquer les mêmes modifications.

Dans catalog.html.twig :

Rajouter le code suivant :

 {# Hhennes Hook Custom pour afficher des colonnes supplémentaires #}
 {{ renderhook('displayAdminCatalogTwigProductHeader') }}

Après le code :

 <th>
 {{ "Category"|trans({}, 'Admin.Catalog.Feature') }}
 {% include 'PrestaShopBundle:Admin/Product/Include:catalog_order_carrets.html.twig' with {
 'column': 'name_category'
 } %}
 </th>

Rajouter le code suivant :

 {# Hhennes Hook Custom pour afficher des filtres supplémentaires #}
 {{ renderhook('displayAdminCatalogTwigProductFilter') }}

Après le code :

 <th>
 <input
 type="text"
 class="form-control"
 placeholder="{{ "Search category"|trans({}, 'Admin.Catalog.Help') }}"
 name="filter_column_name_category"
 value="{{ filter_column_name_category }}"
 />
 </th>

Dans list.html.twig :
Rajouter le code suivant :

 {# Hhennes Hook Custom pour afficher les nouveaux champs dans le listing #}
 {{ renderhook('displayAdminCatalogTwigListingProductFields', { 'product': product }) }}

Après le code :

 <td>
 {{ product.name_category|default('') }} 
 </td>

Affichage des nouveaux champs via les hooks du fichier twig

Nos nouveaux hooks étant maintenant créé il est temps d’ajouter nos champs via les hooks du module :

hook displayAdminCatalogTwigProductHeader : Affichage de l’entête de la colonne

 /**
 * Hook personnalisé ( non core ) pour afficher le header product
 * cf. src\PrestaShopBundle\Resources\views\Admin\Product\catalog.html.twig
 * @param type $params
 */
 public function hookDisplayAdminCatalogTwigProductHeader($params)
 {
 return $this->display(__FILE__,'views/templates/hook/displayAdminCatalogTwigProductHeader.tpl'); 
 }

Contenu du fichier displayAdminCatalogTwigProductHeader.tpl :

 <th>{l s='Manufacturer' mod='hhproduct'}</th>

 

hook displayAdminCatalogTwigProductFilter : Affichage du champ html du filtre

 /**
 * Hook personnalisé ( non core ) pour afficher le filter product
 * cf. src\PrestaShopBundle\Resources\views\Admin\Product\catalog.html.twig
 * @param type $param
 */
 public function hookDisplayAdminCatalogTwigProductFilter($params)
 {
 $manufacturers = Manufacturer::getManufacturers();
 $this->context->smarty->assign(
 [
 'filter_column_name_manufacturer' => Tools::getValue('filter_column_name_manufacturer',''),
 'manufacturers' => $manufacturers,
 ]
 );
 return $this->display(__FILE__,'views/templates/hook/displayAdminCatalogTwigProductFilter.tpl');
 }

Contenu du fichier displayAdminCatalogTwigProductFilter.tpl :

 <th>
 <select name="filter_column_name_manufacturer" data-toggle="select2">
 <option value="">{l s='Manufacturer' mod='hhproduct'}</option>
 {foreach from=$manufacturers item=manufacturer}
 <option value="{$manufacturer.id_manufacturer}" 
 {if $filter_column_name_manufacturer == $manufacturer.id_manufacturer} selected="selected"{/if}>
 {$manufacturer.name}
 </option>
 {/foreach}
 </select>
</th>

 

hook displayAdminCatalogTwigListingProductFields : Affichage de la valeur du champ pour chaque produit

 /**
 * Hook personnalisé (non core) pour afficher les informations additionnelles produits )
 * cf. src\PrestaShopBundle\Resources\views\Admin\Product\list.html.twig
 * @param type $params
 */
 public function hookDisplayAdminCatalogTwigListingProductFields($params)
 {
 $this->context->smarty->assign('product',$params['product']);
 return $this->display(__FILE__,'views/templates/hook/displayAdminCatalogTwigListingProductFields.tpl');
 }

Contenu du fichier displayAdminCatalogTwigListingProductFields.tpl :

 <td>{$product.manufacturer}</td>

 

Avec ces codes nous devrions à présent obtenir l’affichage suivant :

Prestashop produt fields

C’est bien joli mais il n’y a pas de données 😉

 

Affichage et filtrage des résultats

Pour remonter ces données la bonne nouvelle c’est que le hooks natif de prestashop 1.6 fonctionne encore !
Dans le fichier \src\Adapter\Product\AdminProductDataProvider.php, le hook actionAdminProductsListingFieldsModifier est toujours appellé.
Comme vous pouvez le voir ligne 280

 // exec legacy hook but with different parameters (retro-compat < 1.7 is broken here)
 \HookCore::exec('actionAdminProductsListingFieldsModifier', array(
 '_ps_version' => _PS_VERSION_,
 'sql_select' => &$sqlSelect,
 'sql_table' => &$sqlTable,
 'sql_where' => &$sqlWhere,
 'sql_order' => &$sqlOrder,
 'sql_limit' => &$sqlLimit,
 ));

Voici donc l’implémentation du hook dans notre module :

/**
* Modification de la requête de la liste
* @param type $params
*/
public function hookActionAdminProductsListingFieldsModifier($params)
{
/**
* Rajout du fabricant
*/
//Champ sql
$params['sql_select']['manufacturer'] = [
'table' => 'm',
'field' => 'name',
'filtering' => \PrestaShop\PrestaShop\Adapter\Admin\AbstractAdminQueryBuilder::FILTERING_LIKE_BOTH
];
//Table sql
$params['sql_table']['m'] = [
'table' => 'manufacturer',
'join' => 'LEFT JOIN',
'on' => 'p.`id_manufacturer` = m.`id_manufacturer`',
];
 
//Gestion du filtre, si un paramètre post est défini ( c'est le nom du champ dans le fichier displayAdminCatalogTwigProductFilter.tpl )
$manufacturer_filter = Tools::getValue('filter_column_name_manufacturer',false);
if ( $manufacturer_filter && $manufacturer_filter != '') {
$params['sql_where'][] .= "p.id_manufacturer =".$manufacturer_filter;
}
}

Voici donc comment rajouter et filtrer les résultats de l’attribut manufacturer 🙂

Et voici le rendu final, avec le filtre qui fonctionne :

Colonne manufacturer OK

 

EDIT 2018-03-20 : Ajout des informations pour PS 1.7.3 et supérieur