<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>NemoPS &#187; back office</title>
	<atom:link href="http://nemops.com/tag/back-office/feed/" rel="self" type="application/rss+xml" />
	<link>http://nemops.com</link>
	<description>Prestashop Tutorials, Modules and More!</description>
	<lastBuildDate>Wed, 05 Dec 2018 13:25:23 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.35</generator>
	<item>
		<title>Change department for customer threads in PrestaShop 1.6</title>
		<link>http://nemops.com/prestashop-customer-threads-change-department/</link>
		<comments>http://nemops.com/prestashop-customer-threads-change-department/#comments</comments>
		<pubDate>Tue, 20 Jun 2017 17:46:55 +0000</pubDate>
		<dc:creator><![CDATA[Nemo]]></dc:creator>
				<category><![CDATA[Tips n Tricks]]></category>
		<category><![CDATA[back office]]></category>
		<category><![CDATA[customer service]]></category>
		<category><![CDATA[department]]></category>
		<category><![CDATA[messages]]></category>
		<category><![CDATA[threads]]></category>

		<guid isPermaLink="false">http://nemops.com/?p=3036</guid>
		<description><![CDATA[<p>In this quick tip, we will see how to easily modify the PrestaShop back office template, so to be able to change the customer messages&#8217; department whenever we want. Watch the screencast Text Version This tutorial can be applied to ThirtyBees as well! Part of the functionality we need is in PrestaShop already, all we [&#8230;]</p>
<p>The post <a rel="nofollow" href="http://nemops.com/prestashop-customer-threads-change-department/">Change department for customer threads in PrestaShop 1.6</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>In this quick tip, we will see how to easily modify the PrestaShop back office template, so to be able to change the customer messages&#8217; department whenever we want.</p>
<p><span id="more-3036"></span></p>
<h2>Watch the screencast</h2>

	<div class="video-embed">
		<iframe width="640" height="360" src="http://www.youtube.com/embed/Ol_RHo1mwcg#038;feature=youtu.be" frameborder="0" allowfullscreen></iframe><p><a href="https://www.youtube.com/user/NemoPostScriptum/videos" rel="nofollow" title="Subscribe Post Scriptum's Youtube Channel">Subscribe Post Scriptum's Youtube Channel</a></p>	</div>
<h2>Text Version</h2>
<p>This tutorial can be applied to <strong><a href="http://thirtybees.com" title="ThirtyBees e-commerce software" target="_blank">ThirtyBees</a></strong> as well!</p>
<p>Part of the functionality we need is in PrestaShop already, all we have to do is add some place where we can submit the change of department type.<br />
Open up <strong>AdminCustomerThreadsController.php</strong> located in <em>controllers/admin</em> or use an override instead (recommended). We are interested in the renderView method, specifically where it assigns <strong>$this->tpl_vars</strong>, around line 700 in PrestaShop 1.6.1.7.</p>
<pre class="brush: php; title: ; notranslate">
        $this-&gt;tpl_view_vars = array(
            'id_customer_thread' =&gt; $id_customer_thread,
            'thread' =&gt; $thread,
            'actions' =&gt; $actions,
            'employees' =&gt; $employees,
            'current_employee' =&gt; $this-&gt;context-&gt;employee,
            'messages' =&gt; $messages,
            'first_message' =&gt; $first_message,
            'contact' =&gt; $contact,
            'contacts' =&gt; $contacts, // &lt;-- This is what we added!
            'next_thread' =&gt; $next_thread,
            'orders' =&gt; isset($orders) ? $orders : false,
            'customer' =&gt; isset($customer) ? $customer : false,
            'products' =&gt; isset($products) ? $products : false,
            'total_ok' =&gt; isset($total_ok) ?  Tools::displayPrice($total_ok, $this-&gt;context-&gt;currency) : false,
            'orders_ok' =&gt; isset($orders_ok) ? $orders_ok : false,
            'count_ok' =&gt; isset($orders_ok) ? count($orders_ok) : false,
            'PS_CUSTOMER_SERVICE_SIGNATURE' =&gt; str_replace('\r\n', &quot;\n&quot;, Configuration::get('PS_CUSTOMER_SERVICE_SIGNATURE', (int)$thread-&gt;id_lang)),
            'timeline_items' =&gt; $timeline_items,
        );
</pre>
<p><strong>Please note:</strong> if you use an override, copy the whole method, add the variable as described above, and make sure you change return <strong>parent::renderView()</strong> to return <strong>AdminController::renderView()</strong> at the very end! Failing to do so will make it impossible for our new variable to be used in the template, as the parent class would simply override the tpl_vars.</p>
<p>Now that we have the variable containing all contacts, let&#8217;s add a form to submit it, in the view.tpl template of that controller. The file we want is located in the theme folder  <em>themes\default\template\controllers\customer_threads\helpers\view</em>. Once more, it&#8217;s <strong>named view.tpl</strong>.<br />
You can find any spot you like for the new button, I added it at the very beginning, before the div with class &#8220;well&#8221;</p>
<pre class="brush: php; html-script: true; title: ; notranslate">
	&lt;div class=&quot;well&quot;&gt;
		&lt;form action=&quot;{$link-&gt;getAdminLink('AdminCustomerThreads')|escape:'html':'UTF-8'}&amp;amp;viewcustomer_thread&amp;amp;id_customer_thread={$id_customer_thread|intval}&quot; method=&quot;post&quot; class=&quot;form-horizontal&quot;&gt;
			&lt;div class=&quot;row&quot;&gt;
				&lt;div class=&quot;col-sm-3&quot;&gt;
					&lt;select name=&quot;id_contact&quot;&gt;
						{foreach from=$contacts item=dept}
							&lt;option value=&quot;{$dept.id_contact}&quot; {if $dept.name == $contact}selected=&quot;selected&quot;{/if}&gt;
								{$dept.name}
							&lt;/option&gt;
						{/foreach}
					&lt;/select&gt;
				&lt;/div&gt;
				&lt;div class=&quot;col-sm-3&quot;&gt;
					&lt;button class=&quot;btn btn-default&quot; type=&quot;submit&quot;&gt;
						{l s='Change Department'}
					&lt;/button&gt;
				&lt;/div&gt;
			&lt;/div&gt;
		&lt;/form&gt;
	&lt;/div&gt;
</pre>
<p>Save and refresh, we should be done! We didn&#8217;t have to add any post processing code, simply because it&#8217;s already present, at the very beginning of the <strong>postProcess</strong> method of the AdminCustomerThreadsController.</p>
<p>The post <a rel="nofollow" href="http://nemops.com/prestashop-customer-threads-change-department/">Change department for customer threads in PrestaShop 1.6</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://nemops.com/prestashop-customer-threads-change-department/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Hooking modules to the Category Back Office in Prestashop</title>
		<link>http://nemops.com/hook-modules-prestashop-category-back-office/</link>
		<comments>http://nemops.com/hook-modules-prestashop-category-back-office/#comments</comments>
		<pubDate>Tue, 17 May 2016 09:42:05 +0000</pubDate>
		<dc:creator><![CDATA[Nemo]]></dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[back office]]></category>
		<category><![CDATA[category]]></category>
		<category><![CDATA[hooks]]></category>
		<category><![CDATA[prestashop]]></category>

		<guid isPermaLink="false">http://nemops.com/?p=2772</guid>
		<description><![CDATA[<p>If you want to add extra fields to the category configuration page, there is no better way than using a module hooked to DisplayBackOfficeCategory. Let&#8217;s see how to implement it! Starting with a simple module First, download the project file, and place the module you will find inside the &#8220;start&#8221; folder in the modules/ folder [&#8230;]</p>
<p>The post <a rel="nofollow" href="http://nemops.com/hook-modules-prestashop-category-back-office/">Hooking modules to the Category Back Office in Prestashop</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>If you want to add extra fields to the category configuration page, there is no better way than using a module hooked to DisplayBackOfficeCategory. Let&#8217;s see how to implement it!</p>
<p><span id="more-2772"></span></p>
<a class="download-files button style1" href="http://nemops.com/wp-content/uploads/2016/05/project.zip" title="Download Project Files">Download Project Files</a>
<h2>Starting with a simple module</h2>
<p>First, download the project file, and place the module you will find inside the &#8220;start&#8221; folder in the modules/ folder of your prestashop installation.</p>
<p>Open up displaybocategorytut.php, it&#8217;s just a very basic module structure.</p>
<pre class="brush: php; title: ; notranslate">
if (!defined('_PS_VERSION_'))
	exit;

class displayBoCategoryTut extends Module
{

	protected $_errors = array();
	protected $_html = '';


	public function __construct()
	{
		$this-&gt;name = 'displaybocategorytut';
		$this-&gt;tab = 'front_office_features';
		$this-&gt;version = '1.0';
		$this-&gt;author = 'Nemo';
		$this-&gt;need_instance = 0;
		
		$this-&gt;bootstrap = true;

	 	parent::__construct();

		$this-&gt;displayName = $this-&gt;l('Display BO Category Tutorial');
		$this-&gt;description = $this-&gt;l('Displays an additional field in the category back office');
	}
	
	public function install()
	{
		if (!parent::install())
			return false;
		return true;
	}

	public function uninstall()
	{
		if (!parent::uninstall())
			return false;
		return true;
	}

}

</pre>
<p>The first thing we need is of course some additional data we want to save and retrieve. For this reason, we need an extra method to modify the database, and add a further column to the category table:</p>
<pre class="brush: php; title: ; notranslate">
	public function alterTable($method = 'add')
	{
		if($method == 'add')
			$sql = 'ALTER TABLE ' . _DB_PREFIX_ . 'category ADD `myowninput` VARCHAR (255) NOT NULL';
		else 
			$sql = 'ALTER TABLE ' . _DB_PREFIX_ . 'category DROP COLUMN `myowninput`';

		if(!Db::getInstance()-&gt;Execute($sql))
			return false;
		return true;
	}
</pre>
<p><strong>Explanation</strong>: since we need the extra column, we are using a single method to add and remove it. We are passing in a &#8220;method&#8221; parameter, so that we can switch between actions depending on our needs.</p>
<p>As mentioned, we need this column to be added when installing, and removed when uninstalling, so let&#8217;s amend the install and uninstall methods as well:</p>
<pre class="brush: php; title: ; notranslate">


	public function install()
	{
		if (!parent::install() OR
			!$this-&gt;alterTable() OR
			!$this-&gt;registerHook('displayBackOfficeCategory') OR
			!$this-&gt;registerHook('categoryAddition') OR
			!$this-&gt;registerHook('categoryUpdate')
			)
			return false;
		return true;
	}

	public function uninstall()
	{
		if (!parent::uninstall() OR
			!$this-&gt;alterTable('remove'))
			return false;
		return true;
	}

</pre>
<p>Additionally, I am registering two hooks to update the field&#8217;s value. This would not be necessary if we had a Category class override to take care of the extra field (see more on <a href="http://nemops.com/extending-prestashop-objects/" title="Extending PrestaShop Objects">Extending PrestaShop Objects</a>).</p>
<p>Next, we will need some way to retrieve our custom field from the database</p>
<pre class="brush: php; title: ; notranslate">
	public function getMyOwnInput($id_category)
	{
		return Db::getInstance()-&gt;getValue('SELECT myowninput FROM '._DB_PREFIX_.'category WHERE id_category = '. (int)$id_category);
	}
</pre>
<p>Then, it&#8217;s time to display something in the category back office. Let&#8217;s create the hooking method:</p>
<pre class="brush: php; title: ; notranslate">
	public function hookDisplayBackOfficeCategory($params)
	{

		// we need an actual id, otherwise if we are just adding the category this field can be left empty
		if(Tools::getValue('id_category'))
			$myowninput = $this-&gt;getMyOwnInput(Tools::getValue('id_category'));
		else $myowninput = '';

		$this-&gt;context-&gt;smarty-&gt;assign(array(
			'myowninput'=&gt; $myowninput
		));


		return $this-&gt;display(__FILE__, 'backoffice.tpl');
	}

</pre>
<p><strong>Explanation:</strong> First off, we make sure we have a category ID that we can use to retrieve the value from the database. We use a switch to prevent the script from causing trouble in case there is none (that is, we are just creating a new category). Then, we assign the input value to the template, and return it. We don&#8217;t have it yet, so let&#8217;s create a new file inside <em>views\templates\hook</em>, naming it <strong>backoffice.tpl</strong></p>
<p>Let&#8217;s add some simple markup:</p>
<pre class="brush: php; html-script: true; title: ; notranslate">
&lt;div class=&quot;form-group&quot;&gt;
	&lt;label class=&quot;control-label col-lg-3&quot;&gt;
		&lt;span class=&quot;label-tooltip&quot;&gt;
			{l s='Custom Input' mod='displaybocategorytut'}
		&lt;/span&gt;
	&lt;/label&gt;
	&lt;div class=&quot;col-lg-4&quot;&gt;
		&lt;input type=&quot;text&quot; name=&quot;myowninput&quot; value=&quot;{$myowninput}&quot;&gt;
	&lt;/div&gt;
	&lt;div class=&quot;col-lg-6 col-lg-offset-3&quot;&gt;
	&lt;/div&gt;
&lt;/div&gt;
</pre>
<p>We are ready to install the module! Go ahead and do it from the modules page. If everything goes smoothly as it should, reach a category and click edit (or add one). It should display our new field:</p>
<p><a href="http://nemops.com/wp-content/uploads/2016/05/displaybocategory.png"><img src="http://nemops.com/wp-content/uploads/2016/05/displaybocategory-680x247.png" alt="New input in the PrestaShop Category Back Office " width="680" height="247" class="aligncenter size-large wp-image-2776" /></a></p>
<p>It won&#8217;t do much at the time being, since we are not saving the value on submit. For this, we need another couple of methods that will take advantage of the hooks we registered upon install:</p>
<pre class="brush: php; title: ; notranslate">
	public function hookCategoryAddition($params)
	{
		Db::getInstance()-&gt;update('category', array('myowninput' =&gt; pSQL(Tools::getValue('myowninput'))), 'id_category = ' . $params['category']-&gt;id);
	}

	public function hookCategoryUpdate($params)
	{
		$this-&gt;hookCategoryAddition($params);
	}
</pre>
<p><strong>Explanation:</strong> here we are using some standard code to update the database: the myowninput value is sent over via POST when submitting the page, and the $params variable passed to the method contains a useful Category object, from which we are taking the ID.</p>
<p>Now write something in the field and save, it should be stored in the database! To make sure everything runs smoothly, create a new category as well, adding content to our field before submitting the page.</p>
<p>Once everything works, you can try to expand the module with hooks, in the front office as well, and take full advantage of the new value.</p>
<h3>Additional Resources </h3>
<ul>
<li>
Learn how to develop PrestaShop Modules with my <a href="http://nemops.com/prestashop-modules-course/" title="PrestaShop Modules Course">PrestaShop Modules Course</a>
</li>
</ul>
<p>The post <a rel="nofollow" href="http://nemops.com/hook-modules-prestashop-category-back-office/">Hooking modules to the Category Back Office in Prestashop</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://nemops.com/hook-modules-prestashop-category-back-office/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Adding new fields to the PrestaShop CSV Importer</title>
		<link>http://nemops.com/new-fields-prestashop-csv-importer/</link>
		<comments>http://nemops.com/new-fields-prestashop-csv-importer/#comments</comments>
		<pubDate>Mon, 04 Apr 2016 09:40:19 +0000</pubDate>
		<dc:creator><![CDATA[Nemo]]></dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[back office]]></category>
		<category><![CDATA[csv]]></category>
		<category><![CDATA[import]]></category>
		<category><![CDATA[spreadsheet]]></category>

		<guid isPermaLink="false">http://nemops.com/?p=2750</guid>
		<description><![CDATA[<p>The CSV import PrestaShop natively comes with becomes useless if we have added custom fields to our objects. Let&#8217;s see how to overcome the limit, and enable extra fields in the CSV Importer as well. Adding an extra field to PrestaShop objects Before doing anything with CSVs or the importer, we need a field to [&#8230;]</p>
<p>The post <a rel="nofollow" href="http://nemops.com/new-fields-prestashop-csv-importer/">Adding new fields to the PrestaShop CSV Importer</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>The CSV import PrestaShop natively comes with becomes useless if we have added custom fields to our objects. Let&#8217;s see how to overcome the limit, and enable extra fields in the CSV Importer as well.</p>
<p><span id="more-2750"></span></p>
<h2>Adding an extra field to PrestaShop objects</h2>
<p>Before doing anything with CSVs or the importer, we need a field to fill with your data. If you don&#8217;t know how to add one, here is a tutorial on <a href="http://nemops.com/extending-prestashop-objects/#.Vv5Nkfn5jmg" title="How to extend PrestaShop Objects">How to extend PrestaShop Objects</a>, and add new fields to them.<br />
In this example, we will use that extrafield one added in the tutorial.<br />
As a side note, it&#8217;s not strictly necessary to add the extra field to the product object, as we will see, but it&#8217;s essential to have a database column we can use.</p>
<div class="separator"></div>
<h2>Two approaches</h2>
<p>Given that the Product class override is not strictly necessary, we can proceed in two ways, depending on our needs: the first, is to complete the previous tutorial, and add the field to the Product Object; the second is to stop after adding the database column, and override an extra method of the AdminImportController, to manually update the new field. We will cover both to see how they work.</p>
<div class="separator"></div>
<h2>The AdminImportController override</h2>
<p>Let&#8217;s start playing with the real file. First of all, create a new file in <em>override/controllers/admin</em>, and name it <strong>AdminImportController.php</strong></p>
<p>Open it up, and add some standard override code within PHP tags</p>
<pre class="brush: php; title: ; notranslate">
class AdminImportController extends AdminImportControllerCore
{

}
</pre>
<p>Next, we want to tell the Importer we have an extra field for products. To do this, we have to override the whole construct method, since it&#8217;s the one defining available fields for all entities. It&#8217;s too long to copy it here, to make sure you grab yours from the original Controller, and drop it into the override.</p>
<pre class="brush: php; title: ; notranslate">
class AdminImportController extends AdminImportControllerCore
{
        $this-&gt;bootstrap = true;
        $this-&gt;entities = array(
            $this-&gt;l('Categories'),
            $this-&gt;l('Products'),
            $this-&gt;l('Combinations'),
            $this-&gt;l('Customers'),
            $this-&gt;l('Addresses'),
            $this-&gt;l('Manufacturers'),
            $this-&gt;l('Suppliers'),
            $this-&gt;l('Alias'),
        );
        // more code here

        $this-&gt;separator = ($separator = Tools::substr(strval(trim(Tools::getValue('separator'))), 0, 1)) ? $separator :  ';';
        $this-&gt;multiple_value_separator = ($separator = Tools::substr(strval(trim(Tools::getValue('multiple_value_separator'))), 0, 1)) ? $separator :  ',';
        AdminController::__construct();
}
</pre>
<p><strong>Make absolutely sure you change the very last call to AdminController::__construct(); to avoid losing any modification to the product properties.</strong></p>
<p>Now that the override is in place, we must let it know about our field. Locate the following snippet:</p>
<pre class="brush: php; title: ; notranslate">
            case $this-&gt;entities[$this-&gt;l('Products')]:
                self::$validators['image'] = array(
                    'AdminImportController',
                    'split'
                );
</pre>
<p>You will notice it&#8217;s followed by an array defining available fields:</p>
<pre class="brush: php; title: ; notranslate">
               $this-&gt;available_fields = array(
                    'no' =&gt; array('label' =&gt; $this-&gt;l('Ignore this column')),
                    'id' =&gt; array('label' =&gt; $this-&gt;l('ID')),
                    'active' =&gt; array('label' =&gt; $this-&gt;l('Active (0/1)')),
                    'name' =&gt; array('label' =&gt; $this-&gt;l('Name')),
                    'category' =&gt; array('label' =&gt; $this-&gt;l('Categories (x,y,z...)')),
                    'price_tex' =&gt; array('label' =&gt; $this-&gt;l('Price tax excluded')),
                    'price_tin' =&gt; array('label' =&gt; $this-&gt;l('Price tax included')),
                    'id_tax_rules_group' =&gt; array('label' =&gt; $this-&gt;l('Tax rules ID')),
                    'wholesale_price' =&gt; array('label' =&gt; $this-&gt;l('Wholesale price')),
                    'on_sale' =&gt; array('label' =&gt; $this-&gt;l('On sale (0/1)')),
                    'reduction_price' =&gt; array('label' =&gt; $this-&gt;l('Discount amount')),
                    'reduction_percent' =&gt; array('label' =&gt; $this-&gt;l('Discount percent')),
                    'reduction_from' =&gt; array('label' =&gt; $this-&gt;l('Discount from (yyyy-mm-dd)')),
                    'reduction_to' =&gt; array('label' =&gt; $this-&gt;l('Discount to (yyyy-mm-dd)')),
                    'reference' =&gt; array('label' =&gt; $this-&gt;l('Reference #')),
                    'supplier_reference' =&gt; array('label' =&gt; $this-&gt;l('Supplier reference #')),
                    'supplier' =&gt; array('label' =&gt; $this-&gt;l('Supplier')),
                    'manufacturer' =&gt; array('label' =&gt; $this-&gt;l('Manufacturer')),
                    'ean13' =&gt; array('label' =&gt; $this-&gt;l('EAN13')),
                    'upc' =&gt; array('label' =&gt; $this-&gt;l('UPC')),
                    'ecotax' =&gt; array('label' =&gt; $this-&gt;l('Ecotax')),
                    'width' =&gt; array('label' =&gt; $this-&gt;l('Width')),
                    'height' =&gt; array('label' =&gt; $this-&gt;l('Height')),
                    'depth' =&gt; array('label' =&gt; $this-&gt;l('Depth')),
                    'weight' =&gt; array('label' =&gt; $this-&gt;l('Weight')),
                    'quantity' =&gt; array('label' =&gt; $this-&gt;l('Quantity')),
                    'minimal_quantity' =&gt; array('label' =&gt; $this-&gt;l('Minimal quantity')),
                    'visibility' =&gt; array('label' =&gt; $this-&gt;l('Visibility')),
                    'additional_shipping_cost' =&gt; array('label' =&gt; $this-&gt;l('Additional shipping cost')),
                    'unity' =&gt; array('label' =&gt; $this-&gt;l('Unit for the unit price')),
                    'unit_price' =&gt; array('label' =&gt; $this-&gt;l('Unit price')),
                    'description_short' =&gt; array('label' =&gt; $this-&gt;l('Short description')),
                    'description' =&gt; array('label' =&gt; $this-&gt;l('Description')),
                    'tags' =&gt; array('label' =&gt; $this-&gt;l('Tags (x,y,z...)')),
                    'meta_title' =&gt; array('label' =&gt; $this-&gt;l('Meta title')),
                    'meta_keywords' =&gt; array('label' =&gt; $this-&gt;l('Meta keywords')),
                    'meta_description' =&gt; array('label' =&gt; $this-&gt;l('Meta description')),
                    'link_rewrite' =&gt; array('label' =&gt; $this-&gt;l('URL rewritten')),
                    'available_now' =&gt; array('label' =&gt; $this-&gt;l('Text when in stock')),
                    'available_later' =&gt; array('label' =&gt; $this-&gt;l('Text when backorder allowed')),
                    'available_for_order' =&gt; array('label' =&gt; $this-&gt;l('Available for order (0 = No, 1 = Yes)')),
                    'available_date' =&gt; array('label' =&gt; $this-&gt;l('Product availability date')),
                    'date_add' =&gt; array('label' =&gt; $this-&gt;l('Product creation date')),
                    'show_price' =&gt; array('label' =&gt; $this-&gt;l('Show price (0 = No, 1 = Yes)')),
                    'image' =&gt; array('label' =&gt; $this-&gt;l('Image URLs (x,y,z...)')),
                    'delete_existing_images' =&gt; array(
                        'label' =&gt; $this-&gt;l('Delete existing images (0 = No, 1 = Yes)')
                    ),
                    'features' =&gt; array('label' =&gt; $this-&gt;l('Feature (Name:Value:Position:Customized)')),
                    'online_only' =&gt; array('label' =&gt; $this-&gt;l('Available online only (0 = No, 1 = Yes)')),
                    'condition' =&gt; array('label' =&gt; $this-&gt;l('Condition')),
                    'customizable' =&gt; array('label' =&gt; $this-&gt;l('Customizable (0 = No, 1 = Yes)')),
                    'uploadable_files' =&gt; array('label' =&gt; $this-&gt;l('Uploadable files (0 = No, 1 = Yes)')),
                    'text_fields' =&gt; array('label' =&gt; $this-&gt;l('Text fields (0 = No, 1 = Yes)')),
                    'out_of_stock' =&gt; array('label' =&gt; $this-&gt;l('Action when out of stock')),
                    'shop' =&gt; array(
                        'label' =&gt; $this-&gt;l('ID / Name of shop'),
                        'help' =&gt; $this-&gt;l('Ignore this field if you don\'t use the Multistore tool. If you leave this field empty, the default shop will be used.'),
                    ),
                    'advanced_stock_management' =&gt; array(
                        'label' =&gt; $this-&gt;l('Advanced Stock Management'),
                        'help' =&gt; $this-&gt;l('Enable Advanced Stock Management on product (0 = No, 1 = Yes).')
                    ),
                    'depends_on_stock' =&gt; array(
                        'label' =&gt; $this-&gt;l('Depends on stock'),
                        'help' =&gt; $this-&gt;l('0 = Use quantity set in product, 1 = Use quantity from warehouse.')
                    ),
                    'warehouse' =&gt; array(
                        'label' =&gt; $this-&gt;l('Warehouse'),
                        'help' =&gt; $this-&gt;l('ID of the warehouse to set as storage.')
                    )
                );
</pre>
<p>This represents all of the fields, or columns, that you can map to every column of your csv file. At this point, it&#8217;s enough to append our element to the array:</p>
<pre class="brush: php; title: ; notranslate">
                    'depends_on_stock' =&gt; array(
                        'label' =&gt; $this-&gt;l('Depends on stock'),
                        'help' =&gt; $this-&gt;l('0 = Use quantity set in product, 1 = Use quantity from warehouse.')
                    ),
                    'warehouse' =&gt; array(
                        'label' =&gt; $this-&gt;l('Warehouse'),
                        'help' =&gt; $this-&gt;l('ID of the warehouse to set as storage.')
                    ),
                    'extrafield' =&gt; array(
                        'label' =&gt; $this-&gt;l('Extrafield'),
                        'help' =&gt; $this-&gt;l('Something')
                    )
                );
</pre>
<p>Save, then reach the <em>cache</em> folder and delete <strong>class_index.php</strong>, so that the override file is loaded.</p>
<p><strong>If you added the Product class override, you can skip to Testing The Import</strong></p>
<p>Otherwise, there is a little snippet you need to add. Unfortunately, in order to do it we have to <strong>override the whole ProductImport()</strong> method. Therefore, copy and paste yours into the override file we created; then, reach the very end of it, where it reads:</p>
<pre class="brush: php; title: ; notranslate">
        $this-&gt;closeCsvFile($handle);
        Module::processDeferedFuncCall();
        Module::processDeferedClearCache();
        Tag::updateTagCount();
</pre>
<p>Right before, add the following statement</p>
<pre class="brush: php; title: ; notranslate">
Db::getInstance()-&gt;update('product', array('extrafield' =&gt; $info['extrafield']), 'id_product = ' . (int)$product-&gt;id);
</pre>
<p>This will manually update the field, in case it was not part of the product object.</p>
<div class="separator"></div>
<h2>Testing The Import</h2>
<p><strong>Before proceeding: Make sure you do not have a product with the same ID of the sample one, or it will be overridden.</strong></p>
<p>We are ready for a test run. Download the product csv sample from <strong>Advanced Parameters > CSV Import</strong></p>
<p><a href="http://nemops.com/wp-content/uploads/2016/04/download_sample.png"><img src="http://nemops.com/wp-content/uploads/2016/04/download_sample-680x332.png" alt="PrestaShop Sample CSV File Download" width="680" height="332" class="aligncenter size-large wp-image-2752" /></a></p>
<p>Open up the file in any text editor, get rid of all lines apart from the heading and first product. Then, add a new heading after &#8220;Warehouse&#8221;, and a value for it on the next line:</p>
<p><a href="http://nemops.com/wp-content/uploads/2016/04/extrafield_product.png"><img src="http://nemops.com/wp-content/uploads/2016/04/extrafield_product.png" alt="Adding an extra field value to the csv for PrestaShop" width="349" height="104" class="aligncenter size-full wp-image-2754" /></a></p>
<p><a href="http://nemops.com/wp-content/uploads/2016/04/extrafield_heading.png"><img src="http://nemops.com/wp-content/uploads/2016/04/extrafield_heading.png" alt="Adding an extra field to the csv for PrestaShop" width="381" height="140" class="aligncenter size-full wp-image-2753" /></a></p>
<p>Save the file. Now load it up in the importer. Make sure you select Products as entity, and leave all other settings as default. Hit Next.</p>
<p><a href="http://nemops.com/wp-content/uploads/2016/04/importer_settings.png"><img src="http://nemops.com/wp-content/uploads/2016/04/importer_settings-680x752.png" alt="PrestaShop CSV Import Settings" width="680" height="752" class="aligncenter size-large wp-image-2755" /></a></p>
<p>On the next screen, hit the next arrow until you reach the end of the file. You should see the new column popping up:</p>
<p><a href="http://nemops.com/wp-content/uploads/2016/04/importer_columns.png"><img src="http://nemops.com/wp-content/uploads/2016/04/importer_columns-680x172.png" alt="PrestaShop CSV Import Settings for Columns" width="680" height="172" class="aligncenter size-large wp-image-2756" /></a></p>
<p>Now proceed and simply hit import to complete the process. You will probably get an error because of the broken image url, but the new field should be added to the database:</p>
<p><a href="http://nemops.com/wp-content/uploads/2016/04/database_updated.png"><img src="http://nemops.com/wp-content/uploads/2016/04/database_updated.png" alt="PrestaShop Database Updated PrestaShop Database via CSV via CSV" width="537" height="219" class="aligncenter size-full wp-image-2757" /></a></p>
<p>We are done! Now you can display the extra field the way you like, whether it is with a module or following the previously linked tutorial.</p>
<h3>Additional Resources on CSV Import in PrestaShop</h3>
<ul>
<li><a href="http://nemops.com/extending-prestashop-objects/#.Vv5Nkfn5jmg" title="How to extend PrestaShop Objects">How to extend PrestaShop Objects</a></li>
<li><a href="http://nemops.com/prestashop-import-csv-data-in-1-6/#.VwIzWvn5jmg" title="Prestashop: Import CSV data in 1.6">Prestashop: Import CSV data in 1.6</a></li>
</ul>
<p>The post <a rel="nofollow" href="http://nemops.com/new-fields-prestashop-csv-importer/">Adding new fields to the PrestaShop CSV Importer</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://nemops.com/new-fields-prestashop-csv-importer/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>PrestaShop 1.7 Pre-Beta video Preview</title>
		<link>http://nemops.com/prestashop-1-7-pre-beta-preview/</link>
		<comments>http://nemops.com/prestashop-1-7-pre-beta-preview/#comments</comments>
		<pubDate>Wed, 24 Feb 2016 09:31:14 +0000</pubDate>
		<dc:creator><![CDATA[Nemo]]></dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[back office]]></category>
		<category><![CDATA[prestashop]]></category>
		<category><![CDATA[prestashop 1.7]]></category>
		<category><![CDATA[preview]]></category>

		<guid isPermaLink="false">http://nemops.com/?p=2721</guid>
		<description><![CDATA[<p>In this first video on PrestaShop 1.7, we will see what&#8217;s the current state of development, exploring the front office and the product and modules catalog in the back office. Watch the screencast More about PrestaShop 1.7 PrestaShop 1.7&#8217;s new theme Preview PrestaShop 1.7 will be a catastrophe. Here is why</p>
<p>The post <a rel="nofollow" href="http://nemops.com/prestashop-1-7-pre-beta-preview/">PrestaShop 1.7 Pre-Beta video Preview</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>In this first video on PrestaShop 1.7, we will see what&#8217;s the current state of development, exploring the front office and the product and modules catalog in the back office.</p>
<p><span id="more-2721"></span></p>
<h2>Watch the screencast</h2>

	<div class="video-embed">
		<iframe width="640" height="360" src="http://www.youtube.com/embed/UUmTq-tfADw" frameborder="0" allowfullscreen></iframe><p><a href="https://www.youtube.com/user/NemoPostScriptum/videos" rel="nofollow" title="Subscribe Post Scriptum's Youtube Channel">Subscribe Post Scriptum's Youtube Channel</a></p>	</div>
<div class="separator"></div>
<h3>More about PrestaShop 1.7</h3>
<ul>
<li><a href="http://nemops.com/prestashop-1-7-new-theme-preview/#.Vs14E_k4Hmg" title="PrestaShop 1.7 new theme Preview">PrestaShop 1.7&#8217;s new theme Preview</a></li>
<li><a href="http://nemops.com/prestashop-1-7-will-be-a-catastrophe-here-is-why/#.Vs14O_k4Hmg" title="http://nemops.com/prestashop-1-7-will-be-a-catastrophe-here-is-why/#.Vs14O_k4Hmg">PrestaShop 1.7 will be a catastrophe. Here is why</a></li>
</ul>
<p>The post <a rel="nofollow" href="http://nemops.com/prestashop-1-7-pre-beta-preview/">PrestaShop 1.7 Pre-Beta video Preview</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://nemops.com/prestashop-1-7-pre-beta-preview/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>How to upload new file types with the Prestashop Filemanager</title>
		<link>http://nemops.com/new-file-types-filemanager/</link>
		<comments>http://nemops.com/new-file-types-filemanager/#comments</comments>
		<pubDate>Wed, 23 Sep 2015 08:32:23 +0000</pubDate>
		<dc:creator><![CDATA[Nemo]]></dc:creator>
				<category><![CDATA[Tips n Tricks]]></category>
		<category><![CDATA[back office]]></category>
		<category><![CDATA[filemanager]]></category>
		<category><![CDATA[prestashop]]></category>
		<category><![CDATA[upload]]></category>

		<guid isPermaLink="false">http://nemops.com/?p=2537</guid>
		<description><![CDATA[<p>If you are struggling with ftp every time you need to upload something that is not an image/video to link it with the rich text editor&#8217;s filemanager in Prestashop, here is the solution. Watch the screencast</p>
<p>The post <a rel="nofollow" href="http://nemops.com/new-file-types-filemanager/">How to upload new file types with the Prestashop Filemanager</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>If you are struggling with ftp every time you need to upload something that is not an image/video to link it with the rich text editor&#8217;s filemanager in Prestashop, here is the solution.<br />
<span id="more-2537"></span></p>
<h2>Watch the screencast</h2>

	<div class="video-embed">
		<iframe width="640" height="360" src="http://www.youtube.com/embed/X5CUUA8bAtM" frameborder="0" allowfullscreen></iframe><p><a href="https://www.youtube.com/user/NemoPostScriptum/videos" rel="nofollow" title="Subscribe Post Scriptum's Youtube Channel">Subscribe Post Scriptum's Youtube Channel</a></p>	</div>
<p>The post <a rel="nofollow" href="http://nemops.com/new-file-types-filemanager/">How to upload new file types with the Prestashop Filemanager</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://nemops.com/new-file-types-filemanager/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to disable top notifications in the Prestashop back office</title>
		<link>http://nemops.com/disable-notifications-prestashop-back-office/</link>
		<comments>http://nemops.com/disable-notifications-prestashop-back-office/#comments</comments>
		<pubDate>Mon, 08 Jun 2015 10:06:10 +0000</pubDate>
		<dc:creator><![CDATA[Nemo]]></dc:creator>
				<category><![CDATA[Tips n Tricks]]></category>
		<category><![CDATA[back office]]></category>
		<category><![CDATA[notifications]]></category>
		<category><![CDATA[prestashop]]></category>

		<guid isPermaLink="false">http://nemops.com/?p=2441</guid>
		<description><![CDATA[<p>If your back office is hanging without apparent reason, it might be because of these notifications. Let&#8217;s get rid of them. Watch the Screencast Text version Open up classes/Notification.php, and locate the getLastElements method: Modify as follows This way, we are effectively saving lots of resources as we don&#8217;t query the database for new items.</p>
<p>The post <a rel="nofollow" href="http://nemops.com/disable-notifications-prestashop-back-office/">How to disable top notifications in the Prestashop back office</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>If your back office is hanging without apparent reason, it might be because of these notifications. Let&#8217;s get rid of them.<br />
<span id="more-2441"></span></p>
<h2>Watch the Screencast</h2>

	<div class="video-embed">
		<iframe width="640" height="360" src="http://www.youtube.com/embed/Rn0kNszfA9s" frameborder="0" allowfullscreen></iframe><p><a href="https://www.youtube.com/user/NemoPostScriptum/videos" rel="nofollow" title="Subscribe Post Scriptum's Youtube Channel">Subscribe Post Scriptum's Youtube Channel</a></p>	</div>
<h2>Text version</h2>
<p>Open up classes/Notification.php, and locate the getLastElements method:</p>
<pre class="brush: php; title: ; notranslate">
	public function getLastElements()
	{
		global $cookie;

		$notifications = array();

		$employee_infos = Db::getInstance(_PS_USE_SQL_SLAVE_)-&gt;getRow('
		SELECT id_last_order, id_last_customer_message, id_last_customer
		FROM `'._DB_PREFIX_.'employee`
		WHERE `id_employee` = '.(int)$cookie-&gt;id_employee);

		foreach ($this-&gt;types as $type)
			$notifications[$type] = Notification::getLastElementsIdsByType($type, $employee_infos['id_last_'.$type]);

		return $notifications;
	}
</pre>
<p>Modify as follows</p>
<pre class="brush: php; title: ; notranslate">
	public function getLastElements()
	{
		global $cookie;

		$notifications = array();

		foreach($this-&gt;types as $type)
			$notifications[$type] = array();

		return $notifications;

		$employee_infos = Db::getInstance(_PS_USE_SQL_SLAVE_)-&gt;getRow('
		SELECT id_last_order, id_last_customer_message, id_last_customer
		FROM `'._DB_PREFIX_.'employee`
		WHERE `id_employee` = '.(int)$cookie-&gt;id_employee);

		foreach ($this-&gt;types as $type)
			$notifications[$type] = Notification::getLastElementsIdsByType($type, $employee_infos['id_last_'.$type]);

		return $notifications;
	}
</pre>
<p>This way, we are effectively saving lots of resources as we don&#8217;t query the database for new items.</p>
<p>The post <a rel="nofollow" href="http://nemops.com/disable-notifications-prestashop-back-office/">How to disable top notifications in the Prestashop back office</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://nemops.com/disable-notifications-prestashop-back-office/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Faster Prestashop Back Office #1: removing modules and themes Ads</title>
		<link>http://nemops.com/faster-prestashop-back-office-modules-themes-ads/</link>
		<comments>http://nemops.com/faster-prestashop-back-office-modules-themes-ads/#comments</comments>
		<pubDate>Wed, 20 May 2015 09:52:20 +0000</pubDate>
		<dc:creator><![CDATA[Nemo]]></dc:creator>
				<category><![CDATA[Tips n Tricks]]></category>
		<category><![CDATA[back office]]></category>
		<category><![CDATA[modules]]></category>
		<category><![CDATA[prestashop]]></category>
		<category><![CDATA[speed]]></category>

		<guid isPermaLink="false">http://nemops.com/?p=2423</guid>
		<description><![CDATA[<p>In this quick video we will see how to improve our Prestashop back office&#8217;s speed a bit, by preventing our Shop to load anything out of prestashop.com Watch the Screencast</p>
<p>The post <a rel="nofollow" href="http://nemops.com/faster-prestashop-back-office-modules-themes-ads/">Faster Prestashop Back Office #1: removing modules and themes Ads</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>In this quick video we will see how to improve our Prestashop back office&#8217;s speed a bit, by preventing our Shop to load anything out of prestashop.com<br />
<span id="more-2423"></span></p>
<h2>Watch the Screencast</h2>

	<div class="video-embed">
		<iframe width="640" height="360" src="http://www.youtube.com/embed/0u8MQ2RHxnY" frameborder="0" allowfullscreen></iframe><p><a href="https://www.youtube.com/user/NemoPostScriptum/videos" rel="nofollow" title="Subscribe Post Scriptum's Youtube Channel">Subscribe Post Scriptum's Youtube Channel</a></p>	</div>
<p>The post <a rel="nofollow" href="http://nemops.com/faster-prestashop-back-office-modules-themes-ads/">Faster Prestashop Back Office #1: removing modules and themes Ads</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://nemops.com/faster-prestashop-back-office-modules-themes-ads/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Troubleshooting the spinning save button in Prestashop 1.6.0.11 and above</title>
		<link>http://nemops.com/spinning-save-button-prestashop-1-6/</link>
		<comments>http://nemops.com/spinning-save-button-prestashop-1-6/#comments</comments>
		<pubDate>Wed, 04 Feb 2015 10:39:04 +0000</pubDate>
		<dc:creator><![CDATA[Nemo]]></dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[back office]]></category>
		<category><![CDATA[prestashop]]></category>
		<category><![CDATA[products]]></category>
		<category><![CDATA[save]]></category>

		<guid isPermaLink="false">http://nemops.com/?p=2298</guid>
		<description><![CDATA[<p>It this article we will try to explain the reason behind the &#8220;spinning&#8221; save button on the product back office, that seems to be bothering merchants since Prestashop 1.6.0.11. Update: possible Fix on Git Here is a fix that came out recently, you can try replacing the red lines with green ones, or simply download [&#8230;]</p>
<p>The post <a rel="nofollow" href="http://nemops.com/spinning-save-button-prestashop-1-6/">Troubleshooting the spinning save button in Prestashop 1.6.0.11 and above</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>It this article we will try to explain the reason behind the &#8220;spinning&#8221; save button on the product back office, that seems to be bothering merchants since Prestashop 1.6.0.11.</p>
<p><span id="more-2298"></span></p>
<h2>Update: possible Fix on Git</h2>
<p>Here is a fix that came out recently, you can try replacing the red lines with green ones, or simply download the file and replace yours:</p>
<p>https://github.com/PrestaShop/PrestaShop/commit/5a0d4c90ff95332d8a03df84c5821c730a95087d</p>
<div class="separator"></div>
<h2>The issue: Save buttons on the Prestashop Product back office keep spinning (almost) forver</h2>
<p>Ever since the release of Prestashop 1.6.0.11, many users of the Prestashop forums have reported the same, big issue that seemed to be affecting all upgraded versions of the software. The fearsome glitch being an absolute catastrophe for merchants, since it made it impossible to save the product page in the back office. Thus, impossible to edit or add products whatsoever.<br />
Given that is one of the worst issues the Prestashop back office ever had, what is the cause of it? I fired an out-of-the-box 1.6.0.11 myself on my localhost and sought for a reasonable explanation: <strong>the save button keeps spinning until all tabs are loaded via ajax.</strong> This means that until all of them (Information, Prices, Combinations and so on) are fully loaded, it won&#8217;t be possible to even save the product. Let&#8217;s have a look at a screenshot to better understand what&#8217;s going on under the hood while the button is disabled:</p>
<p><a href="http://nemops.com/wp-content/uploads/2015/02/xhr_table.jpg"><img src="http://nemops.com/wp-content/uploads/2015/02/xhr_table-680x219.jpg" alt="Ajax calls in the prestashop 1.6 back office" width="680" height="219" class="aligncenter size-large wp-image-2309" /></a></p>
<p>Notice how many ajax calls to the same page are performed, with the last one still pending response. Each of them fetches the content of a tab, and it won&#8217;t ever be possible to save the page before everything has been loaded.</p>
<p>Unfortunately, the back office being slower and slower the more Prestashop versions are released, the waiting time might become unsustainable. It took 10 seconds on that localhost test, but it can grow up to one minute, or even more, on shared, medium quality hostings.</p>
<div class="separator"></div>
<h2>The reason behind it</h2>
<p>In the end, it all comes down to a question: why wasn&#8217;t this happening before? Simple: it was indeed possible to save before all tabs had been loaded, however this ended up spawning the well known &#8220;Product must be in the default category&#8221; or &#8220;link_rewrite field is required&#8221; errors, which were indeed caused by saving the product form without all the necessary fields having been filled with the required data yet. We can think of the spinning button as a measure to prevent this kind of error.</p>
<div class="separator"></div>
<h2>Troubleshooting the issue</h2>
<p>Given that it&#8217;s a matter of timing, let&#8217;s try to go over some possible fixes that came up in the constantly updating forum thread (<a href="https://www.prestashop.com/forums/topic/393218-16011-problem-with-saving-products/" title="Prestashop 1.6.0.11 problem with saving products">Prestashop 1.6.0.11 problem with saving products</a>).<br />
Make sure you also enable error reporting by <strong>setting PS_MODE_DEV to true in <em>config/defines.inc.php</em></strong> before even thinking of troubleshooting.</p>
<h3>Identifying the source</h3>
<p><a href="http://nemops.com/wp-content/uploads/2015/02/broken-ajax-calls.jpg"><img src="http://nemops.com/wp-content/uploads/2015/02/broken-ajax-calls-680x204.jpg" alt="Broken Ajax calls in the prestashop 1.6 back office" width="680" height="204" class="aligncenter size-large wp-image-2310" /></a><br />
There are three possible scenarios: a broken entry in the ajax requests queue, that will show up in red (see previous screenshot) in the list mentioned above; a forever pending request; lastly, a really slow request. It is important to understand which of these is preventing the button from being clickable, as the long-term fix will vary depending on it. Make sure you wait a couple of minutes and keep an eye on the following timing column as well:</p>
<p><a href="http://nemops.com/wp-content/uploads/2015/02/long_loading_times.jpg"><img src="http://nemops.com/wp-content/uploads/2015/02/long_loading_times.jpg" alt="Prestashop slow back office product page" width="460" height="333" class="aligncenter size-full wp-image-2315" /></a></p>
<p>Once we are relatively sure about the type of issue, how can we find out the source?</p>
<p>First, you can tell the tab name by the url:</p>
<pre class="brush: php; title: ; notranslate">
index.php?controller=AdminProducts&amp;token=aeaf41a133dadba136c21930b7caa933&amp;id_product=1&amp;action=Suppliers&amp;updateproduct&amp;ajax=1&amp;rand=1423043161452&amp;_=1423043155352
</pre>
<p>In this case, you can see action=Suppliers, so we&#8217;re dealing with the suppliers table. If it&#8217;s a module, it will be <strong>action=Module*ModuleName*</strong> without asterisks of course.</p>
<p>In the case of a red entry make sure you check out the ajax response by clicking on the broken url itself, it should give you more insights on what&#8217;s wrong with it.</p>
<h3>Case 1: Broken Module</h3>
<p>The most common source of the error is a broken module. Inspect the name as above, and if it really is a module go ahead and disable it; it should fix the big issue while you figure out the underlying cause.</p>
<h3>Case 2: broken product tab</h3>
<p>This is worse than the previous, as it can&#8217;t be solved by simply disabling a module. Once you are sure it really is a tab (see above), there are multiple things you can do. If it&#8217;s a red entry and the response is a Prestashop Exception or PHP error, follow the hints given by the error itself. Common issues might come from:</p>
<ul>
<li>A hard-modified AdminProductsController.php</li>
<li>AdminProductsController.php override</li>
<li>Broken/incompatible methods coming from other overrides</li>
</ul>
<p>If you didn&#8217;t modify the original controller, you can temporarily disable all overrides by reaching <em>Advanced Parameters > Performance</em> and setting <strong>Disable all overrides</strong> to yes.</p>
<p>If you are not using overrides, the issue might be coming, yet again, from a module. Reach <strong>Modules > Positions</strong>, check &#8220;Display non-positionable hooks&#8221;, and then look for modules hooked to one of the following:</p>
<ul>
<li>actionAdminControllerSetMedia</li>
<li>displayBackOfficeHeader</li>
<li>actionProductUpdate</li>
<li>actionProductAdd</li>
<li>actionCategoryUpdate</li>
</ul>
<div class="separator"></div>
<h2>Wrapping it up</h2>
<p>This post was not meant to give you a 100% reliable solution, since it&#8217;s impossible to predict every single scenario. Still, I hope it pointed you to the right direction in case you were facing the never-ending spinning save button issue in Prestashop 1.6.0.11 and newer.</p>
<p>The post <a rel="nofollow" href="http://nemops.com/spinning-save-button-prestashop-1-6/">Troubleshooting the spinning save button in Prestashop 1.6.0.11 and above</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://nemops.com/spinning-save-button-prestashop-1-6/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>Adding new tabs and fields to Prestashop products&#8217; back office</title>
		<link>http://nemops.com/prestashop-products-new-tabs-fields/</link>
		<comments>http://nemops.com/prestashop-products-new-tabs-fields/#comments</comments>
		<pubDate>Wed, 11 Sep 2013 14:02:38 +0000</pubDate>
		<dc:creator><![CDATA[Nemo]]></dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[back office]]></category>
		<category><![CDATA[prestashop]]></category>
		<category><![CDATA[products]]></category>
		<category><![CDATA[tabs]]></category>

		<guid isPermaLink="false">http://nemops.com/?p=1537</guid>
		<description><![CDATA[<p>It is easy enough to modify Prestashop’s products&#8217; back office and add new fields by editing the AdminProductsController. However, by using a module and a new tab, it becomes much more maintainable! Prestashop back office hooks Although we will go through the basics of setting up a module, this tutorial assumes you already know how [&#8230;]</p>
<p>The post <a rel="nofollow" href="http://nemops.com/prestashop-products-new-tabs-fields/">Adding new tabs and fields to Prestashop products&#8217; back office</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>It is easy enough to modify Prestashop’s products&#8217; back office and add new fields by editing the AdminProductsController. However, by using a module and a new tab, it becomes much more maintainable!</p>
<p><span id="more-1537"></span></p>
<a class="download-files button style1" href="http://nemops.com/wp-content/uploads/2013/09/Adding_new_fields_nemops.zip" title="Download Project Files">Download Project Files</a>
<h2>Prestashop back office hooks</h2>
<p>Although we will go through the basics of setting up a module, this tutorial assumes you already know how to create one from scratch. If you are totally new to Prestashop, I strongly recommend that you read the <a href="http://doc.prestashop.com/display/PS15/Creating+a+PrestaShop+module" title="How to create a Prestashop Module" target="_blank">Official documentation on how to create a Prestashop Module</a> before approaching this tutorial.</p>
<p>Now, in order to add new fields to Prestashop&#8217;s products&#8217; back office, it is essential to be aware of the hooks that can be used to perform various operations in the admin panel. Specifically, we will be using the following ones:</p>
<p><strong>DisplayAdminProductsExtra</strong>: this hook adds new tabs to the product&#8217;s back office interface, thus, we will use this hook to plug in our new content&#8217;s input field with translations</p>
<p><strong>ActionAdminControllerSetMedia</strong>: if we ever need to style our new tab, or add custom javascript functions, this is the ideal hook to use to plug css and js files. This is called for every Prestashop Admin page, thus we will need to prevent it from running in pages that are not the product&#8217;s configuration.</p>
<p><strong>ActionProductUpdate</strong>: the new field needs to be saved in the database. Specifically, we will add a new column (custom_field) to the product_lang table and add a new translatable field, without using overrides at all. By plugging code snippets into this hook, we can easily update the column when the product itself is updated.</p>
<p>At this point, we can line out our plan of action: after giving the module a basic setup, we will first create the template file that will display the new field&#8217;s input box on its own table. Then, we will see how to overcome a little issue with translatable fields, using the <strong>ActionAdminControllerSetMedia</strong> hook, and lastly, on data submission, we will update the new custom field once the product is updated. We will create a new field for demonstrational purposes only, but feel free to dare beyond the limits of this tutorial if you want!</p>
<div class="separator"></div>
<h2>Setting up the module</h2>
<p>First of all, let&#8217;s start with a simple module template. You can download the blank module folder from the link at the beginning of the article. Drop the newfieldstut folder (the one from the &#8220;Start here&#8221; archive!) in the <em>modules/</em> folder of your Prestashop Root. Then open up <strong>newfieldstut.php</strong> and start by adding some regular module&#8217;s code.</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php

if (!defined('_PS_VERSION_'))
	exit;

class newFieldsTut extends Module
{
	/* @var boolean error */
	protected $_errors = false;
	
	public function __construct()
	{
		$this-&gt;name = 'newfieldstut';
		$this-&gt;tab = 'front_office_features';
		$this-&gt;version = '1.0';
		$this-&gt;author = 'Nemo';
		$this-&gt;need_instance = 0;

	 	parent::__construct();

		$this-&gt;displayName = $this-&gt;l('New Fields Tutorial');
		$this-&gt;description = $this-&gt;l('Test module from Nemo\'s Post Scriptum Tutorial (nemops.com).');
	}
		
}
?&gt;
</pre>
<p>Now that the basic structure is laid out, we want to specify the install and uninstall functions. Let&#8217;s add a new column to product_lang with an ALTER TABLE, and provide a way to remove it if this module is uninstalled:</p>
<pre class="brush: php; title: ; notranslate">

	public function install()
	{
		if (!parent::install() OR
			!$this-&gt;alterTable('add') OR			
			!$this-&gt;registerHook('actionAdminControllerSetMedia') OR
			!$this-&gt;registerHook('actionProductUpdate') OR
			!$this-&gt;registerHook('displayAdminProductsExtra'))
			return false;
		return true;
	}
	
	public function uninstall()
	{
		if (!parent::uninstall() OR !$this-&gt;alterTable('remove'))
			return false;
		return true;
	}


	public function alterTable($method)
	{
		switch ($method) {
			case 'add':
				$sql = 'ALTER TABLE ' . _DB_PREFIX_ . 'product_lang ADD `custom_field` TEXT NOT NULL';
				break;
			
			case 'remove':
				$sql = 'ALTER TABLE ' . _DB_PREFIX_ . 'product_lang DROP COLUMN `custom_field`';
				break;
		}
		
		if(!Db::getInstance()-&gt;Execute($sql))
			return false;
		return true;
	}
</pre>
<p><strong>Explanation:</strong> A couple of things here! First, in the <strong>install</strong> method, we</p>
<ul>
<li>1- As with every module, call the parent&#8217;s install method</li>
<li>2- Alter the product_lang table, to add the new field</li>
<li>3- Register all the hooks we will use</li>
</ul>
<p>Notice how I decided to structure the <strong>alterTable</strong> method. To avoid creating two functions, I stacked together the drop and add statements, passing a <strong>$method</strong> variable to determine what the function should do. Therefore, we call alterTable with &#8216;add&#8217; when installing, and &#8216;remove&#8217; when uninstalling.</p>
<p>Now, just to be sure we did everything correctly without errors, let&#8217;s try installing the module! Reach the <strong>Modules</strong> page in the back office and look for <strong>New Fields Tutorial</strong> in the modules list, as shown below.</p>
<p><img src="http://nemops.com/wp-content/uploads/2013/09/new_fields_module-680x254.png" alt="Our module in the Prestashop modules list" width="680" height="254" class="alignnone size-large wp-image-1552" /></p>
<p>Click install, and see if it works. If it does, move on to the next step!</p>
<div class="separator"></div>
<h2>Creating a new tab in the Product Back Office (DisplayAdminProductsExtra)</h2>
<p>Okay, our module is installed, and the hooks have been registered as well. Time to test it out! Add the following function to your module:</p>
<pre class="brush: php; title: ; notranslate">
	public function hookDisplayAdminProductsExtra($params)
	{
		if (Validate::isLoadedObject($product = new Product((int)Tools::getValue('id_product'))))
		{

			return $this-&gt;display(__FILE__, 'newfieldstut.tpl');
		}
	}	
</pre>
<p><strong>Explanation:</strong> first, we make sure the current product object is correctly loaded; if so we display the content of the module&#8217;s tpl file. Reach a product&#8217;s back office page; you should see something like this, by clicking on the new tab:</p>
<p><img src="http://nemops.com/wp-content/uploads/2013/09/productbo_start.png" alt="New tab to Prestashop Products&#039; back office" width="593" height="600" class="alignnone size-full wp-image-1553" /></p>
<p>At this point, we can start filling in the tpl file. Open up <strong>newfieldstut.tpl</strong>, get rid of the placeholder text and add the following instead:</p>
<pre class="brush: php; html-script: true; title: ; notranslate">

&lt;h4&gt;{l s='New Fields Tutorial' mod='newfieldstut'}&lt;/h4&gt;
&lt;div class=&quot;separation&quot;&gt;&lt;/div&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td class=&quot;col-left&quot;&gt;
			&lt;label&gt;{l s='Our New Field:'}&lt;/label&gt;
		&lt;/td&gt;
		&lt;td&gt;
			{include file=&quot;controllers/products/input_text_lang.tpl&quot;
				languages=$languages
				input_name='custom_field'
				input_value=$custom_field}
			&lt;p class=&quot;preference_description&quot;&gt;{l s='Simply a new custom field'}. &lt;strong&gt;{l s='ie: something here as a hint'}&lt;/strong&gt;&lt;/p&gt;
		&lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
</pre>
<p>Do not test this out yet! It will not work. Why? Let&#8217;s have a look at what we just did: first, we setup a simple table structure imitating the one Prestashop uses by default in the Product configuration page. Then, inside the rightmost table cell (td), we include a template file Prestashop kindly provides. This file is <strong>input_text_lang.tpl</strong>, and it is located in the admin theme folder, inside the controller section for products. What it does, is it provides a standardized way to add new translatable fields without having to mess with foreach loops in our own code. We can assign the currently available languages, name of the new input field and its value.</p>
<p>However, if we were to refresh the page now, and turn on error reporting, this is what we would see:</p>
<p><img src="http://nemops.com/wp-content/uploads/2013/09/product_bo_error-680x667.png" alt="Error before adding variables to the hook" width="680" height="667" class="alignnone size-large wp-image-1554" /></p>
<p>This happens because we have not assigned any of those 2 variables we mention in the code: <strong>$languages</strong> and <strong>$custom_field</strong>. Let&#8217;s take care of this.</p>
<p>Back to <strong>newfieldstut.php</strong>, create a new method as follows:</p>
<pre class="brush: php; title: ; notranslate">

	public function prepareNewTab()
	{

		$this-&gt;context-&gt;smarty-&gt;assign(array(
			'custom_field' =&gt; '',
			'languages' =&gt; $this-&gt;context-&gt;controller-&gt;_languages,
			'default_language' =&gt; (int)Configuration::get('PS_LANG_DEFAULT')
		));

	}

</pre>
<p>For the time being, we will not bother adding a real value to the new field. As for the other 2 variables, we get the currently available languages by the controller itself, and the default language for our store.</p>
<p>At this point, amend <strong>hookDisplayAdminProductsExtra</strong> as follows:</p>
<pre class="brush: php; title: ; notranslate">
	public function hookDisplayAdminProductsExtra($params)
	{
		if (Validate::isLoadedObject($product = new Product((int)Tools::getValue('id_product'))))
		{
			$this-&gt;prepareNewTab();
			return $this-&gt;display(__FILE__, 'newfieldstut.tpl');
		}
	}	
</pre>
<p>The new tab is ready! &#8230;.BUT! Hey, watch closely at what happens if you wait a couple of seconds before accessing it, or click its label right after the page reloads!</p>
<p>The language flags pops out after a while, or <strong>does not appear at all!</strong></p>
<p>This is (I believe) yet another Prestashop bug. If we want our new translatable field to work correctly every time, we absolutely need to take this bug off. How to?</p>
<div class="separator"></div>
<h2>Properly enabling multilanguage fields in the product Back Office</h2>
<p>What on earth is going on here? Basically, Prestashop loads the language translations flags using javascript. Not only this, but it also loads each tab asynchronously with Ajax, and &#8216;forgets&#8217; to call the function which assigns those flags for custom tabs. This is where the <strong>ActionAdminControllerSetMedia</strong> hook becomes useful! We will plug in a new javascript file to take it into account, so that flags are assigned to our new tab as well.</p>
<p>First off, open up <strong>newfieldstut.js</strong>, which you can find in the project&#8217;s module folder you already know. Here is how it will look:</p>
<pre class="brush: jscript; title: ; notranslate">
$(document).ready(function() {

});
</pre>
<p>Nothing but a simple jQuery ready statement. Inside, add the following</p>
<pre class="brush: jscript; title: ; notranslate">

	$(&quot;#product-tab-content-ModuleNewfieldstut&quot;).on('loaded', function(){
			displayFlags(languages, id_language, allowEmployeeFormLang);
	})

</pre>
<p>And that&#8217;s it, really. A few notes though: Notice the ID we are checking the <strong>load</strong> status for. This will vary depending on the name you give your module, and you can check it by inspecting the tab element with the browser&#8217;s developer tools:</p>
<p><img src="http://nemops.com/wp-content/uploads/2013/09/inpect_element-680x269.jpg" alt="Inspecting the Product tab id in the back office" width="680" height="269" class="alignnone size-large wp-image-1555" /></p>
<p>Just bear in mind you have to point the right ID, nothing else.</p>
<p>Now, back to <strong>newfieldstut.php</strong> once more. Add the following method:</p>
<pre class="brush: php; title: ; notranslate">
	public function hookActionAdminControllerSetMedia($params)
	{

		// add necessary javascript to products back office
		if($this-&gt;context-&gt;controller-&gt;controller_name == 'AdminProducts' &amp;&amp; Tools::getValue('id_product'))
		{
			$this-&gt;context-&gt;controller-&gt;addJS($this-&gt;_path.'/js/newfieldstut.js');
		}

	}
</pre>
<p><strong>Explanation:</strong> As we saw at the beginning of the article, this hook runs for every page of the back office. Thus, we need to be sure we are embedding our javascript for the single product configuration page only. Therefore, we first check the the current controller is <strong>AdminProducts</strong>, then, to be sure we are not viewing the products list, we also make sure a product id is set in the current url. After performing these checks, we simply use a regular addJS to embed the code.</p>
<p>Save &#038; refresh, at this point the language flags are always added to the new tab!</p>
<div class="separator"></div>
<h2>Saving and retrieving the new value</h2>
<p>Everything is in place, but we are not doing anything now. We are not displaying the new field value, nor are we able to save its content!</p>
<p>First off, let&#8217;s save the value for each language inside the database. Append the following method to our beloved <strong>newfieldstut.php</strong>:</p>
<pre class="brush: php; title: ; notranslate">

	public function hookActionProductUpdate($params)
	{
		// get all languages
		// for each of them, store the new field

		$id_product = (int)Tools::getValue('id_product');

		$languages = Language::getLanguages(true);
		foreach ($languages as $lang) {
			if(!Db::getInstance()-&gt;update('product_lang', array('custom_field'=&gt; pSQL(Tools::getValue('custom_field_'.$lang['id_lang']))) ,'id_lang = ' . $lang['id_lang'] .' AND id_product = ' .$id_product ))
				$this-&gt;context-&gt;controller-&gt;_errors[] = Tools::displayError('Error: ').mysql_error();
		}

	}

</pre>
<p><strong>Explanation:</strong> the hook we are targeting here(<strong>ActionProductUpdate</strong>) runs at the very same time a product&#8217;s data is stored inside the database. The perfect time to add our new content! First, we retrieve the current product ID, and then get all the currently active languages. For each of the languages, we update the database field for the matching language and product id. If the update operation cannot be completed, we spawn an error using the default Prestashop error handler for Admin tabs.</p>
<p>A small note on <strong>Tools::getValue(&#8216;custom_field_&#8217;.$lang[&#8216;id_lang&#8217;])</strong>: if you remember, we called our new field &#8216;custom_field&#8217; when embedding the translatable input box. This means Prestashop generates one field, appending each language id, for each language. Thus, we end up having custom_field_1, custom_field_2 etc&#8230; Where the number after the second underscore represents the language ID. That&#8217;s why we are targeting it like this &#8216;custom_field_&#8217;.$lang[&#8216;id_lang&#8217;], to be sure each language is correctly added.</p>
<p>Now, let&#8217;s try inputting different values for each languages, and hit &#8216;Save and stay&#8217;. Then, since we are not yet retrieving the field, let&#8217;s check it out in the database.</p>
<p><img src="http://nemops.com/wp-content/uploads/2013/09/database_entries.jpg" alt="Our custom fields in the Prestashop Database" width="501" height="341" class="alignnone size-full wp-image-1556" /></p>
<p>Okay, it&#8217;s done! At this point, we only need to retrieve those values! Let&#8217;s add a new method to our friend <strong>newfieldstut.php</strong>:</p>
<pre class="brush: php; title: ; notranslate">

	public function getCustomField($id_product)
	{
		$result = Db::getInstance()-&gt;ExecuteS('SELECT custom_field, id_lang FROM '._DB_PREFIX_.'product_lang WHERE id_product = ' . (int)$id_product);
		if(!$result)
			return array();

		foreach ($result as $field) {
			$fields[$field['id_lang']] = $field['custom_field'];
		}

		return $fields;
	}

</pre>
<p><strong>Explanation:</strong> Quite simply, using the product id as source data, we retrieve all entries for the <strong>custom_field</strong> column. Then, we format it for an array whose keys are language ids, and values the custom field value for that specific language. This is how Prestashop will be able to use them in the template: array(&#8216;5&#8242; => &#8216;value for id_lang 5), &#8230;&#8217;).</p>
<p>Of course, as a last step we call this function when assigning variables in <strong>prepareNewTab</strong>:</p>
<pre class="brush: php; title: ; notranslate">

	public function prepareNewTab()
	{

		$this-&gt;context-&gt;smarty-&gt;assign(array(
			'custom_field' =&gt; $this-&gt;getCustomField((int)Tools::getValue('id_product')),
			'languages' =&gt; $this-&gt;context-&gt;controller-&gt;_languages,
			'default_language' =&gt; (int)Configuration::get('PS_LANG_DEFAULT')
		));

	}

</pre>
<p>And we are finished!</p>
<p><img src="http://nemops.com/wp-content/uploads/2013/09/completed-680x488.png" alt="The new custom field added to Prestashop Products&#039; back office" width="680" height="488" class="alignnone size-large wp-image-1558" /></p>
<div class="separator"></div>
<h2>Conclusion</h2>
<p>As you could see, adding new fields to products using modules, without any remote sign of overrides, is not as complex as it might seem. Moreover, it&#8217;s a much more maintainable practice than messing with the original back office templates and controllers! Of course, at this point, you can take this tutorial further and add front office hooks to display your new, translatable field!</p>
<div class="separator">&nbsp;</div>
<h3>Additional Resources</h3>
<ul>
<li><a target="_blank" href="http://doc.prestashop.com/display/PS15/Creating+a+PrestaShop+module" title="How to create a Prestashop Module">Official documentation on how to create a Prestashop Module</a></li>
</ul>
<p>The post <a rel="nofollow" href="http://nemops.com/prestashop-products-new-tabs-fields/">Adding new tabs and fields to Prestashop products&#8217; back office</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://nemops.com/prestashop-products-new-tabs-fields/feed/</wfw:commentRss>
		<slash:comments>77</slash:comments>
		</item>
	</channel>
</rss>
