<?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; image</title>
	<atom:link href="https://nemops.com/tag/image/feed/" rel="self" type="application/rss+xml" />
	<link>https://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>Adding a second image for Prestashop categories</title>
		<link>https://nemops.com/prestashop-categories-second-image/</link>
		<comments>https://nemops.com/prestashop-categories-second-image/#comments</comments>
		<pubDate>Wed, 29 Oct 2014 10:55:26 +0000</pubDate>
		<dc:creator><![CDATA[Nemo]]></dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[category]]></category>
		<category><![CDATA[image]]></category>
		<category><![CDATA[prestashop]]></category>

		<guid isPermaLink="false">http://nemops.com/?p=2185</guid>
		<description><![CDATA[<p>Prestashop only allows using one image as category thumbnail by default, thus creating issues in having different formats for subcategory images in the product list view. In this tutorial we will add a secondary image to prestashop categories, to increase flexibility on thumbs display when showing them as subcategories. Prestashop version: any 1.6 (used: 1.6.0.9, [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://nemops.com/prestashop-categories-second-image/">Adding a second image for Prestashop categories</a> appeared first on <a rel="nofollow" href="https://nemops.com">NemoPS</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>Prestashop only allows using one image as category thumbnail by default, thus creating issues in having different formats for subcategory images in the product list view. In this tutorial we will add a secondary image to prestashop categories, to increase flexibility on thumbs display when showing them as subcategories.</p>
<p><span id="more-2185"></span></p>
<ul>
<li>Prestashop version: any 1.6 (used: 1.6.0.9, should equally apply to 1.5, though not tested)</li>
</ul>
<a class="download-files button style1" href="http://nemops.com/wp-content/uploads/2014/10/second_image_for_categories.zip" title="Download Project Files">Download Project Files</a>
<h2>Introduction</h2>
<p>Before starting, it&#8217;s worth noticing this tutorial implies quite a lot of modifications and overrides, and it&#8217;s therefore recommended that you have a solid knowledge of php before doing anything. As always, refer to the <a href="http://doc.prestashop.com/display/PS15/Overriding+default+behaviors" title="Official Prestashop documentation on Overrides">Official Prestashop documentation on Overrides</a> if you are new to the subject. That said, these are the files we need to override/modify:</p>
<ul>
<li>AdminCategoriesController.php: here is where most of the magic will occur, to upload and delete the new image</li>
<li>Category.php: the category class, as we have to implement the new field and image file deletion</li>
<li>category.tpl: to display the new image for subcategories</li>
<li>.htaccess: only needed if you use Friendly urls, otherwise no image will be shown</li>
</ul>
<div class="separator"></div>
<h2>Extending the AdminCategoriesController file</h2>
<p>The categories&#8217; admin controller is the file we will be mostly dealing with. Although we could modify it directly, it&#8217;s always best practice to use an override. Therefore, create a new file in <em>/override/controllers/admin</em> named <strong>AdminCategoriesController.php</strong>, and paste the following inside php tags:</p>
<pre class="brush: php; title: ; notranslate">
class AdminCategoriesController extends AdminCategoriesControllerCore
{
}
</pre>
<p>Then, reach the original <strong>AdminCategoriesController</strong> located within <em>/controllers/admin</em>, open it, locate and copy <strong>the whole renderForm method</strong>. Then, paste it inside the new override:</p>
<pre class="brush: php; title: ; notranslate">


class AdminCategoriesController extends AdminCategoriesControllerCore
{


	public function renderForm()
	{
		$this-&gt;initToolbar();
		$obj = $this-&gt;loadObject(true);
		$id_shop = Context::getContext()-&gt;shop-&gt;id;
		$selected_categories = array((isset($obj-&gt;id_parent) &amp;&amp; $obj-&gt;isParentCategoryAvailable($id_shop))? (int)$obj-&gt;id_parent : (int)Tools::getValue('id_parent', Category::getRootCategory()-&gt;id));
		$unidentified = new Group(Configuration::get('PS_UNIDENTIFIED_GROUP'));
		$guest = new Group(Configuration::get('PS_GUEST_GROUP'));
		$default = new Group(Configuration::get('PS_CUSTOMER_GROUP'));

		$unidentified_group_information = sprintf($this-&gt;l('%s - All people without a valid customer account.'), '&lt;b&gt;'.$unidentified-&gt;name[$this-&gt;context-&gt;language-&gt;id].'&lt;/b&gt;');
		$guest_group_information = sprintf($this-&gt;l('%s - Customer who placed an order with the guest checkout.'), '&lt;b&gt;'.$guest-&gt;name[$this-&gt;context-&gt;language-&gt;id].'&lt;/b&gt;');
		$default_group_information = sprintf($this-&gt;l('%s - All people who have created an account on this site.'), '&lt;b&gt;'.$default-&gt;name[$this-&gt;context-&gt;language-&gt;id].'&lt;/b&gt;');

		if (!($obj = $this-&gt;loadObject(true)))
			return;

		$image = _PS_CAT_IMG_DIR_.$obj-&gt;id.'.jpg';
		$image_url = ImageManager::thumbnail($image, $this-&gt;table.'_'.(int)$obj-&gt;id.'.'.$this-&gt;imageType, 350,
			$this-&gt;imageType, true, true);
		$image_size = file_exists($image) ? filesize($image) / 1000 : false;

		$this-&gt;fields_form = array(
			'tinymce' =&gt; true,
			'legend' =&gt; array(
				'title' =&gt; $this-&gt;l('Category'),
				'icon' =&gt; 'icon-tags'
			),
			'input' =&gt; array(
				array(
					'type' =&gt; 'text',
					'label' =&gt; $this-&gt;l('Name'),
					'name' =&gt; 'name',
					'lang' =&gt; true,
					'required' =&gt; true,
					'class' =&gt; 'copy2friendlyUrl',
					'hint' =&gt; $this-&gt;l('Invalid characters:').' &lt;&gt;;=#{}',
				),
				array(
					'type' =&gt; 'switch',
					'label' =&gt; $this-&gt;l('Displayed'),
					'name' =&gt; 'active',
					'required' =&gt; false,
					'is_bool' =&gt; true,
					'values' =&gt; array(
						array(
							'id' =&gt; 'active_on',
							'value' =&gt; 1,
							'label' =&gt; $this-&gt;l('Enabled')
						),
						array(
							'id' =&gt; 'active_off',
							'value' =&gt; 0,
							'label' =&gt; $this-&gt;l('Disabled')
						)
					)
				),
				array(
					'type'  =&gt; 'categories',
					'label' =&gt; $this-&gt;l('Parent category'),
					'name'  =&gt; 'id_parent',
					'tree'  =&gt; array(
						'id'                  =&gt; 'categories-tree',
						'selected_categories' =&gt; $selected_categories,
						'disabled_categories' =&gt; !Tools::isSubmit('add'.$this-&gt;table) ? array($this-&gt;_category-&gt;id) : null
					)
				),
				array(
					'type' =&gt; 'textarea',
					'label' =&gt; $this-&gt;l('Description'),
					'name' =&gt; 'description',
					'autoload_rte' =&gt; true,
					'lang' =&gt; true,
					'hint' =&gt; $this-&gt;l('Invalid characters:').' &lt;&gt;;=#{}'
				),
				array(
					'type' =&gt; 'file',
					'label' =&gt; $this-&gt;l('Image'),
					'name' =&gt; 'image',
					'display_image' =&gt; true,
					'image' =&gt; $image_url ? $image_url : false,
					'size' =&gt; $image_size,
					'delete_url' =&gt; self::$currentIndex.'&amp;'.$this-&gt;identifier.'='.$this-&gt;_category-&gt;id.'&amp;token='.$this-&gt;token.'&amp;deleteImage=1',
					'hint' =&gt; $this-&gt;l('Upload a category logo from your computer.'),
				),
				array(
					'type' =&gt; 'text',
					'label' =&gt; $this-&gt;l('Meta title'),
					'name' =&gt; 'meta_title',
					'lang' =&gt; true,
					'hint' =&gt; $this-&gt;l('Forbidden characters:').' &lt;&gt;;=#{}'
				),
				array(
					'type' =&gt; 'text',
					'label' =&gt; $this-&gt;l('Meta description'),
					'name' =&gt; 'meta_description',
					'lang' =&gt; true,
					'hint' =&gt; $this-&gt;l('Forbidden characters:').' &lt;&gt;;=#{}'
				),
				array(
					'type' =&gt; 'tags',
					'label' =&gt; $this-&gt;l('Meta keywords'),
					'name' =&gt; 'meta_keywords',
					'lang' =&gt; true,
					'hint' =&gt; $this-&gt;l('To add &quot;tags,&quot; click in the field, write something, and then press &quot;Enter.&quot;').'&amp;nbsp;'.$this-&gt;l('Forbidden characters:').' &lt;&gt;;=#{}'
				),
				array(
					'type' =&gt; 'text',
					'label' =&gt; $this-&gt;l('Friendly URL'),
					'name' =&gt; 'link_rewrite',
					'lang' =&gt; true,
					'required' =&gt; true,
					'hint' =&gt; $this-&gt;l('Only letters, numbers, underscore (_) and the minus (-) character are allowed.')
				),
				array(
					'type' =&gt; 'group',
					'label' =&gt; $this-&gt;l('Group access'),
					'name' =&gt; 'groupBox',
					'values' =&gt; Group::getGroups(Context::getContext()-&gt;language-&gt;id),
					'info_introduction' =&gt; $this-&gt;l('You now have three default customer groups.'),
					'unidentified' =&gt; $unidentified_group_information,
					'guest' =&gt; $guest_group_information,
					'customer' =&gt; $default_group_information,
					'hint' =&gt; $this-&gt;l('Mark all of the customer groups which you would like to have access to this category.')
				)
			),
			'submit' =&gt; array(
				'title' =&gt; $this-&gt;l('Save'),
				'name' =&gt; 'submitAdd'.$this-&gt;table.($this-&gt;_category-&gt;is_root_category &amp;&amp; !Tools::isSubmit('add'.$this-&gt;table) &amp;&amp; !Tools::isSubmit('add'.$this-&gt;table.'root') ? '': 'AndBackToParent')
			)
		);

		$this-&gt;tpl_form_vars['shared_category'] = Validate::isLoadedObject($obj) &amp;&amp; $obj-&gt;hasMultishopEntries();
		$this-&gt;tpl_form_vars['PS_ALLOW_ACCENTED_CHARS_URL'] = (int)Configuration::get('PS_ALLOW_ACCENTED_CHARS_URL');
		$this-&gt;tpl_form_vars['displayBackOfficeCategory'] = Hook::exec('displayBackOfficeCategory');

		// Display this field only if multistore option is enabled
		if (Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE') &amp;&amp; Tools::isSubmit('add'.$this-&gt;table.'root'))
		{
			$this-&gt;fields_form['input'][] = array(
				'type' =&gt; 'switch',
				'label' =&gt; $this-&gt;l('Root Category'),
				'name' =&gt; 'is_root_category',
				'required' =&gt; false,
				'is_bool' =&gt; true,
				'values' =&gt; array(
					array(
						'id' =&gt; 'is_root_on',
						'value' =&gt; 1,
						'label' =&gt; $this-&gt;l('Yes')
					),
					array(
						'id' =&gt; 'is_root_off',
						'value' =&gt; 0,
						'label' =&gt; $this-&gt;l('No')
					)
				)
			);
			unset($this-&gt;fields_form['input'][2],$this-&gt;fields_form['input'][3]);
		}
		// Display this field only if multistore option is enabled AND there are several stores configured
		if (Shop::isFeatureActive())
			$this-&gt;fields_form['input'][] = array(
				'type' =&gt; 'shop',
				'label' =&gt; $this-&gt;l('Shop association'),
				'name' =&gt; 'checkBoxShopAsso',
			);

		// remove category tree and radio button &quot;is_root_category&quot; if this category has the root category as parent category to avoid any conflict
		if ($this-&gt;_category-&gt;id_parent == Category::getTopCategory()-&gt;id &amp;&amp; Tools::isSubmit('updatecategory'))
			foreach ($this-&gt;fields_form['input'] as $k =&gt; $input)
				if (in_array($input['name'], array('id_parent', 'is_root_category')))
					unset($this-&gt;fields_form['input'][$k]);

		if (!($obj = $this-&gt;loadObject(true)))
			return;

		$image = ImageManager::thumbnail(_PS_CAT_IMG_DIR_.'/'.$obj-&gt;id.'.jpg', $this-&gt;table.'_'.(int)$obj-&gt;id.'.'.$this-&gt;imageType, 350, $this-&gt;imageType, true);

		$this-&gt;fields_value = array(
			'image' =&gt; $image ? $image : false,
			'size' =&gt; $image ? filesize(_PS_CAT_IMG_DIR_.'/'.$obj-&gt;id.'.jpg') / 1000 : false
		);

		// Added values of object Group
		$category_groups_ids = $obj-&gt;getGroups();

		$groups = Group::getGroups($this-&gt;context-&gt;language-&gt;id);
		// if empty $carrier_groups_ids : object creation : we set the default groups
		if (empty($category_groups_ids))
		{
			$preselected = array(Configuration::get('PS_UNIDENTIFIED_GROUP'), Configuration::get('PS_GUEST_GROUP'), Configuration::get('PS_CUSTOMER_GROUP'));
			$category_groups_ids = array_merge($category_groups_ids, $preselected);
		}
		foreach ($groups as $group)
			$this-&gt;fields_value['groupBox_'.$group['id_group']] = Tools::getValue('groupBox_'.$group['id_group'], (in_array($group['id_group'], $category_groups_ids)));

		$this-&gt;fields_value['is_root_category'] = (bool)Tools::isSubmit('add'.$this-&gt;table.'root');

		return parent::renderForm();
	}
	
}
</pre>
<p>Notice the last row, <strong>return parent::renderForm();</strong>. Change it to <strong>return AdminController::renderForm();</strong>. if we didn&#8217;t take this counter-measure, all of our changes would have been overridden by the original controller. To make sure the override works, reach the <em>cache/</em> and erase <strong>class_index.php</strong> to enable the new file. Then login to the back office, and check the single category view works as expected. If so, read on.</p>
<h3>Adding the new field</h3>
<p>First off, we will need to add the code that displays any eventual image we upload. To do so, locate the following:</p>
<pre class="brush: php; title: ; notranslate">
		$image = _PS_CAT_IMG_DIR_.$obj-&gt;id.'.jpg';
		$image_url = ImageManager::thumbnail($image, $this-&gt;table.'_'.(int)$obj-&gt;id.'.'.$this-&gt;imageType, 350,
			$this-&gt;imageType, true, true);
		$image_size = file_exists($image) ? filesize($image) / 1000 : false;
</pre>
<p>Right after it, add</p>
<pre class="brush: php; title: ; notranslate">
		$image2 = _PS_CAT_IMG_DIR_.$obj-&gt;id.'_second.jpg';
		$image_url2 = ImageManager::thumbnail($image2, $this-&gt;table.'_'.(int)$obj-&gt;id.'_second.'.$this-&gt;imageType, 350,
			$this-&gt;imageType, true, true);
		$image_size2 = file_exists($image2) ? filesize($image2) / 1000 : false;
</pre>
<p>Which is basically the same with modified names. Next, right below we have the fields list. We need to add our file input here, so that we can later upload the image. Therefore, locate:</p>
<pre class="brush: php; title: ; notranslate">
				array(
					'type' =&gt; 'file',
					'label' =&gt; $this-&gt;l('Image'),
					'name' =&gt; 'image',
					'display_image' =&gt; true,
					'image' =&gt; $image_url ? $image_url : false,
					'size' =&gt; $image_size,
					'delete_url' =&gt; self::$currentIndex.'&amp;'.$this-&gt;identifier.'='.$this-&gt;_category-&gt;id.'&amp;token='.$this-&gt;token.'&amp;deleteImage=1',
					'hint' =&gt; $this-&gt;l('Upload a category logo from your computer.'),
				),
</pre>
<p>And add the following right after it</p>
<pre class="brush: php; title: ; notranslate">
				array(
					'type' =&gt; 'file',
					'label' =&gt; $this-&gt;l('Image2'),
					'name' =&gt; 'image2',
					'display_image' =&gt; true,
					'image' =&gt; $image_url2 ? $image_url2 : false,
					'size' =&gt; $image_size2,
					'delete_url' =&gt; self::$currentIndex.'&amp;'.$this-&gt;identifier.'='.$this-&gt;_category-&gt;id.'&amp;token='.$this-&gt;token.'&amp;deleteImage2=1',
					'hint' =&gt; $this-&gt;l('Upload a secondary category logo from your computer.'),
				),
</pre>
<p>Once again, same code, different names. And, lastly, change this:</p>
<pre class="brush: php; title: ; notranslate">
		$image = ImageManager::thumbnail(_PS_CAT_IMG_DIR_.'/'.$obj-&gt;id.'.jpg', $this-&gt;table.'_'.(int)$obj-&gt;id.'.'.$this-&gt;imageType, 350, $this-&gt;imageType, true);

		$this-&gt;fields_value = array(
			'image' =&gt; $image ? $image : false,
			'size' =&gt; $image ? filesize(_PS_CAT_IMG_DIR_.'/'.$obj-&gt;id.'.jpg') / 1000 : false
		);
</pre>
<p>Into this</p>
<pre class="brush: php; title: ; notranslate">
		$image = ImageManager::thumbnail(_PS_CAT_IMG_DIR_.'/'.$obj-&gt;id.'.jpg', $this-&gt;table.'_'.(int)$obj-&gt;id.'.'.$this-&gt;imageType, 350, $this-&gt;imageType, true);
		$image2 = ImageManager::thumbnail(_PS_CAT_IMG_DIR_.'/'.$obj-&gt;id.'_second.jpg', $this-&gt;table.'_'.(int)$obj-&gt;id.'_second.'.$this-&gt;imageType, 350, $this-&gt;imageType, true);

		$this-&gt;fields_value = array(
			'image' =&gt; $image ? $image : false,
			'size' =&gt; $image ? filesize(_PS_CAT_IMG_DIR_.'/'.$obj-&gt;id.'.jpg') / 1000 : false,
			'image2' =&gt; $image2 ? $image2 : false,
			'size2' =&gt; $image2 ? filesize(_PS_CAT_IMG_DIR_.'/'.$obj-&gt;id.'_second.jpg') / 1000 : false
		);
</pre>
<p>Useless to mention we are doing the same, once more. We are done with renderForm, let&#8217;s deal with <strong>postImage()</strong> now!</p>
<h3>Managing the new image upload and removal</h3>
<p>Trying to fill in the new file input would not produce anything, at the moment. The whole upload magic is held through a method named <strong>postImage()</strong>, which we are going to override and extend. Thus, copy it from the original AdminCategoriesController, and paste it inside the override file. It should look like the following:</p>
<pre class="brush: php; title: ; notranslate">

	protected function postImage($id)
	{
		$ret = parent::postImage($id);
		if (($id_category = (int)Tools::getValue('id_category')) &amp;&amp;
			isset($_FILES) &amp;&amp; count($_FILES) &amp;&amp; $_FILES['image']['name'] != null &amp;&amp;
			file_exists(_PS_CAT_IMG_DIR_.$id_category.'.jpg'))
		{
			$images_types = ImageType::getImagesTypes('categories');
			foreach ($images_types as $k =&gt; $image_type)
			{
				ImageManager::resize(
					_PS_CAT_IMG_DIR_.$id_category.'.jpg',
					_PS_CAT_IMG_DIR_.$id_category.'-'.stripslashes($image_type['name']).'.jpg',
					(int)$image_type['width'], (int)$image_type['height']
				);
			}
		}

		return $ret;
	}
</pre>
<p>Get rid of <strong>return $ret;</strong>, and add the following instead:</p>
<pre class="brush: php; title: ; notranslate">


		$ret2 = $this-&gt;uploadImage($id.'_second', 'image2', $this-&gt;fieldImageSettings['dir'].'/');
		if (($id_category = (int)Tools::getValue('id_category')) &amp;&amp;
			isset($_FILES) &amp;&amp; count($_FILES) &amp;&amp; $_FILES['image2']['name'] != null &amp;&amp;
			file_exists(_PS_CAT_IMG_DIR_.$id_category.'_second.jpg'))
		{
			$images_types = ImageType::getImagesTypes('categories');
			foreach ($images_types as $k =&gt; $image_type)
			{
				ImageManager::resize(
					_PS_CAT_IMG_DIR_.$id_category.'_second.jpg',
					_PS_CAT_IMG_DIR_.$id_category.'_second-'.stripslashes($image_type['name']).'.jpg',
					(int)$image_type['width'], (int)$image_type['height']
				);
			}
		}

		return $ret &amp;&amp; $ret2;

</pre>
<p><strong>Explanation:</strong> first, we are grabbing some code directly from the adminController. We have to use a custom name for the image upload, which is the category id plus _second, using the field &#8220;image2&#8243;. The rest is simply a copy/paste of the above, with, again, changes in the name only. Lastly, we make sure that we return true only if both eventual uploads were successful.</p>
<p><strong>We have a problem though</strong>. At the time being, Prestashop still thinks we only have one image for the category entity. Thus, when uploading any other image for it (excluding thumbs), it will erase the previous one. We can test it right away: upload a new image for the image2 field, you will notice the original category image will be erased. As we don&#8217;t want this, we have to grab <strong>imageUpload()</strong> directly from the AdminController.php file, and extend it. Locate the method, and paste it inside our override. In Prestashop 1.6.0.9, it looks like this: </p>
<pre class="brush: php; title: ; notranslate">
	protected function uploadImage($id, $name, $dir, $ext = false, $width = null, $height = null)
	{
		if (isset($_FILES[$name]['tmp_name']) &amp;&amp; !empty($_FILES[$name]['tmp_name']))
		{
			// Delete old image
			if (Validate::isLoadedObject($object = $this-&gt;loadObject()))
				$object-&gt;deleteImage();
			else
				return false;

			// Check image validity
			$max_size = isset($this-&gt;max_image_size) ? $this-&gt;max_image_size : 0;
			if ($error = ImageManager::validateUpload($_FILES[$name], Tools::getMaxUploadSize($max_size)))
				$this-&gt;errors[] = $error;

			$tmp_name = tempnam(_PS_TMP_IMG_DIR_, 'PS');
			if (!$tmp_name)
				return false;

			if (!move_uploaded_file($_FILES[$name]['tmp_name'], $tmp_name))
				return false;

			// Evaluate the memory required to resize the image: if it's too much, you can't resize it.
			if (!ImageManager::checkImageMemoryLimit($tmp_name))
				$this-&gt;errors[] = Tools::displayError('Due to memory limit restrictions, this image cannot be loaded. Please increase your memory_limit value via your server\'s configuration settings. ');

			// Copy new image
			if (empty($this-&gt;errors) &amp;&amp; !ImageManager::resize($tmp_name, _PS_IMG_DIR_.$dir.$id.'.'.$this-&gt;imageType, (int)$width, (int)$height, ($ext ? $ext : $this-&gt;imageType)))
				$this-&gt;errors[] = Tools::displayError('An error occurred while uploading the image.');

			if (count($this-&gt;errors))
				return false;
			if ($this-&gt;afterImageUpload())
			{
				unlink($tmp_name);
				return true;
			}
			return false;
		}
		return true;
	}

</pre>
<p>Pay attention at this snippet:</p>
<pre class="brush: php; title: ; notranslate">

			// Delete old image
			if (Validate::isLoadedObject($object = $this-&gt;loadObject()))
				$object-&gt;deleteImage();
			else
				return false;
</pre>
<p>It&#8217;s where the original image gets erased to make room for a new one. Change it to:</p>
<pre class="brush: php; title: ; notranslate">

			// Delete old image
			if (Validate::isLoadedObject($object = $this-&gt;loadObject()))
			{
				if($name == 'image2')
					$object-&gt;deleteImage2();
				else $object-&gt;deleteImage();
			} else
				return false;
</pre>
<p>It won&#8217;t work yet as didn&#8217;t override the Category class and added the deleteImage2 method. Before leaving this file, we need to extend one, last function, <strong>postProcess()</strong>. Copy it again from the original AdminCategoriesController, it should be something like:</p>
<pre class="brush: php; title: ; notranslate">

	public function postProcess()
	{
		if (!in_array($this-&gt;display, array('edit', 'add')))
			$this-&gt;multishop_context_group = false;
		if (Tools::isSubmit('forcedeleteImage') || (isset($_FILES['image']) &amp;&amp; $_FILES['image']['size'] &gt; 0) || Tools::getValue('deleteImage'))
		{
			$this-&gt;processForceDeleteImage();
			if (Tools::isSubmit('forcedeleteImage'))
				Tools::redirectAdmin(self::$currentIndex.'&amp;token='.Tools::getAdminTokenLite('AdminCategories').'&amp;conf=7');
		}

		return parent::postProcess();
	}
</pre>
<p>We need to take care of the secondary image deletion:</p>
<pre class="brush: php; title: ; notranslate">

	public function postProcess()
	{
		if (!in_array($this-&gt;display, array('edit', 'add')))
			$this-&gt;multishop_context_group = false;
		if (Tools::isSubmit('forcedeleteImage') || (isset($_FILES['image']) &amp;&amp; $_FILES['image']['size'] &gt; 0) || Tools::getValue('deleteImage'))
		{
			$this-&gt;processForceDeleteImage();
			if (Tools::isSubmit('forcedeleteImage'))
				Tools::redirectAdmin(self::$currentIndex.'&amp;token='.Tools::getAdminTokenLite('AdminCategories').'&amp;conf=7');
		} else if(Tools::getValue('deleteImage2'))
		{
			$category = $this-&gt;loadObject(true);

			if (Validate::isLoadedObject($category))
				if($category-&gt;deleteImage2(true))
					Tools::redirectAdmin(self::$currentIndex.'&amp;token='.Tools::getAdminTokenLite('AdminCategories').'&amp;updatecategory&amp;id_category='.$category-&gt;id.'&amp;conf=7');
		}

		return parent::postProcess();
	}
</pre>
<p>And we are done with this file, let&#8217;s extend the Category class now.</p>
<div class="separator"></div>
<h2>Overriding the category class</h2>
<p>Create a new file inside <em>override/classes</em> and name it <strong>Category.php</strong> (or use an existing override if you have it). First of all, we need to test it the back office functionality, so let&#8217;s add that deleteImage2() method:</p>
<pre class="brush: php; title: ; notranslate">


Class Category extends CategoryCore
{


	public function deleteImage2($force_delete = false)
	{
		if (!$this-&gt;id)
			return false;
		
		if ($force_delete || !$this-&gt;hasMultishopEntries())
		{
			/* Deleting object images and thumbnails (cache) */
			if ($this-&gt;image_dir)
			{
				if (file_exists($this-&gt;image_dir.$this-&gt;id.'_second.'.$this-&gt;image_format)
					&amp;&amp; !unlink($this-&gt;image_dir.$this-&gt;id.'_second.'.$this-&gt;image_format))
					return false;
			}
			if (file_exists(_PS_TMP_IMG_DIR_.$this-&gt;def['table'].'_'.$this-&gt;id.'_second.'.$this-&gt;image_format)
				&amp;&amp; !unlink(_PS_TMP_IMG_DIR_.$this-&gt;def['table'].'_'.$this-&gt;id.'_second.'.$this-&gt;image_format))
				return false;
			if (file_exists(_PS_TMP_IMG_DIR_.$this-&gt;def['table'].'_mini_'.$this-&gt;id.'_second.'.$this-&gt;image_format)
				&amp;&amp; !unlink(_PS_TMP_IMG_DIR_.$this-&gt;def['table'].'_mini_'.$this-&gt;id.'_second.'.$this-&gt;image_format))
				return false;
	
			$types = ImageType::getImagesTypes();
			foreach ($types as $image_type)
				if (file_exists($this-&gt;image_dir.$this-&gt;id.'_second-'.stripslashes($image_type['name']).'.'.$this-&gt;image_format)
				&amp;&amp; !unlink($this-&gt;image_dir.$this-&gt;id.'_second-'.stripslashes($image_type['name']).'.'.$this-&gt;image_format))
					return false;
		}
		return true;
	}
}
</pre>
<p>To create it, I simply copied the original deleteImage from the <strong>objectModel</strong>, and modified the name of each entry to reflect our convention (_second).</p>
<p>Time to test the back office! Access the categories tab, then open up one of them and try adding an image. Then, delete this image to check if that works as well. Then again add one, and one immediately after to check it gets over-written. Lastly, make sure the original one isn&#8217;t erased during this process, and the new one is not affected by any operation on the first onee. </p>
<p>After checking this, it&#8217;s time too display the new thumb. Since we will use it in subcategories, we need to assign it at the time they are retrieved for the template display. This is held through the <strong>getSubcategories()</strong> method of the Category class. Thus, copy the original one and paste it inside our override:</p>
<pre class="brush: php; title: ; notranslate">
	public function getSubCategories($id_lang, $active = true)
	{
		$sql_groups_where = '';
		$sql_groups_join = '';
		if (Group::isFeatureActive())
		{
			$sql_groups_join = 'LEFT JOIN `'._DB_PREFIX_.'category_group` cg ON (cg.`id_category` = c.`id_category`)';
			$groups = FrontController::getCurrentCustomerGroups();
			$sql_groups_where = 'AND cg.`id_group` '.(count($groups) ? 'IN ('.implode(',', $groups).')' : '='.(int)Group::getCurrent()-&gt;id);
		}

		$result = Db::getInstance(_PS_USE_SQL_SLAVE_)-&gt;executeS('
		SELECT c.*, cl.id_lang, cl.name, cl.description, cl.link_rewrite, cl.meta_title, cl.meta_keywords, cl.meta_description
		FROM `'._DB_PREFIX_.'category` c
		'.Shop::addSqlAssociation('category', 'c').'
		LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (c.`id_category` = cl.`id_category` AND `id_lang` = '.(int)$id_lang.' '.Shop::addSqlRestrictionOnLang('cl').')
		'.$sql_groups_join.'
		WHERE `id_parent` = '.(int)$this-&gt;id.'
		'.($active ? 'AND `active` = 1' : '').'
		'.$sql_groups_where.'
		GROUP BY c.`id_category`
		ORDER BY `level_depth` ASC, category_shop.`position` ASC');

		foreach ($result as &amp;$row)
		{
			
			$row['legend'] = 'no picture';
		}
		return $result;
	}
</pre>
<p>Then, right after this:</p>
<pre class="brush: php; title: ; notranslate">
$row['id_image'] = Tools::file_exists_cache(_PS_CAT_IMG_DIR_.$row['id_category'].'.jpg') ? (int)$row['id_category'] : Language::getIsoById($id_lang).'-default';
</pre>
<p>Add our new image definition</p>
<pre class="brush: php; title: ; notranslate">
$row['id_image2'] = Tools::file_exists_cache(_PS_CAT_IMG_DIR_.$row['id_category'].'_second.jpg') ? (int)$row['id_category'] .'_second' : Language::getIsoById($id_lang).'-default';
</pre>
<p>And we are done with php! </p>
<div class="separator"></div>
<h2>Display the new image in the template</h2>
<p>We are almost there. Open <strong>category.tpl</strong>, located in the theme&#8217;s folder. Locate:</p>
<pre class="brush: php; html-script: true; title: ; notranslate">
{if $subcategory.id_image}
	&lt;img class=&quot;replace-2x&quot; src=&quot;{$link-&gt;getCatImageLink($subcategory.link_rewrite, $subcategory.id_image, 'medium_default')|escape:'html':'UTF-8'}&quot; alt=&quot;&quot; width=&quot;{$mediumSize.width}&quot; height=&quot;{$mediumSize.height}&quot; /&gt;
{else}
</pre>
<p>And change it to</p>
<pre class="brush: php; html-script: true; title: ; notranslate">
{if $subcategory.id_image2}
	&lt;img class=&quot;replace-2x&quot; src=&quot;{$link-&gt;getCatImageLink($subcategory.link_rewrite, $subcategory.id_image2, 'medium_default')|escape:'html':'UTF-8'}&quot; alt=&quot;&quot; width=&quot;{$mediumSize.width}&quot; height=&quot;{$mediumSize.height}&quot; /&gt;
{else}
</pre>
<p>This will be enough if friendly urls are not enabled. <strong>But what if we are using rewritten URLs?</strong>. Sadly, we need to hardcode one, last modification in the <strong>.htaccess file</strong>. It is not exactly bulletproof, but it worked out well in all my tests. Therefore, open your <strong>.htaccess</strong>, and add the following <strong>at the very beginning, right BEFORE &#8220;# ~~start~~ Do not remove this comment, Prestashop will keep automatically the code outside this comment when .htaccess will be generated again&#8221;</strong></p>
<pre class="brush: php; title: ; notranslate">
&lt;IfModule mod_rewrite.c&gt;
RewriteRule ^c/([0-9]+)_second(\-[\.*_a-zA-Z0-9-]*)(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/c/$1_second$2$3.jpg [L]
&lt;/IfModule&gt;
</pre>
<p>This will make sure our &#8220;_second&#8221; text in the image path won&#8217;t be treated as part of the category ID, thus making it impossible to retrieve the picture.</p>
<div class="separator"></div>
<h2>Conclusion</h2>
<p>Despite being a bit cumbersome, adding a secondary image for categories (or actually any other entity such as manufacturers or suppliers) is indeed possible by using this technique. The final trick for rewritten-url environments is to make sure the proper regEx is added right at the beginning of the .htaccess file.</p>
<p>The post <a rel="nofollow" href="https://nemops.com/prestashop-categories-second-image/">Adding a second image for Prestashop categories</a> appeared first on <a rel="nofollow" href="https://nemops.com">NemoPS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://nemops.com/prestashop-categories-second-image/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
	</channel>
</rss>
