Jump to content

Recommended Posts

bonjour,

 

Ces derniers jours j'ai passer un certain temps à modifier ce cher prestashop 1.5 afin d'avoir une gestion des groupes sur les produit eux même et pas seulement sur les catégories.

 

Je vais partager mon travail pour en premier lieu aidé ceux qui le veulent, et aussi pour peut-être améliorer mon code fait un peu à la rash.

 

Tout d’abord j'ai fait la modification en partie admin afin d'obtenir ceci :

product_group_presta1_5.jpg

 

En premier lieu il nous faut ajouter la table en base de donnée :

CREATE TABLE IF NOT EXISTS `PREFIX_product_group` (
 `id_group` int(11) NOT NULL,
 `id_product` int(11) NOT NULL,
 `etat` tinyint(1) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

 

Ensuite nous allons préparer la récupération des donnée de cette base de donnée pour l'inclure et l'affiché dans une partie de l'administration du produit.

Pour ma part j'ai choisi dans la partie association car cette partie n'est pas trop charger(sachant que ma partie description est déjà blinder d'ajout) et il s'agit de la partie qui correspond le mieux à cette partie.

 

Donc nous allons ouvrir notre joli fichier /override/controllers/admin/AdminProductsController.php ​et y surclasser une fonction complète (car c'est un peu beaucoup enchevêtrer) :

public function initFormAssociations($obj)
{
 $product = $obj;
 $data = $this->createTemplate($this->tpl_form);
 // Prepare Categories tree for display in Associations tab
 $root = Category::getRootCategory();
 $default_category = Tools::getValue('id_category', Context::getContext()->shop->id_category);
 if (!$product->id || !$product->isAssociatedToShop())
  $selected_cat = Category::getCategoryInformations(Tools::getValue('categoryBox', array($default_category)), $this->default_form_language);
 else
 {
  if (Tools::isSubmit('categoryBox'))
$selected_cat = Category::getCategoryInformations(Tools::getValue('categoryBox', array($default_category)), $this->default_form_language);
  else
$selected_cat = Product::getProductCategoriesFull($product->id, $this->default_form_language);
 }
 /**
 Ajout par rapport à la fonction de base

 Gestion des groupes existant et récupération des informations en base de donnée
 **/
 /* on parcours tout les groupe existant et on en fait une liste */
 $groups = Group::getGroups(Context::getContext()->language->id);
 $selected_group=array();/* tableau des groupe selectionné pour notre produit*/
 if (!$product->id)
 {
  foreach($groups as $group)
  {
$selected_group['groupBox_'.$group['id_group']]=true;
  }
 }
 else
 {
  $prod_groups=Product::getProductGroupFull($product->id);
  if(empty($prod_groups))
  {
foreach($groups as $group)
{
 $selected_group['groupBox_'.$group['id_group']]=true;
}
  }
  else
  {
foreach($groups as $group)
{
 if(isset($prod_groups[$group['id_group']]) && $prod_groups[$group['id_group']])
 {
  $selected_group['groupBox_'.$group['id_group']]=true;
 }
 else
 {
  $selected_group['groupBox_'.$group['id_group']]=false;
 }
}
  }
 }
 /**
 Fin de l'ajout
 **/
 // Multishop block
 $data->assign('feature_shop_active', Shop::isFeatureActive());
 $helper = new HelperForm();
 if ($this->object && $this->object->id)
  $helper->id = $this->object->id;
 else
  $helper->id = null;
 $helper->table = $this->table;
 $helper->identifier = $this->identifier;
 // Accessories block
 $accessories = Product::getAccessoriesLight($this->context->language->id, $product->id);
 if ($post_accessories = Tools::getValue('inputAccessories'))
 {
  $post_accessories_tab = explode('-', Tools::getValue('inputAccessories'));
  foreach ($post_accessories_tab as $accessory_id)
if (!$this->haveThisAccessory($accessory_id, $accessories) && $accessory = Product::getAccessoryById($accessory_id))
 $accessories[] = $accessory;
 }
 $data->assign('accessories', $accessories);
 $product->manufacturer_name = Manufacturer::getNameById($product->id_manufacturer);
 $tab_root = array('id_category' => $root->id, 'name' => $root->name);
 $helper = new Helper();
 $category_tree = $helper->renderCategoryTree($tab_root, $selected_cat, 'categoryBox', false, true, array(), false, true);
 /**
 Ajout par rapport à la fonction de base
 J'ai ajouté les variable groups_tree et groups_selected à l'assign
 **/
 $data->assign(array('default_category' => $default_category,
 'groups_tree' => Group::getGroups(Context::getContext()->language->id),
 'groups_selected' => $selected_group,
 'selected_cat_ids' => implode(',', array_keys($selected_cat)),
 'selected_cat' => $selected_cat,
 'id_category_default' => $product->getDefaultCategory(),
 'category_tree' => $category_tree,
 'product' => $product,
 'link' => $this->context->link,
 'is_shop_context' => Shop::getContext() == Shop::CONTEXT_SHOP
 ));
 /**
 Fin de l'ajout
 **/
 $this->tpl_form_vars['custom_form'] = $data->fetch();
}

 

Et enfin nous allons surclasser le template admin présent dans /admin/theme/default/templates/controllers/products/associations.tpl par le fichier /override/controllers/admin/templates/products/associations.tpl. Si ce fichier n'existe pas, le créer à partir du fichier de base.

 

Vous allez vous placer juste avant le second "<div class="separation"></div>" (ctrl+f : separation). et ajouter :

<div class="separation"></div>
<input type="hidden" name="submitted_tabs[]" value="Groups" />
<table>
 <tr>
  <td class="col-left">
{include file="controllers/products/multishop/checkbox.tpl" field="category_box" type="category_box"}
<label for="category_block">{l s='Group access:'}</label>
  </td>
  <td class="col-right">
<div id="category_block">
 {include file="helpers/form/form_group.tpl" groups=$groups_tree fields_value=$groups_selected}
</div>
  </td>
 </tr>
</table>

 

A partir de ce moment vous avez un joli formulaire avec une récupération des données mais aucune possibilité d'enregistrer.

Edited by hiroshi (see edit history)
  • Like 1
Link to comment
Share on other sites

Ensuite pour enregistrer les éléments sélectionné en base de donnée nous devons reprendre notre petit fichier /override/controllers/admin/AdminProductsController.php et y ajouter :

/**
Les trois fonctions suivante sont plus ou moins sur le modèle des associations
**/
/* fonction de modifications des éléments en base de donnée **/
public function updateGroups($product, $groups)
{
 $this->cleanGroups($product);
 $this->addGroups($product, $groups);
}
/* fonction de suppressions des éléments en base de donnée **/
public function cleanGroups($product)
{
 Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'product_group` WHERE `id_product` = '.(int)$product->id);
}
/* fonction d'ajouts des éléments en base de donnée **/
public function addGroups($product, $groups)
{
 foreach ($groups as $group)
 {
  $row = array('id_product' => (int)$product->id, 'id_group' => (int)$group['id'], 'etat' => (int)$group['etat']);
  Db::getInstance()->insert('product_group', $row);
 }
}
/* fonction de traitement des donnée récupéré du formulaire pour les ranger dans un tableau comme je le souhaite pour l'ajout en base de donnée */
public function addFormGroups($product)
{
 $groups = Group::getGroups(Context::getContext()->language->id);
 $mygroups=array();
 if(isset($_POST['groupBox']))
 {
  foreach($_POST['groupBox'] as $gb)
  {
   foreach($groups as $group)
   {
 if($gb==$group['id_group'])
 {
  $mg=array();
  $mg['id']=$gb;
  $mg['etat']=true;
  $mygroups[]=$mg;
 }
   }
  }
 }
 $this->updateGroups($product, $mygroups);
}
/* fonction appeler à l'envois du formulaire lors de l'ajout d'un produits */
public function processAdd()
{
 $this->checkProduct();
 if (!empty($this->errors))
 {
  $this->display = 'add';
  return false;
 }
 $this->object = new $this->className();
 $this->_removeTaxFromEcotax();
 $this->copyFromPost($this->object, $this->table);

 $groups = Group::getGroups(Context::getContext()->language->id);
 $mygroups=array();
 foreach($groups as $group)
 {
  $mg=array();
  $mg['id']=$group['id_group'];
  $mg['etat']=true;
  $mygroups[]=$mg;
 }
 if ($this->object->add())
 {
  $this->addGroups($this->object, $mygroups);
 }
 parent::processAdd();
}
/* fonction appeller lors de la modifications des produits */
public function processUpdate()
{
 $this->checkProduct();
 if (!empty($this->errors))
 {
  $this->display = 'edit';
  return false;
 }
 $id = (int)Tools::getValue('id_'.$this->table);
 /* Update an existing product */
 if (isset($id) && !empty($id))
 {
  $object = new $this->className((int)$id);
  $this->object = $object;
  if (Validate::isLoadedObject($object))
  {
   $this->_removeTaxFromEcotax();
   $this->copyFromPost($object, $this->table);
   $object->indexed = 0;
   if (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_SHOP)
 $object->setFieldsToUpdate((array)Tools::getValue('multishop_check'));
   if ($object->update())
   {
 if (in_array($this->context->shop->getContext(), array(Shop::CONTEXT_SHOP, Shop::CONTEXT_ALL)))
 {
  if ($this->isTabSubmitted('Groups'))
   $this->addFormGroups($object);
 }
   }
  }
 }
 parent::processUpdate();
}

 

à partir de ce moment vous avez l'ajout et la modification de vos éléments qui sont pris en compte.

  • Like 1
Link to comment
Share on other sites

Enfin nous allons nous intéresser à la partie front.

 

Tout d'abord afin d'avoir une notion de groupe sur l'intégralité du site (car je n'ai pas trouvé de variable sur le current groupe pré-enregistrer dans le smarty) nous allons ajouter dans le fichier /override/classes/controller/FrontController.php :

 

public function initContent()
{
 $this->context->smarty->assign('currentGroups', $this->getCurrentGroup());

 parent::initContent();
}
public function getCurrentGroup()
{
 if($this->context->customer->isLogged())
 {
  $current_groups=$this->context->customer->getGroups();
 }
 else
 {
  $current_groups=array(Configuration::get('PS_UNIDENTIFIED_GROUP'));
 }
 return $current_groups;
}

 

Nous aurons ainsi pour toute nos page de template la variable {$currentGroups} qui correspond a un tableau.

 

Nous allons surclasser la class product pour y ajouter les éléments voulu (/override/classes/Product.php) :

class Product extends ProductCore
{
public $groups;
public function __construct($id_product = null, $full = false, $id_lang = null, $id_shop = null, Context $context = null)
{
 if($id_product!=null)
 {
  $this->groups=$this->getProductGroupFull($id_product);
 }
 parent::__construct($id_product, $full, $id_lang, $id_shop, $context);
}
public function getProductGroupFull($id_product = '')
{
 $groups = array();
 $result = Db::getInstance()->executeS('
  SELECT pg.`id_group`, pg.`etat`
  FROM '._DB_PREFIX_.'product_group pg
  WHERE pg.`id_product` = '.(int)$id_product
 );
 foreach ($result as $group){
  $groups[$group['id_group']] = $group['etat'];
 }
 return $groups;
}
/* fonction de remonté des variable dans la partie liste de produits (valable aussi pour les packs) */
public static function getProductProperties($id_lang, $row, Context $context = null)
{
 if (!$row['id_product'])
  return false;
 $newgroups=self::getProductGroupFull($row['id_product']);
 if(empty($newgroups)){$newgroups=array(1=>0);}
 $row['groups']=$newgroups;
 return parent::getProductProperties($id_lang, $row, $context);
}
}

 

Avec ce code nous pouvons interagir sur la partie produit et sur la partie listes des produits mais pour ma part, je n'ai fait que la partie listes pour allez au plus vite (nous pouvons toujours après cela renforcer avec des test et des redirections).

 

Voici mon ajout dans la partie /theme/mon_theme/product-list.php :

 

{if isset($products)}
<!-- Products list -->
<div>
 <ul id="product_list" class="clear">
 {foreach from=$products item=product name=products}
  {assign var=viewProduct value=false}
  {foreach from=$product['groups'] item=group key=groupkey}
   {foreach from=$currentGroups item=cgroup}
 {if $groupkey==$cgroup && $group}
  {assign var=viewProduct value=true}
 {/if}
   {/foreach}
  {/foreach}
  {if $viewProduct}
  <li class="ajax_block_product {if $smarty.foreach.products.first}first_item{elseif $smarty.foreach.products.last}last_item{/if} {if $smarty.foreach.products.index % 2}alternate_item{else}item{/if} clearfix">
  [...]tout le contenu[...]
  </li>
  {/if}
 {/foreach}
  <li class="clear clearfix"></li>
 </ul>
</div>
<!-- /Products list -->
{/if}

 

Et vous avez une mini gestion des groupe associer a vos produits.

 

Merci de m'avoir lu et a bientôt.

 

Cordialement,

Link to comment
Share on other sites

  • 1 month later...

Bonjour,

 

Et merci de partager ceci :)

 

Cependant, je note quelques bugs.

 

L'ajout du produit se fait deux fois pour ma part.

L'appel de $this->object->add est fait deux fois. Elle est appelée une fois dans la fonction processAdd() du controller natif (AdminProductsController) et ré-appelé dans l'override (qui appel lui même le controlleur parent).

 

 

voici donc ma modif ( j'ai aussi condensé la fonction processAdd du coup)

 

public function processAdd()
{
 parent::processAdd();
  if (empty($this->errors))
  {
   $this->addFormGroups($this->object);
  }
  else {
   $this->cleanGroups($product);

  }

 return $this->object;
}

 

Je rappel aussi ta fonction addFormGroups() qui permet de prendre en compte les groupes clients directement lors de l'ajout.Sinon on avait tous les groupes clients cochés par défaut lors de l'ajout.

Edited by Myst26 (see edit history)
Link to comment
Share on other sites

  • 1 year later...
  • 3 months later...

Merci Hiroshi pour ce tuto très complet.

 

Je tente vainement d'adapter ce tutoriel à Prestshop 1.6, malheureusement, à la fin de la première étape, mon "joli formulaire avec récupération des données" ne ressort pas.

 

J'ai à la place : "Group access: Aucun groupe créé". Le fichier "form_group.tpl" est donc bien récupéré, mais pas les différents variables $groups…

 

Quelqu'un s'est-il déjà penché sur le sujet ?

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...