Tuesday, December 29, 2015

PrestaShop 1.6.x. How to add drop down menus in “Top Horizontal Menu” module

This module allows you to build all types of horizontal navigation bars.

Adding a product category sub-menu to your navigation menu

  1. Add a new product category link to the top menu :
    1. Navigate to Modules -> Modules and look for Top horizontal menu.
    2. Click the Configure button to access the module configuration page:
      How_to_add_drop_down_menus_in_Top_Horizontal_Menu_module_1
    3. To add a new element to the frontend menu, you should select the required element on the right and click the Add button:
      How_to_add_drop_down_menus_in_Top_Horizontal_Menu_module_2
    4. Click Save to confirm adding a new menu item for the top menu.
  2. Add a new sub-category to your product category.
    1. Navigate to the Catalog -> Categories menu. To create a new sub-category, click on the Add New button from any level of categories:
      How_to_add_drop_down_menus_in_Top_Horizontal_Menu_module_3
This sub-category will be displayed as a drop-down menu button for product category automatically.

Adding a CMS pages sub-menu to your navigation menu

  1. Create a new CMS category.
    1. Navigate to Preferences -> CMS and click  Add new CMS category button:
      How_to_add_drop_down_menus_in_Top_Horizontal_Menu_module_4
    2. Fill in the choices suggested and click ‘Save’ button.
  2. Add a new CMS category to the top menu :
    1. Navigate to Modules -> Modules and look for Top horizontal menu.
    2. Click the Configure button to access the module configuration page.
    3. To add a new element to the frontend menu, you should select the required element on the right and click the Add button.
    4. Click Save to confirm adding a new menu item for the top menu.
  3. Create a new CMS page.
    1. Navigate to Preferences -> CMS and click  Add new CMS page button:
      How_to_add_drop_down_menus_in_Top_Horizontal_Menu_module_5
    2. Fill in the choices suggested and click ‘Save’ button.
This CMS page will be displayed as a drop-down menu button for CMS category automatically:

Prestashop - Add multiple category trees with helper form

Question:

I'm creating a prestashop module which need to select 2 categories root.
I tried to add 2 fields with type "categories", but on the second category tree, it has the same ID and the same NAME as the first tree.
$fields_form[1]['form'] = array(
    'legend' => array(
        'title' => $this->l('Setting'),
    ),
    'input' => array(       
        array(
            'type'  => 'text',
            'label' => $this->l('First column title'),
            'name'  => 'HCA_TITLE_COL1',
        ),
        array(
           'type'  => 'categories',
           'label' => $this->l('Root category'),
           'desc'    => $this->l('Root category of the first column.'),  
           'name'  => 'HCA_CAT_COL1',
           'tree'  => array(
                'id' => 'HCA_CAT_COL1',
                'selected_categories' => array((int)Configuration::get('HCA_CAT_COL1')),
            )
        ),
        array(
            'type'  => 'text',
            'label' => $this->l('Second column title'),
            'name'  => 'HCA_TITLE_COL2',
        ),
        array(
           'type'  => 'categories',
           'label' => $this->l('Root category'),
           'desc'    => $this->l('Root category of the second column.'),  
           'name'  => 'HCA_CAT_COL2',
           'tree'  => array(
                'id' => 'HCA_CAT_COL2',
                'selected_categories' => array((int)Configuration::get('HCA_CAT_COL2')),
            )
        ),
    )

Answer:

Here is the solution I found after reading admin\themes\default\template\helpers\form\form.tpl
In this file, there is this condition
{elseif $input.type == 'categories_select'}
    {$input.category_tree}
So, I used 'type' = 'categories_select' instead of 'type' = 'categories', and I generated the categories trees manually.
$root = Category::getRootCategory();

//Generating the tree for the first column
$tree = new HelperTreeCategories('categories_col1'); //The string in param is the ID used by the generated tree
$tree->setUseCheckBox(false)
    ->setAttribute('is_category_filter', $root->id)
    ->setRootCategory($root->id)
    ->setSelectedCategories(array((int)Configuration::get('HCA_CAT_COL1')))
    ->setInputName('HCA_CAT_COL1'); //Set the name of input. The option "name" of $fields_form doesn't seem to work with "categories_select" type
$categoryTreeCol1 = $tree->render();

//Generating the tree for the second column
$tree = new HelperTreeCategories('categories_col2');
$tree->setUseCheckBox(false)
     ->setAttribute('is_category_filter', $root->id)
     ->setRootCategory($root->id)
     ->setSelectedCategories(array((int)Configuration::get('HCA_CAT_COL2')))
     ->setInputName('HCA_CAT_COL2');
$categoryTreeCol2 = $tree->render();


$fields_form[1]['form'] = array(
    'legend' => array(
        'title' => $this->l('Setting'),
    ),
    'input' => array(       
        array(
            'type'  => 'text',
            'label' => $this->l('First column title'),
            'name'  => 'HCA_TITLE_COL1',
        ),
        array(
           'type'  => 'categories_select',
           'label' => $this->l('Root category'),
           'desc'    => $this->l('Root category of the first column.'),  
           'name'  => 'HCA_CAT_COL1',
           'category_tree'  => $categoryTreeCol1 //This is the category_tree called in form.tpl
        ),
        array(
            'type'  => 'text',
            'label' => $this->l('Second column title'),
            'name'  => 'HCA_TITLE_COL2',
        ),
        array(
           'type'  => 'categories_select',
           'label' => $this->l('Root category'),
           'desc'    => $this->l('Root category of the second column.'),  
           'name'  => 'HCA_CAT_COL2',
           'category_tree'  => $categoryTreeCol2
        ),
    )
);
 

Prestashop select attribute combination photos

Question:
Short version : I want to get product photos that are assigned to product's attribute groups. Long version : I want to accomplish the feature by creating a custom module : on product page, you can choose a product color by choosing from a list of product's photos representing different colors, just like here : http://www.kupbuty.com/product-pol-6941-Komin-wzor-w-koleczka-SZ-MRA-110-Granat.html (sorry that it's polish, but I think you'll get the idea). I've already accomplished to get the attributes groups of a product with distinct colours by using the code below (I get all attribute groups and if I haven't got a group with a given color name already then I add it to array $colors):
$attr=$product->getAttributesGroups($this->context->language->id);
$colors=array();
$exists=array();
foreach ($attr as $key => $a) {
   if($a['id_attribute_group']==Configuration::get($this->name.'_attr_id'))
      {
         if(!in_array($a['attribute_name'], $exists))
         {
            $colors[]=$a;
            $exists[]=$a['attribute_name'];
         }
       }
}
Now I looked into Product class and I can't understand how I can get images associated with selected product groups. I've also printed whole $colors content, but I did not see any relevant fields. The images are correctly assigned to attributs combinations in the admin. Can you point me in some direction? EDIT : To make myself more clear - I want to get PRODUCT'S PHOTO assigned to specific attribute value - let's say I have shoes that can be black or white, I want to get white shoe image and black shoe image. The attributes are organized in combinations (I think it's now called "groups"?) of color and size, and every combination has a set of photos - I want to access this photos list.
 
Answer:
You won't find anything useful into the Product class because the attribute-image association done on Prestashop for Attributes value is done in a silly and simply way. when you save an image associated to an attribute, a image file is created under the specific folder
_THEME_COL_DIR_
that is nothing more than the "co" subfolder under the prestashop image directory, with the id_attribute as namefile and jpg as file extension.
so for example if you want to check the image for the id_attribute 5, you will find it under: _THEME_COL_DIR.$id_attribute.'jpg' => '/img/co/5.jpg';
By working that way you will see that both in admin and on the frontend each time the attributes' images have to be shown the code is directly placed in the template, without any preprocessing involved on the Controller/Class.
for example in the product page, the product.tpl has something along the line of:
<a id="color_{$id_attribute|intval}" class="color_pick{if ($group.default == $id_attribute)} selected{/if}" style="background: {$colors.$id_attribute.value};" title="{$colors.$id_attribute.name}" onclick="colorPickerClick(this);getProductAttribute();{if $colors|@count > 0}$('#wrapResetImages').show('slow');{/if}">
        {if file_exists($col_img_dir|cat:$id_attribute|cat:'.jpg')}
        <img src="{$img_col_dir}{$id_attribute}.jpg" alt="{$colors.$id_attribute.name}" width="20" height="20" /><br>
        {/if} ... </a>
where both the image existance and the url are created directly in the template by simply using the img_col_dir and the id_attribute

Prestashop set multiple select from the module and get them in the input

Question:
I am doing a small module in Prestashop. In that module I have used multiselect with helperform. So my code is like this
array(
    'type' => 'select',
    'cols' => 8,
    'class' => 'chosen-product-selct selected_products ',
    'multiple' => true,
    'label' => $this->l('Selected Products'),
    'name' => 'selected_products[]',
    'options' => array(
        'query' => $product_query,
        'id' => 'id',
        'name' => 'product_name'
    ),
    'desc' => $this->l('Select products from products list.'),
),
Here I am saving those multiselected values to the database. But when I am doing edit no saved values has been selected in the box. The box is totally empty.
for getting the result I am doing this
public function getConfigFieldsValues() {
    'selected_products[]'  => Tools::getValue('selected_products', Configuration::get('selected_products')),
}
Its not showing the values that has been entered.So can someone tell me how to solve this issue? Any help and suggestions will be really appreciable. Thanks
Amswer:
I found a solution to the problem with Prestashop multiple select form helper issue.
In order for the select box to work properly there are the following requirements:
  1. Input name should have '[]'. For example: manufacturer_ids[]
  2. $fields_value array should have this element with the same name: manufacturer_ids[] not manufacturer_ids.
  3. The value of the $fields_value array's corresponding item should have selected values as array. For example:
    $fields_value['manufacturer_ids[]'] = array("120", "145");
I save the submitted values as sarialized string in Database, so I am handling it this way:
    $selectedManufacturers = @unserialize($manufacturerIdsTakenFromDb);
    if ($selectedManufacturers === false && $selectedManufacturers !== 'b:0;') {
        $selectedManufacturers = array();
    }        
    $fields_value['manufacturer_ids[]'] = $selectedManufacturers;
And my code in form definition looks like this:
array(
    'type' => 'select',
    'label' => $this->l('Manufacturers'),
    'name' => 'manufacturer_ids[]',
    'multiple' => true,
    'options' => array(
        'query' => array(
            array('key' => '1', 'name' => 'Apple'),
            array('key' => '2', 'name' => 'Samsung'),
            array('key' => '3', 'name' => 'HTC'),
        ),
        'id' => 'key',
        'name' => 'name'
    )
),
If your code does satisfy all these and it still does not work, please let me know, I will be happy to assist you to fix it.

Third party modules in mailalert on prestashop

Question:
I have a custom module that I'm using on prestashop 1.5.4.1 and I need to show some information on the new_order email. I'm quite new to prestashop and it's the first time I'm messing with it.. I wanna know how I can get the variable of that module and show it on the email template.
I already found where the new_order mail variables are set, but don't know how I can add my new custom variable to it.
Any help will be appreciated. Thanks!
 
Answer:
You should override the PaymentModule class and add your custom variable to the email template.
Copy the validateOrder method from classes/PaymentModule.php
Create override/classes/PaymentModule.php and paste the validateOrder method:
<?php
class PaymentModule extends PaymentModuleCore
{
  //paste validateOrder here
}
Find the following line in validateOrder:
'{delivery_other}' => $delivery->other,
After that line assign your custom variable. For example:
'{delivery_date}' => $myDeliveryDate,
Remove /cache/class_index.php to clear the cache.
Copy order_conf.html and order_conf.txt from mails/en to themes/YOURTHEME/mails/en if they are not already there. This will prevent PrestaShop updates to overwrite your changes.
Add your custom variable to the new order_conf.html and order_conf.txt. For example:
<tr>
  <td align="left">Delivery date: {delivery_date}</td>
</tr>     

Prestashop autocomplete

Queation:
Im trying to add very simple autocomplete function to my prestashop addon input. What I want to achieve is something like this:
city.php
<label for="city">City: </label>
And auto.js
$(function() {
var availableTags = [
  "London",
  "Manchester",
  "Liverpool",
];
$( "#city" ).autocomplete({
  source: availableTags
});
The problem is that I dont know how to call jquery library in prestashop. I was trying to add something like this in my addon class:
$this->context->controller->addJqueryPlugin('autocomplete');
With no luck...
 
Answer:
1:In controllers you can add any JS files with
$this->addJS(_THEME_JS_DIR_.'index.js');
So, you can put this plugin to theme_folder/js/plugins/autocomplite.js and add it with $this->addJS(_THEME_JS_DIR_.'plugins/autocomplite.js');
2:
In Prestashop 1.6, using hook function, you can do something like this (actualy i'm using it inside a custom module) :
public function hookHeader() {
    //Jquery native Prestashop plugin
    $this->context->controller->addJQueryPlugin('fancybox');
    //CSS
    $this->context->controller->addCSS('//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css', 'all');
    $this->context->controller->addCSS('//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.css', 'all');
    $this->context->controller->addCSS('//cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.15.35/css/bootstrap-datetimepicker.css', 'all');
    $this->context->controller->addCSS('//cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.15.35/css/bootstrap-datetimepicker.min.css', 'all');
    //Javascript
    $this->context->controller->addJS('//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js', 'all');
    $this->context->controller->addJS('//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.js', 'all');
    $this->context->controller->addJS('//cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.js', 'all');
    $this->context->controller->addJS('//cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js', 'all');
    $this->context->controller->addJS('//cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/locale/fr.js', 'all');
    $this->context->controller->addJS('//cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.15.35/js/bootstrap-datetimepicker.min.js', 'all');
}
As you can see, i'm adding Fancybox, Bootstrap and DateTimePicker. You should add your own plugins inside js directory, inside your theme or module.
Calling a plugin in theme is easy using smarty ($js_dir i guess, or $tpl_dir)
EDIT :
Here's a sample of autocomplete in Prestashop :
TPL :
<!-- Block eversearch module TOP -->
<div id="search_block_top" class="col-sm-4 clearfix">
    <form id="searchbox" method="get" action="{$link->getPageLink('search')|escape:'html':'UTF-8'}" >
        <input type="hidden" name="controller" value="search" />
        <input type="hidden" name="orderby" value="position" />
        <input type="hidden" name="orderway" value="desc" />
        <input class="search_query form-control" type="text" id="search_query_top" name="search_query" placeholder="{l s='Search' mod='blocksearch'}" value="{$search_query|escape:'htmlall':'UTF-8'|stripslashes}" />
        <button type="submit" name="submit_search" class="btn btn-default button-search">
            <span>{l s='Search' mod='blocksearch'}</span>
        </button>
    </form>
And here's autocomplete using Jquery :
$(document).ready(function(){
//console.log('Autocomplete loaded');
var baseUrl = $('#baseURL').val();
var evertrade_module_dir = baseUrl+'/useful';
var form = $('.ever_search_query_top');
//console.log(baseUrl);
//Autocomplete
$('#ever_search_query_top').autocomplete(evertrade_module_dir+'/ajax_product_list.php', {
    minChars: 1,
    autoFill: true,
    max:20,
    matchContains: true,
    mustMatch:true,
    scroll:false,
    cacheLength:0,
    formatItem: function(item) {
        return item[1];

    }
}).result(function(e,i){ 
    console.log(i);
    if(i != undefined)
        $('#ever_search_query_top').val(i[1]);
        window.location.href = baseUrl+"recherche?orderby=position&orderway=desc&search_query="+i[1]+"";
});
Assuming your php file is returning correct values. Prefere use your own HTML, overriding tpl in your theme.

PrestaShop. How to fix the blank product page issue

This tutorial shows how to fix the blank product page issue in PrestaShop.
Today we will show how you can fix the blank page appearing instead of your product page when you click on the product.
The issue of the blank product page can occur in PrestaShop due to the following reasons:
  • upgrading Prestoshop version from the previous ones (1.4.x, 1.5.x)
  • server settings
  • third party modules installed
  • migration from subdomain to domain
To fix the blank product page, please try the possible fixes below:
  1. Clear smarty and web brwoser cache, especially if the problem appeared after moving your site from subdomain to domain.
  2. If any third party modules were installed, go to Modules -> Modules in your admin and disable the module(s):
    PrestaShop_How_to_fix_the_blank_product_page_issue_1
  3. Deleting and regenerating the .htaccess file can solve the problem.
    In order to do it, delete the .htaccess file from the root directory on the server using FTP or in cPanel (do not forget to make a back up of the file first) and refresh your front office:
    PrestaShop_How_to_fix_the_blank_product_page_issue_2
  4. Another thing worth doing is activating a debug mode and setting _PS_MODE_DEV_ to true. Please note that this fix is mostly used for Prestashop 1.5.
    To activate a debug mode, you need to open config/config.inc.php file on your server and find the following lines:

    1
    2
    @ini_set('display_errors', 'off');
    define('_PS_DEBUG_SQL_', false)
    change ‘off’ to ‘on’ and false to true, like this:

    1
    @ini_set('display_errors', 'on');<br>define('_PS_DEBUG_SQL_', true);
    We strongly recommend that you make a back up before modifying the file.
    Besides, you may need to change the setting for _PS_MODE_DEV_. Open config/defines.inc.php file on the server and find the following line:

    1
    define('_PS_MODE_DEV_', false);
    change it to

    1
    define('_PS_MODE_DEV_', true);
    Be sure to make a back up before editing the file:
    PrestaShop_How_to_fix_the_blank_product_page_issue_3
  5. One more possible solution is increasing memory limit for the site.
    This can be done either by adding the following code in config.inc.php:

    1
    ini_set('memory_limit','128M');
    or edit memory limit in the php.ini located in the root of your Prestashop installation folder (if you do not have such a file in the root of your site folder, you can simply create a new text file and name it “php.ini” and upload it on the server):

    1
    memory_limit = 256M;
    PrestaShop_How_to_fix_the_blank_product_page_issue_4
Please note that the above described methods may not always help depending on the circumstances and environment of your Prestashop site. In this case, we recommend that you visit Prestashop official forum or/and contact your hosting provider.

Prestashop no errors / blank page

Question:
I'm developing a module in PHP for Prestashop and I'm having a tough time trying to debug code. Whenever something falls over it doesn't display errors, just a blank page - either on the front end where the module is hooked, or on the back end module page.
I'm trying to write in another class, or another function but it doesn't like it at all.
It's on a local dev server, PHP errors are on etc.
Can somebody tell me any other way to debug stuff instead of commenting out code? Or some way of getting error codes?
Thanks for your help in advance.
 
Answer:
 As1:
Try opening config/config.inc.php and then change:
@ini_set('display_errors', 'off')
to
@ini_set('display_errors', 'on').

From PS 1.5+, you need to open config/defines.inc.php and change:
define('_PS_MODE_DEV_', false);
to
define('_PS_MODE_DEV_', true);
 
AS2: check this out for the final solution!
First of all, you need to enable errors reporting on your website.
1) Open the file config\config.inc.php and find the following line:
@ini_set(‘display_errors’, off’);    
2) Change ‘off’ to ‘on’, re-upload the file and refresh your page.
If it doesn’t help, go to the next step.
3)Add this code to the top of your index.php file in the root of PrestaShop installation and re-upload it on your server. Then try to access your website and admin panel.
    <?php error_reporting(0); 
       $old_error_handler = set_error_handler("userErrorHandler");

       function userErrorHandler ($errno, $errmsg, $filename, $linenum,  $vars) 
     {
     $time=date("d M Y H:i:s"); 
     // Get the error type from the error number 
     $errortype = array (1    => "Error",
                         2    => "Warning",
                         4    => "Parsing Error",
                     8    => "Notice",
                     16   => "Core Error",
                     32   => "Core Warning",
                     64   => "Compile Error",
                     128  => "Compile Warning",
                     256  => "User Error",
                     512  => "User Warning",
                     1024 => "User Notice");
  $errlevel=$errortype[$errno];

  //Write error to log file (CSV format) 
  $errfile=fopen("errors.csv","a"); 
  fputs($errfile,"\"$time\",\"$filename: 
  $linenum\",\"($errlevel) $errmsg\"\r\n"); 
  fclose($errfile);

  if($errno!=2 && $errno!=8) {
     //Terminate script if fatal error
     die("A fatal error has occurred. Script execution has been aborted");
  } 
   }
?>
After this manipulations you will find the file called errors.csv in the folder where your index.php file is located. Download and open the file errors.csv using any text editor, you will find the error log there.