Добавление второго изображения для рубрик Prestashop

Добавление второго изображения для рубрик Prestashop

В Prestashop разрешено использовать только одно изображение-миниатюру по умолчанию, тем самым создавая проблемы в наличии разных форматов для пиктограмм подкатегорий в списке. Поэтому мы представим вторичное изображение для категорий Prestashop, чтобы увеличить плавность на дисплее при отображении их как подкатегории.
Версия Prestashop: любая 1.6 (используемая: 1.6.0.9, также должна подойти для 1.5, хотя и не тестировалась на этой версии).
Скачать файлы проекта
Введение


Перед тем, как начать, стоит отметить, что данная обучающая программа предусматривает много модификаций и переопределений, и желательно, чтобы пользователь был хорошо осведомлен в php прежде, чем что-либо делать. Если же Вы новичок в этой сфере, то обратитесь к официальной документации Prestashop на Overrides (переопределение).
Перечень файлов, необходимых для изменения или отмены:
AdminCategoriesController.php: здесь будет наиболее волшебный участок работы – загрузка и удаление новых изображений,
Category.php: класс категории, где нам предстоит определить новое поле и удаление графических изображений,
Сategory.tpl: для отображения нового изображения для подкатегории,
.htaccess: требуется только в случае использования friendly URLs (дружественные адреса ресурсов), в противном случае ни одно изображение не будет отображаться.

Расширение файла AdminCategoriesController


Контроллер администратора по категориям (AdminCategoriesController) является файлом, с которым придется работать чаще всего. Хотя можно модифицировать его напрямую, практика показывает, что лучше использовать для этого модификатор override.
Таким образом, создаем файл в /override/controllers/admin с названием AdminCategoriesController.php и вставляем в php-теги следующее:
class AdminCategoriesController extends AdminCategoriesControllerCore
{
}

Теперь, берем оригинальный AdminCategoriesController находится он в /controllers/admin, открываем, размещаем и копируем все renderForm-методом. Вставляем это в новый оверрайд:
class AdminCategoriesController extends AdminCategoriesControllerCore
{
 
 
    public function renderForm()
    {
        $this->initToolbar();
        $obj = $this->loadObject(true);
        $id_shop = Context::getContext()->shop->id;
        $selected_categories = array((isset($obj->id_parent) && $obj->isParentCategoryAvailable($id_shop))? (int)$obj->id_parent : (int)Tools::getValue('id_parent', Category::getRootCategory()->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->l('%s - All people without a valid customer account.'), '<b>'.$unidentified->name[$this->context->language->id].'</b>');
        $guest_group_information = sprintf($this->l('%s - Customer who placed an order with the guest checkout.'), '<b>'.$guest->name[$this->context->language->id].'</b>');
        $default_group_information = sprintf($this->l('%s - All people who have created an account on this site.'), '<b>'.$default->name[$this->context->language->id].'</b>');
 
        if (!($obj = $this->loadObject(true)))
            return;
 
        $image = _PS_CAT_IMG_DIR_.$obj->id.'.jpg';
        $image_url = ImageManager::thumbnail($image, $this->table.'_'.(int)$obj->id.'.'.$this->imageType, 350,
            $this->imageType, true, true);
        $image_size = file_exists($image) ? filesize($image) / 1000 : false;
 
        $this->fields_form = array(
            'tinymce' => true,
            'legend' => array(
                'title' => $this->l('Category'),
                'icon' => 'icon-tags'
            ),
            'input' => array(
                array(
                    'type' => 'text',
                    'label' => $this->l('Name'),
                    'name' => 'name',
                    'lang' => true,
                    'required' => true,
                    'class' => 'copy2friendlyUrl',
                    'hint' => $this->l('Invalid characters:').' <>;=#{}',
                ),
                array(
                    'type' => 'switch',
                    'label' => $this->l('Displayed'),
                    'name' => 'active',
                    'required' => false,
                    'is_bool' => true,
                    'values' => array(
                        array(
                            'id' => 'active_on',
                            'value' => 1,
                            'label' => $this->l('Enabled')
                        ),
                        array(
                            'id' => 'active_off',
                            'value' => 0,
                            'label' => $this->l('Disabled')
                        )
                    )
                ),
                array(
                    'type'  => 'categories',
                    'label' => $this->l('Parent category'),
                    'name'  => 'id_parent',
                    'tree'  => array(
                        'id'                  => 'categories-tree',
                        'selected_categories' => $selected_categories,
                        'disabled_categories' => !Tools::isSubmit('add'.$this->table) ? array($this->_category->id) : null
                    )
                ),
                array(
                    'type' => 'textarea',
                    'label' => $this->l('Description'),
                    'name' => 'description',
                    'autoload_rte' => true,
                    'lang' => true,
                    'hint' => $this->l('Invalid characters:').' <>;=#{}'
                ),
                array(
                    'type' => 'file',
                    'label' => $this->l('Image'),
                    'name' => 'image',
                    'display_image' => true,
                    'image' => $image_url ? $image_url : false,
                    'size' => $image_size,
                    'delete_url' => self::$currentIndex.'&'.$this->identifier.'='.$this->_category->id.'&token='.$this->token.'&deleteImage=1',
                    'hint' => $this->l('Upload a category logo from your computer.'),
                ),
                array(
                    'type' => 'text',
                    'label' => $this->l('Meta title'),
                    'name' => 'meta_title',
                    'lang' => true,
                    'hint' => $this->l('Forbidden characters:').' <>;=#{}'
                ),
                array(
                    'type' => 'text',
                    'label' => $this->l('Meta description'),
                    'name' => 'meta_description',
                    'lang' => true,
                    'hint' => $this->l('Forbidden characters:').' <>;=#{}'
                ),
                array(
                    'type' => 'tags',
                    'label' => $this->l('Meta keywords'),
                    'name' => 'meta_keywords',
                    'lang' => true,
                    'hint' => $this->l('To add "tags," click in the field, write something, and then press "Enter."').' '.$this->l('Forbidden characters:').' <>;=#{}'
                ),
                array(
                    'type' => 'text',
                    'label' => $this->l('Friendly URL'),
                    'name' => 'link_rewrite',
                    'lang' => true,
                    'required' => true,
                    'hint' => $this->l('Only letters, numbers, underscore (_) and the minus (-) character are allowed.')
                ),
                array(
                    'type' => 'group',
                    'label' => $this->l('Group access'),
                    'name' => 'groupBox',
                    'values' => Group::getGroups(Context::getContext()->language->id),
                    'info_introduction' => $this->l('You now have three default customer groups.'),
                    'unidentified' => $unidentified_group_information,
                    'guest' => $guest_group_information,
                    'customer' => $default_group_information,
                    'hint' => $this->l('Mark all of the customer groups which you would like to have access to this category.')
                )
            ),
            'submit' => array(
                'title' => $this->l('Save'),
                'name' => 'submitAdd'.$this->table.($this->_category->is_root_category && !Tools::isSubmit('add'.$this->table) && !Tools::isSubmit('add'.$this->table.'root') ? '': 'AndBackToParent')
            )
        );
 
        $this->tpl_form_vars['shared_category'] = Validate::isLoadedObject($obj) && $obj->hasMultishopEntries();
        $this->tpl_form_vars['PS_ALLOW_ACCENTED_CHARS_URL'] = (int)Configuration::get('PS_ALLOW_ACCENTED_CHARS_URL');
        $this->tpl_form_vars['displayBackOfficeCategory'] = Hook::exec('displayBackOfficeCategory');
 
        // Display this field only if multistore option is enabled
        if (Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE') && Tools::isSubmit('add'.$this->table.'root'))
        {
            $this->fields_form['input'][] = array(
                'type' => 'switch',
                'label' => $this->l('Root Category'),
                'name' => 'is_root_category',
                'required' => false,
                'is_bool' => true,
                'values' => array(
                    array(
                        'id' => 'is_root_on',
                        'value' => 1,
                        'label' => $this->l('Yes')
                    ),
                    array(
                        'id' => 'is_root_off',
                        'value' => 0,
                        'label' => $this->l('No')
                    )
                )
            );
            unset($this->fields_form['input'][2],$this->fields_form['input'][3]);
        }
        // Display this field only if multistore option is enabled AND there are several stores configured
        if (Shop::isFeatureActive())
            $this->fields_form['input'][] = array(
                'type' => 'shop',
                'label' => $this->l('Shop association'),
                'name' => 'checkBoxShopAsso',
            );
 
        // remove category tree and radio button "is_root_category" if this category has the root category as parent category to avoid any conflict
        if ($this->_category->id_parent == Category::getTopCategory()->id && Tools::isSubmit('updatecategory'))
            foreach ($this->fields_form['input'] as $k => $input)
                if (in_array($input['name'], array('id_parent', 'is_root_category')))
                    unset($this->fields_form['input'][$k]);
 
        if (!($obj = $this->loadObject(true)))
            return;
 
        $image = ImageManager::thumbnail(_PS_CAT_IMG_DIR_.'/'.$obj->id.'.jpg', $this->table.'_'.(int)$obj->id.'.'.$this->imageType, 350, $this->imageType, true);
 
        $this->fields_value = array(
            'image' => $image ? $image : false,
            'size' => $image ? filesize(_PS_CAT_IMG_DIR_.'/'.$obj->id.'.jpg') / 1000 : false
        );
 
        // Added values of object Group
        $category_groups_ids = $obj->getGroups();
 
        $groups = Group::getGroups($this->context->language->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->fields_value['groupBox_'.$group['id_group']] = Tools::getValue('groupBox_'.$group['id_group'], (in_array($group['id_group'], $category_groups_ids)));
 
        $this->fields_value['is_root_category'] = (bool)Tools::isSubmit('add'.$this->table.'root');
 
        return parent::renderForm();
    }
     
}

Обратите внимание на последнюю строку return parent::renderForm();. Замените ее на return AdminController::renderForm();. Если не сделать это дополнительное действие, то все наши изменения будут отменены оригинальным контроллером. Чтобы убедиться, что оверрайд работает, заходим в кэш (cache/) и удаляем class_index.php, чтобы мог запуститься новый файл. Теперь авторизируемся на бэк-офис и проверяем по отдельным категориям, или они работают, как ожидалось. Если да, читайте дальше.
Добавление нового поля


Прежде всего, нужно добавить код, отображающий любые возможные изображения, которые были загружены. Для этого определите местонахождение следующего:
$image = _PS_CAT_IMG_DIR_.$obj->id.'.jpg';
$image_url = ImageManager::thumbnail($image, $this->table.'_'.(int)$obj->id.'.'.$this->imageType, 350,
    $this->imageType, true, true);
$image_size = file_exists($image) ? filesize($image) / 1000 : false;

Сразу после этого добавьте:

1
2
3
4
$image2 = _PS_CAT_IMG_DIR_.$obj->id.'_second.jpg';
$image_url2 = ImageManager::thumbnail($image2, $this->table.'_'.(int)$obj->id.'_second.'.$this->imageType, 350,
    $this->imageType, true, true);
$image_size2 = file_exists($image2) ? filesize($image2) / 1000 : false;

Это то же самое, но с измененными именами. Далее, прямо внизу есть перечень полей. Нам надо добавить сюда ввод файла, чтобы позже можно было загрузить изображение. Таким образом, находим:
array(
    'type' => 'file',
    'label' => $this->l('Image'),
    'name' => 'image',
    'display_image' => true,
    'image' => $image_url ? $image_url : false,
    'size' => $image_size,
    'delete_url' => self::$currentIndex.'&'.$this->identifier.'='.$this->_category->id.'&token='.$this->token.'&deleteImage=1',
    'hint' => $this->l('Upload a category logo from your computer.'),
),

И сразу после этого добавляем следующее:
array(
    'type' => 'file',
    'label' => $this->l('Image2'),
    'name' => 'image2',
    'display_image' => true,
    'image' => $image_url2 ? $image_url2 : false,
    'size' => $image_size2,
    'delete_url' => self::$currentIndex.'&'.$this->identifier.'='.$this->_category->id.'&token='.$this->token.'&deleteImage2=1',
    'hint' => $this->l('Upload a secondary category logo from your computer.'),
),

Здесь опять тот же код, но разные имена. И, наконец, меняем вот это:
$image = ImageManager::thumbnail(_PS_CAT_IMG_DIR_.'/'.$obj->id.'.jpg', $this->table.'_'.(int)$obj->id.'.'.$this->imageType, 350, $this->imageType, true);
 
$this->fields_value = array(
    'image' => $image ? $image : false,
    'size' => $image ? filesize(_PS_CAT_IMG_DIR_.'/'.$obj->id.'.jpg') / 1000 : false
);

На это:
$image = ImageManager::thumbnail(_PS_CAT_IMG_DIR_.'/'.$obj->id.'.jpg', $this->table.'_'.(int)$obj->id.'.'.$this->imageType, 350, $this->imageType, true);
$image2 = ImageManager::thumbnail(_PS_CAT_IMG_DIR_.'/'.$obj->id.'_second.jpg', $this->table.'_'.(int)$obj->id.'_second.'.$this->imageType, 350, $this->imageType, true);
 
$this->fields_value = array(
    'image' => $image ? $image : false,
    'size' => $image ? filesize(_PS_CAT_IMG_DIR_.'/'.$obj->id.'.jpg') / 1000 : false,
    'image2' => $image2 ? $image2 : false,
    'size2' => $image2 ? filesize(_PS_CAT_IMG_DIR_.'/'.$obj->id.'_second.jpg') / 1000 : false
);

Не станем каждый раз упоминать, что делаем мы, то же самое. Мы проделали это с renderForm, теперь будем иметь дело с postImage().
Управление новым загруженным изображением и его перемещение


Попытка заполнить новое поле на данном этапе не даст ничего. Все волшебство загрузок проходит методом, что носит название postImage(), которое мы собираемся переопределить и расширить. Таким образом, копируем его из исходного AdminCategoriesController и вставляем в файл коррекции (оверайда). Будет это выглядеть так:
protected function postImage($id)
{
    $ret = parent::postImage($id);
    if (($id_category = (int)Tools::getValue('id_category')) &&
        isset($_FILES) && count($_FILES) && $_FILES['image']['name'] != null &&
        file_exists(_PS_CAT_IMG_DIR_.$id_category.'.jpg'))
    {
        $images_types = ImageType::getImagesTypes('categories');
        foreach ($images_types as $k => $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;
}

Теперь надо вместо последней строки return $ret;, добавить следующее:
$ret2 = $this->uploadImage($id.'_second', 'image2', $this->fieldImageSettings['dir'].'/');
if (($id_category = (int)Tools::getValue('id_category')) &&
    isset($_FILES) && count($_FILES) && $_FILES['image2']['name'] != null &&
    file_exists(_PS_CAT_IMG_DIR_.$id_category.'_second.jpg'))
{
    $images_types = ImageType::getImagesTypes('categories');
    foreach ($images_types as $k => $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 && $ret2;

Объяснение: сначала мы захватываем некоторый код непосредственно из adminController. Нужно использовать имя пользователя для загрузки изображения, что является категорией ID plus _second, используя поле “image2″. Далее просто копировать-вставить все вышеприведенное, конечно же, с измененными именами. Если обе возможных загрузки оказались успешными, то мы вернули все правильно.

Однако, есть одна проблема. На этом этапе Prestashop все еще воспринимает одно изображение для всей категории. Таким образом, когда загружаешь любое другое изображение для программы (исключая thumbs), она будет удалять предыдущее. Можем это проверить: загружаем новое изображение для поля image2, и видим, что исходное изображение категории будет стерто. Если мы этого не хотим, то нужно перетащить imageUpload() непосредственно из файла AdminController.php и расширить его. Находим метод, вставляем в оверайд. В Prestashop 1.6.0.9 это выглядит подобным образом:
protected function uploadImage($id, $name, $dir, $ext = false, $width = null, $height = null)
{
    if (isset($_FILES[$name]['tmp_name']) && !empty($_FILES[$name]['tmp_name']))
    {
        // Delete old image
        if (Validate::isLoadedObject($object = $this->loadObject()))
            $object->deleteImage();
        else
            return false;
 
        // Check image validity
        $max_size = isset($this->max_image_size) ? $this->max_image_size : 0;
        if ($error = ImageManager::validateUpload($_FILES[$name], Tools::getMaxUploadSize($max_size)))
            $this->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->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->errors) && !ImageManager::resize($tmp_name, _PS_IMG_DIR_.$dir.$id.'.'.$this->imageType, (int)$width, (int)$height, ($ext ? $ext : $this->imageType)))
            $this->errors[] = Tools::displayError('An error occurred while uploading the image.');
 
        if (count($this->errors))
            return false;
        if ($this->afterImageUpload())
        {
            unlink($tmp_name);
            return true;
        }
        return false;
    }
    return true;
}

Обратите внимание на этот фрагмент:
// Delete old image
if (Validate::isLoadedObject($object = $this->loadObject()))
    $object->deleteImage();
else
    return false;

Это как раз тот участок, где стирается исходное изображение, чтобы освободить место для нового. Меняем его на:
// Delete old image
if (Validate::isLoadedObject($object = $this->loadObject()))
{
    if($name == 'image2')
        $object->deleteImage2();
    else $object->deleteImage();
} else
    return false;

Но и это тоже еще не работает, пока не переопределен класс Категории и не добавлен метод deleteImage2. Перед тем, как покинуть этот файл, нужно расширить одну последнюю функцию postProcess(). Вновь копируем ее из исходного AdminCategoriesController. Это будет выглядеть так:
public function postProcess()
{
    if (!in_array($this->display, array('edit', 'add')))
        $this->multishop_context_group = false;
    if (Tools::isSubmit('forcedeleteImage') || (isset($_FILES['image']) && $_FILES['image']['size'] > 0) || Tools::getValue('deleteImage'))
    {
        $this->processForceDeleteImage();
        if (Tools::isSubmit('forcedeleteImage'))
            Tools::redirectAdmin(self::$currentIndex.'&token='.Tools::getAdminTokenLite('AdminCategories').'&conf=7');
    }
 
    return parent::postProcess();
}

Нужно также позаботиться об удалении вторичного изображения:
public function postProcess()
{
    if (!in_array($this->display, array('edit', 'add')))
        $this->multishop_context_group = false;
    if (Tools::isSubmit('forcedeleteImage') || (isset($_FILES['image']) && $_FILES['image']['size'] > 0) || Tools::getValue('deleteImage'))
    {
        $this->processForceDeleteImage();
        if (Tools::isSubmit('forcedeleteImage'))
            Tools::redirectAdmin(self::$currentIndex.'&token='.Tools::getAdminTokenLite('AdminCategories').'&conf=7');
    } else if(Tools::getValue('deleteImage2'))
    {
        $category = $this->loadObject(true);
 
        if (Validate::isLoadedObject($category))
            if($category->deleteImage2(true))
                Tools::redirectAdmin(self::$currentIndex.'&token='.Tools::getAdminTokenLite('AdminCategories').'&updatecategory&id_category='.$category->id.'&conf=7');
    }
 
    return parent::postProcess();
}

Теперь мы закончили с этим файлом, переходим к расширению класса Категории.
Переопределение класса Категории


Создаем новый файл в override/classes и называем его Category.php (или используем имеющееся переопределение, если оно есть). Прежде всего, нужно протестировать его функциональность в бэк-офисе, поэтому нужно добавить такой метод deleteImage2():
Class Category extends CategoryCore
{
 
 
    public function deleteImage2($force_delete = false)
    {
        if (!$this->id)
            return false;
         
        if ($force_delete || !$this->hasMultishopEntries())
        {
            /* Deleting object images and thumbnails (cache) */
            if ($this->image_dir)
            {
                if (file_exists($this->image_dir.$this->id.'_second.'.$this->image_format)
                    && !unlink($this->image_dir.$this->id.'_second.'.$this->image_format))
                    return false;
            }
            if (file_exists(_PS_TMP_IMG_DIR_.$this->def['table'].'_'.$this->id.'_second.'.$this->image_format)
                && !unlink(_PS_TMP_IMG_DIR_.$this->def['table'].'_'.$this->id.'_second.'.$this->image_format))
                return false;
            if (file_exists(_PS_TMP_IMG_DIR_.$this->def['table'].'_mini_'.$this->id.'_second.'.$this->image_format)
                && !unlink(_PS_TMP_IMG_DIR_.$this->def['table'].'_mini_'.$this->id.'_second.'.$this->image_format))
                return false;
     
            $types = ImageType::getImagesTypes();
            foreach ($types as $image_type)
                if (file_exists($this->image_dir.$this->id.'_second-'.stripslashes($image_type['name']).'.'.$this->image_format)
                && !unlink($this->image_dir.$this->id.'_second-'.stripslashes($image_type['name']).'.'.$this->image_format))
                    return false;
        }
        return true;
    }
}

Чтобы его создать, можно просто скопировать исходный deleteImage из objectModel и изменить название каждой записи для отображения нашего соглашения (_second).
Теперь надо проверить бэк-офис. Зайдите на вкладку категорий, откройте одну из них и попробуйте добавить изображение. Потом удалите это изображение, чтобы проверить, сработает или нет. Теперь вновь добавьте одно, сразу друг за другом, чтобы проверить, или оно становится перезаписанным. Наконец убедитесь, что исходное изображение не удалено после всех этих процедур, и что на новое не влияют никакие операции с первым.
После этой проверки как раз время отобразить новые thumb. Поскольку мы будем использовать его в подкатегориях, нужно назначить его тогда, когда происходит извлечение для отображения шаблонов. Это проводится через getSubcategories() по классам Категорий. Таким образом, копируем исходный и вставляем в оверайд:
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()->id);
    }
 
    $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->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->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 &$row)
    {
         
        $row['legend'] = 'no picture';
    }
    return $result;
}

Теперь сразу после этого:
$row['id_image'] = Tools::file_exists_cache(_PS_CAT_IMG_DIR_.$row['id_category'].'.jpg') ? (int)$row['id_category'] : Language::getIsoById($id_lang).'-default';

Добавляем новое определение изображения:
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';

Так мы закончили с php!..
Отображение нового изображения в шаблоне


Вот мы уже у цели. Открываем category.tpl, который находится в папке с темами. Размещение:
{if $subcategory.id_image}
    <img class="replace-2x" src="{$link->getCatImageLink($subcategory.link_rewrite, $subcategory.id_image, 'medium_default')|escape:'html':'UTF-8'}" alt="" width="{$mediumSize.width}" height="{$mediumSize.height}" />
{else}

Мы меняем его на:
{if $subcategory.id_image2}
    <img class="replace-2x" src="{$link->getCatImageLink($subcategory.link_rewrite, $subcategory.id_image2, 'medium_default')|escape:'html':'UTF-8'}" alt="" width="{$mediumSize.width}" height="{$mediumSize.height}" />
{else}

Если дружественные URLs не запрещены, этого хватит. Но если используются перезаписанные URLs? Увы, но придется жестко закодировать последнюю модификацию в файле .htaccess. Это не гарантированная защита, но во время тестов оказалось достаточно эффективным. Открываем .htaccess и добавляем следующее в самом начале, как раз перед “# ~~start~~ Do not remove this comment, Prestashop will keep automatically the code outside this comment when .htaccess will be generated again” (значение строки: не удаляйте этот комментарий, Prestashop автоматически поддерживает код вне этого комментария, когда .htaccess будет генерирован вновь):
<IfModule mod_rewrite.c>
RewriteRule ^c/([0-9]+)_second(\-[\.*_a-zA-Z0-9-]*)(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/c/$1_second$2$3.jpg [L]
</IfModule>

Это поможет убедить “_second”-текст в том, что путь к изображению не рассматривается как часть категории ID, таким образом не давая возможности восстановить картинку.
Заключение


Несмотря на то, что это немного громоздко, добавление вторичного изображения для категорий (или других объектов, таких, как производители или поставщики) действительно возможно, используя эту технику. Последнее, что надо сделать в условиях перезаписанных URL – это убедится, что надлежащий regEx добавлен прямо вначале файла .htaccess.

7 комментариев

avatar
  • vik
  • 0
avatar
Хороший модуль?
avatar
Как показывать эту картинку 2-й после основной, именно на странице выбранной категории, а не в подкатегориях?
avatar
Как это сделать для 1.6.1.0?
В этой версии вылетает ошибка:
Notice в строке 403 в файле: C:\OpenServer\domains\foodgurman\classes\helper\HelperTreeCategories.php
[8] Undefined index: id_category

Notice в строке 33 в файле: C:\OpenServer\domains\foodgurman\tools\smarty\sysplugins\smarty_internal_templatebase.php(157) : eval()'d code
[8] Undefined index: id_category

Notice в строке 35 в файле: C:\OpenServer\domains\foodgurman\tools\smarty\sysplugins\smarty_internal_templatebase.php(157) : eval()'d code
[8] Undefined index: id_category
когда заходишь в редактирование категории.
Notice в строке 39 в файле: C:\OpenServer\domains\foodgurman\tools\smarty\sysplugins\smarty_internal_templatebase.php(157) : eval()'d code
[8] Undefined index: name
avatar
Доброго времени суток, спасибо за вопрос. Баг проверил на последней версии PrestaShop баг не обнаружен. Попробуйте еще раз.
avatar
Спасибо, я уже справился, добавив необходимый код напрямую в файл AdminCategoriesController.php.
Спасибо за статью!
avatar
Будут вопросы приходите stuck_out_tongue_winking_eye
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.