How to add display image for CMS page in Prestashop

I want to add an image from the back-end for every CMS page I add to Prestashop, just like we add image images for posts / page in Wordpress

I have not been able to find codes / modules that support this feature in prestashop.

+5


source to share


5 answers


It is possible, but it is not that easy. Here are the steps you need to take to load images into the CMS page module. This approach isn't the most elegant way to do it in PrestaShop, but I hope it helps you move forward.

Step 1. Update the model to contain the image:

First, override "classes / CMS.php" to "override / classes / CMS.php".

class CMS extends CMSCore
{    
    // add a public field to store the CMS image
    public $CMS_IMG; 

    /**
    * @see ObjectModel::$definition
    */
    public static $definition = array(
        'table' => 'cms',
        'primary' => 'id_cms',
        'multilang' => true,
        'fields' => array(
        'id_cms_category' =>  array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'),
        'position' =>    array('type' => self::TYPE_INT),
        'active' =>    array('type' => self::TYPE_BOOL),
        // Lang fields
        'meta_description' =>  array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255),
        'meta_keywords' =>   array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255),
        'meta_title' =>   array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 128),
        'content' =>    array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isString', 'size' => 3999999999999),

        // add one image per page        
        'CMS_IMG' =>   array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isString', 'size' => 3999999999999),  ),
    );
}

      

Step 2. Inject the code required to upload the image to the back office:

Override 'controllers / admin / AdminCmsController.php' to 'override / controllers / admin / AdminCmsController.php'

class AdminCmsController extends AdminCmsControllerCore
{
    public function renderForm()
    {        
        $this->display = 'edit';
        $this->toolbar_btn['save-and-preview'] = array(
            'href' => '#',
            'desc' => $this->l('Save and preview')
        );
        $this->initToolbar();
        if (!$this->loadObject(true))
            return;
        $categories = CMSCategory::getCategories($this->context->language->id, false);
        $html_categories = CMSCategory::recurseCMSCategory($categories, $categories[0][1], 1, $this->getFieldValue($this->object, 'id_cms_category'), 1);

        // Add code to get image url
        $image_url = '';
        $imgName = $this->getImageValue($this->object);
        if($imgName) {
            $image = _PS_IMG_DIR_ . 'cms/' . $imgName;
            $image_url = ImageManager::thumbnail($image, $this->table.'_'.(int)$this->object->id.'.'.$this->imageType, 350,
                $this->imageType, true, true);
        }

        $this->fields_form = array(
            'tinymce' => true,
            'legend' => array(
                'title' => $this->l('CMS Page'),
                'image' => '../img/admin/tab-categories.gif'
            ),
            'input' => array(
                // custom template
                array(
                    'type' => 'select_category',
                    'label' => $this->l('CMS Category'),
                    'name' => 'id_cms_category',
                    'options' => array(
                        'html' => $html_categories,
                    ),
                ),
                array(
                    'type' => 'text',
                    'label' => $this->l('Meta title:'),
                    'name' => 'meta_title',
                    'id' => 'name', // for copy2friendlyUrl compatibility
                    'lang' => true,
                    'required' => true,
                    'class' => 'copy2friendlyUrl',
                    'hint' => $this->l('Invalid characters:').' <>;=#{}',
                    'size' => 50
                ),
                array(
                    'type' => 'text',
                    'label' => $this->l('Meta description'),
                    'name' => 'meta_description',
                    'lang' => true,
                    'hint' => $this->l('Invalid characters:').' <>;=#{}',
                    'size' => 70
                ),
                array(
                    'type' => 'tags',
                    'label' => $this->l('Meta keywords'),
                    'name' => 'meta_keywords',
                    'lang' => true,
                    'hint' => $this->l('Invalid characters:').' <>;=#{}',
                    'size' => 70,
                    'desc' => $this->l('To add "tags" click in the field, write something, then press "Enter"')
                ),
                array(
                    'type' => 'text',
                    'label' => $this->l('Friendly URL'),
                    'name' => 'link_rewrite',
                    'required' => true,
                    'lang' => true,
                    'hint' => $this->l('Only letters and the minus (-) character are allowed')
                ),
                array(
                    'type' => 'textarea',
                    'label' => $this->l('Page content'),
                    'name' => 'content',
                    'autoload_rte' => true,
                    'lang' => true,
                    'rows' => 5,
                    'cols' => 40,
                    'hint' => $this->l('Invalid characters:').' <>;=#{}'
                ),                
                /* Add an fileupload component to the form */
                array(
                    'type' => 'file',
                    'label' => $this->l('Page image'),
                    'name' => 'CMS_IMG',
                    'desc' => $this->l('Upload an image for this page'),
                    'lang' => true,
                    'display_image' => true,
                    'image' => $image_url ? $image_url : false,
                ),                
                array(
                    'type' => 'radio',
                    'label' => $this->l('Displayed:'),
                    'name' => 'active',
                    'required' => false,
                    'class' => 't',
                    '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')
                        )
                    ),
                ),
            ),
            'submit' => array(
                'title' => $this->l('   Save   '),
                'class' => 'button'
            )
        );
        if (Shop::isFeatureActive())
        {
            $this->fields_form['input'][] = array(
                'type' => 'shop',
                'label' => $this->l('Shop association:'),
                'name' => 'checkBoxShopAsso',
            );
        }
        $this->tpl_form_vars = array(
            'active' => $this->object->active
        );
        return AdminControllerCore::renderForm();
    }

    public function postProcess()
    {
        $languages = Language::getLanguages(false);
        $update_images_values = false;

        foreach ($languages as $lang)
        {
            if (isset($_FILES['CMS_IMG'])
                && isset($_FILES['CMS_IMG']['tmp_name'])
                && !empty($_FILES['CMS_IMG']['tmp_name']))
            {
                if ($error = ImageManager::validateUpload($_FILES['CMS_IMG'], 4000000))
                    return $error;
                else
                {
                    $ext = substr($_FILES['CMS_IMG']['name'], strrpos($_FILES['CMS_IMG']['name'], '.') + 1);
                    $file_name = md5($_FILES['CMS_IMG']['name']).'.'.$ext;

                    if (!move_uploaded_file($_FILES['CMS_IMG']['tmp_name'],
                        _PS_IMG_DIR_ .'cms'.DIRECTORY_SEPARATOR.$file_name))
                        return Tools::displayError($this->l('An error occurred while attempting to upload the file.'));
                    else
                    {
                        $values['CMS_IMG'][$lang['id_lang']] = $file_name;
                    }
                }

                $update_images_values = true;
                $cms = new CMS((int)Tools::getValue('id_cms'));
                $cms->CMS_IMG = $file_name;
                $cms->update();
            }
        }

        parent::postProcess();
    }

    public function getImageValue()
    {
        $db = Db::getInstance();
        $sql = 'SELECT CMS_IMG FROM '._DB_PREFIX_.'cms_lang WHERE id_cms = ' . $this->object->id;
        return $db->getValue($sql);
    }
}

      

Step 3. Injecting code for the frontend



Override 'controllers / front / CmsController.php' to 'override / controllers / front / CmsController.php'

class CmsController extends CmsControllerCore
{

    /**
     * Assign template vars related to page content
     * @see CmsControllerCore::initContent()
     */
    public function initContent()
    {
        if(!empty($this->cms->CMS_IMG)) {
            $this->context->smarty->assign('cms_image', _PS_IMG_ . 'cms/' . $this->cms->CMS_IMG);
        }

        parent::initContent();
    }
}

      

Step 4, use your image in the template

Now you can, for example, in cms.tpl use the following code:

{if $cms_image != ''}
    <img src="{$cms_image}">
{/if}

      


Based on: https://www.prestashop.com/forums/topic/141903-add-custom-field-to-cms-module/

+6


source


Adding all of this as a separate answer, as some moderators seem to reject even the simplest fix / change to the original answer: "This change deviates from the original intent of posting" or "This change was intended to respond to the author's post" .. right.


Improving response to 11mb

Step 0, please note that the new field needs to be added manually to the SQL table (use SQL structure edit or PhpMyAdmin):

ALTER TABLE `ps_cms_lang` ADD `CMS_IMG` TEXT NULL DEFAULT NULL;

      

Step 1.2, the class cache file must be deleted for the changes to be active:

/cache/class_index.php

      

Step 4, use an image in your template
..
Or a more generic form (also used in category subpages - use an attribute CMS_IMG

( ->

or .

depends on the code):

{if isset($cms->CMS_IMG) && $cms->CMS_IMG}
    <img src="{$img_ps_dir}/cms/{$cms->CMS_IMG}">
{/if}

      




1. For a non-multilingual field, make the following settings:

ALTER TABLE `ps_cms` ADD `CMS_IMG` TEXT NULL DEFAULT NULL;

'CMS_IMG' =>   array('type' => self::TYPE_STRING, 'lang' => false, ..

'lang' => false,

$sql = 'SELECT CMS_IMG FROM '._DB_PREFIX_.'cms WHERE id_cms = ' . $this->object->id;

      

+ And remove all these things in postProcess()


2. Several fixes before postProcess()


  • the code does not save data correctly - should not be used $cms->update();

    as postProcess()

    an exception trigger when adding a new page, because of incomplete data = just set the value $_POST['CMS_IMG']

    .
  • should generate a unique filename (starting with id) for each page.
  • should check isSubmit to avoid processing in the wrong chain (if same field name is used in CMS categories).

Updated code:

public function postProcess()
{
    if ( (Tools::isSubmit('submitAddcms') || Tools::isSubmit('viewcms'))
        && isset($_FILES['CMS_IMG'])
        && isset($_FILES['CMS_IMG']['tmp_name'])
        && !empty($_FILES['CMS_IMG']['tmp_name']))
    {
        $id = (int)Tools::getValue('id_cms');

        if ($error = ImageManager::validateUpload($_FILES['CMS_IMG'], 4000000))
            return $error;
        else
        {
            $ext = substr($_FILES['CMS_IMG']['name'], strrpos($_FILES['CMS_IMG']['name'], '.') + 1);
            $file_name = $id .'_cms_'. md5($_FILES['CMS_IMG']['name']).'.'.$ext;

            if (!move_uploaded_file($_FILES['CMS_IMG']['tmp_name'],
                _PS_IMG_DIR_.'cms'.DIRECTORY_SEPARATOR.$file_name))
                return Tools::displayError($this->l('An error occurred while attempting to upload the file.'));
            else {
                $_POST['CMS_IMG'] = $file_name;
                @chmod(_PS_IMG_DIR_.'cms'.DIRECTORY_SEPARATOR.$file_name, 0666);
            }
        }
    }

    parent::postProcess();
}

      

+3


source


The above solutions are simply not in line with the PrestaShop philosophy.

Adding a display image for the CMS page should mimic existing mecanisms (see creating / publishing categories or vendor logo).

The following is my solution working in PrestaShop 1.6.1.7. It will add an image field, upload the image to img / cms folder and create all the thumbnails.

I haven't figured out how to remove the image yet, you are more than welcome to comment on my answer. Be careful when updating PrestaShop, files from the overridden folder may be updated.

1 / Add the following to define.inc.php (after line 137):

define('_PS_CMS_IMG_DIR_', _PS_IMG_DIR_.'cms/');

      

2 / Add the following to define_uri.inc.php (after line 61):

define('_THEME_CMS_DIR_', _PS_IMG_.'cms/');

      

3 / Add rules to .htaccess file :

RewriteRule ^cms/([0-9]+)(\-[\.*_a-zA-Z0-9-]*)(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/cms/$1$2$3.jpg [L]
RewriteRule ^cms/([a-zA-Z_-]+)(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/cms/$1$2.jpg [L]

      

4 / Override classes / CMS.php before override /classes/CMS.php :

<?php
class CMS extends CMSCore
{    
    // Add an id_image attribute to allow further tests in cms.tpl
    public $id_image = 'default';

    public function __construct($id = null, $id_lang = null, $id_shop = null)
    {
        parent::__construct($id, $id_lang, $id_shop);
        $this->id_image = ($this->id && file_exists(_PS_CMS_IMG_DIR_.(int)$this->id.'.jpg')) ? (int)$this->id : false;
        $this->image_dir = _PS_CMS_IMG_DIR_;
    }
}
?>

      

5 / override classes /ImageType.php in override /classes/ImageType.php

  • Add public class to class: public $cms

  • Add to $definition=>fields

    :'cms' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool')

  • In getByNameNType add to $types

    var:'cms'

6 / Override classes /Link.php before override /classes/Link.php :

class Link extends LinkCore
{
    public function getCmsImageLink($name, $id_cms, $type = null)
    {
        if ($this->allow == 1 && $type) {
            $uri_path = __PS_BASE_URI__.'cms/'.$id_cms.'-'.$type.'/'.$name.'.jpg';
        } else {
            $uri_path = _THEME_CAT_DIR_.$id_cms.($type ? '-'.$type : '').'.jpg';
        }
        return $this->protocol_content.Tools::getMediaServer($uri_path).$uri_path;
    }
}

      

7 / Override controllers /AdminCmsController.php to override / controllers / AdminCmsController.php :

  • Add the following __contruct method, right before parent :: __ construct ():

    $this->fieldImageSettings = array(
        'name' => 'banner_img',
        'dir' => 'cms',
    );
    
          

  • Add the following postProcess method just after line 351 (in one of the elseif blocks, find the condition for submitAddcms and submitAddcmsAndPreview):

    $object = $this->loadObject();
    $image_is_posted = $this->postImage($object->id);
    if (! $image_is_posted) {
        throw new PrestaShopException("image not posted...");
    }
    
          

  • In the renderForm method, start with:

    if (!($obj = $this->loadObject(true))) {
        return;
    }
    
    $image = _PS_CMS_IMG_DIR_.$obj->id.'.jpg';
    $image_url = ImageManager::thumbnail($image, $this->table.'_'.$obj->id.'.'.$this->imageType, 350,
        $this->imageType, true, true);
    
    $image_size = file_exists($image) ? filesize($image) / 1000 : false;
    
    if (Validate::isLoadedObject($this->object)) {
        $this->display = 'edit';
    } else {
        $this->display = 'add';
    }
    
          

and add the following to the attribute $this->fields_form

, for example after the content field:

array(
    'type' => 'file',
    'label' => $this->l('Banner image'),
    'name' => 'banner_img',
    'display_image' => true,
    'image' => $image_url ? $image_url : false,
    'size' => $image_size,
    'hint' => $this->l('Upload a banner image from your computer.')
)

      

  • Add and afterImageUpload:

    protected function afterImageUpload () {$ return = true; $ generate_hight_dpi_images = (bool) Configuration :: get ('PS_HIGHT_DPI');

    $object = $this->loadObject(true);
    
    /* Generate image with differents size */
    if (($object->id = (int)Tools::getValue('id_cms')) &&
         isset($_FILES) && count($_FILES) && file_exists(_PS_CMS_IMG_DIR_.$object->id.'.jpg')) {
        $images_types = ImageType::getImagesTypes('cms');
        foreach ($images_types as $k => $image_type) {
            $file = _PS_CMS_IMG_DIR_.$object->id.'.jpg';
            if (!ImageManager::resize($file, _PS_CMS_IMG_DIR_.$object->id.'-'.stripslashes($image_type['name']).'.jpg', (int)$image_type['width'], (int)$image_type['height'])) {
                $return = false;
            }
    
            if ($generate_hight_dpi_images) {
                if (!ImageManager::resize($file, _PS_CMS_IMG_DIR_.$object->id.'-'.stripslashes($image_type['name']).'2x.jpg', (int)$image_type['width']*2, (int)$image_type['height']*2)) {
                    $return = false;
                }
            }
        }
    
        $current_logo_file = _PS_CMS_IMG_DIR_.'cms_mini_'.$object->id.'_'.$this->context->shop->id.'.jpg';
    
        if (file_exists($current_logo_file)) {
            unlink($current_logo_file);
        }
    }
    return $return;
    }
    
          

8 / Override controllers /admin/AdminImagesController.php to override / controllers / admin / AdminImagesController.php

  • In the __construct method add to $ this-> fields_list: 'cms' => array('title' => $this->l('CMS'), 'align' => 'center', 'type' => 'bool', 'callback' => 'printEntityActiveIcon', 'orderby' => false)

  • In the method __contruct

    add to $this->fields_form=>input

    :

    array(
        'type' => 'switch',
        'label' => $this->l('Pages CMS'),
        'name' => 'cms',
        'required' => false,
        'is_bool' => true,
        'hint' => $this->l('This type will be used for CMS banner images.'),
        'values' => array(
            array(
                'id' => 'cms_on',
                'value' => 1,
                'label' => $this->l('Enabled')
            ),
            array(
                'id' => 'cms_off',
                'value' => 0,
                'label' => $this->l('Disabled')
            ),
        )
    ),
    
          

  • In initRegenerate

    , add to $types

    var:'cms' => $this->l('CMS pages')

  • In the method _regenerateThumbnails

    add to the array $process

    :array('type' => 'cms', 'dir' => _PS_CMS_IMG_DIR_)

9 / Update your CMS page template cms.tpl something like this:

<!-- Check out the default theme category_header.tpl for original PrestaShop code -->
<div class="cms_banner"{if $cms->id_image} style="background:url({$link->getCmsImageLink($cms->link_rewrite, $cms->id_image, 'large')|escape:'html':'UTF-8'}) right center no-repeat; background-size:cover; "{/if}>
    <div class="container">
        <!-- Your content here -->
    </div>
</div>

      

+2


source


 // add one image per page        
    'CMS_IMG' =>   array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isString', 'size' => 3999999999999),  ),

 Above argument can not create a field on cms_lang table.

 So system can gives the following error

 Unknown column 'cms_image' in 'field list'

 if ($webservice_call && $errno) {
        $dbg = debug_backtrace();
         WebserviceRequest::getInstance()->setError(500, '[SQL Error] '.$this->getMsgError().'. From '.(isset($dbg[3]['class']) ? $dbg[3]['class'] : '').'->'.$dbg[3]['function'].'() Query was : '.$sql, 97);
     } elseif (_PS_DEBUG_SQL_ && $errno && !defined('PS_INSTALLATION_IN_PROGRESS')) {
         if ($sql) {
             throw new PrestaShopDatabaseException($this->getMsgError().'<br /><br /><pre>'.$sql.'</pre>');
         }

         throw new PrestaShopDatabaseException($this->getMsgError());
     }
 }

      

0


source


To prevent image loss when updating data. (This has been added since 1.7) I suggest the following improvement to the postProcess method:

public function postProcess()
{
    $languages = Language::getLanguages(false);
    $update_images_values = false;
    $cms = new CMS((int)Tools::getValue('id_cms'));

    foreach ($languages as $lang)
    {
        if (isset($_FILES['CMS_IMG'])
            && isset($_FILES['CMS_IMG']['tmp_name'])
            && !empty($_FILES['CMS_IMG']['tmp_name']))
        {
            if ($error = ImageManager::validateUpload($_FILES['CMS_IMG'], 4000000))
                return $error;
            else
            {
                $ext = substr($_FILES['CMS_IMG']['name'], strrpos($_FILES['CMS_IMG']['name'], '.') + 1);
                $file_name = md5($_FILES['CMS_IMG']['name']).'.'.$ext;

                if (!move_uploaded_file($_FILES['CMS_IMG']['tmp_name'],
                    _PS_IMG_DIR_ .'cms'.DIRECTORY_SEPARATOR.$file_name))
                    return Tools::displayError($this->l('An error occurred while attempting to upload the file.'));
                else
                {
                    $values['CMS_IMG'][$lang['id_lang']] = $file_name;
                }
            }

            $update_images_values = true;
            $cms->CMS_IMG = $file_name;
            $cms->update();
        }
        else
        {
            $_POST['CMS_IMG'] = $cms->CMS_IMG;
        }
    }

    self::saveProducts();
    parent::postProcess();
}

      

This adds another condition to the original

0


source







All Articles