简体   繁体   English

如何在Prestashop中为CMS页面添加特色图像

[英]How to add a featured image for CMS page in Prestashop

I want to add an image from back-end for each CMS page I'm adding in Prestashop, just like we add featured images for posts/page in Wordpress. 我想在后端为我在Prestashop中添加的每个CMS页面添加一个图像,就像我们在Wordpress中为帖子/页面添加特色图像一样。

I couldn't find any codes/modules which support this feature in prestashop. 我在prestashop中找不到任何支持此功能的代码/模块。

It is possible, but it isn't straightforward. 这是可能的,但并不简单。 Here are the steps you need to do to implement image upload to the CMS page module. 以下是将图像上载到CMS页面模块所需执行的步骤。 This approach is not the most elegant way to implement this in PrestaShop, but I hope it helps you to move forward. 这种方法不是在PrestaShop中实现这一点的最优雅的方法,但我希望它可以帮助您前进。

Step 1, Update the model so it can contain the image: 步骤1,更新模型,使其包含图像:

First override 'classes/CMS.php' to 'override/classes/CMS.php'. 首先将'classes / CMS.php'覆盖为'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, Implement the code needed to upload the image in the backoffice: 步骤2,实现在后台上传图像所需的代码:

Override 'controllers/admin/AdminCmsController.php' in 'override/controllers/admin/AdminCmsController.php' 覆盖'override / controllers / admin / AdminCmsController.php'中的'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, Implement the code for the frontend 第3步,实现前端的代码

Overide 'controllers/front/CmsController.php' in 'override/controllers/front/CmsController.php' 覆盖'override / controllers / front / CmsController.php'中的'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 第4步,在模板中使用您的图像

Now you can, eg in cms.tpl use the following code: 现在你可以,例如在cms.tpl中使用以下代码:

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

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

Adding all these as separate answer, since some moderators seem to reject even most simplest fix/change to original answer as " This edit deviates from the original intent of the post " or " This edit was intended to address the author of the post " ..right. 将所有这些添加为单独的答案,因为一些主持人似乎拒绝最简单的修复/更改为原始答案为“ 此编辑偏离帖子的原始意图 ”或“ 此编辑旨在解决帖子的作者 ”。 。对。


Improving answer by 11mb 提高答案11mb

Step 0, Note that new field needs to be manually added in SQL table (use SQL or PhpMyAdmin structure edit): 步骤0,注意需要在SQL表中手动添加新字段(使用SQL或PhpMyAdmin结构编辑):

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

Step 1.2, Class cache file needs to be deleted for changes to be active: 步骤1.2,需要删除类缓存文件以使更改生效:

/cache/class_index.php

Step 4, use your image in the template 第4步,在模板中使用您的图像
.. ..
Or more universal form (also usable in category subpages - use CMS_IMG attribute ( -> or . depends on code): 或者更通用的表单(也可用于类别子页面 - 使用CMS_IMG属性( ->.取决于代码):

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

1. For a non-multiligual field - make these adjustments: 1.对于非多语言领域 - 进行以下调整:

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 that lang stuff in postProcess() +并删除postProcess()中的所有lang内容


2. Multiple fixes to postProcess() 2.对postProcess()多个修复

  • code does not correctly save data - should not use $cms->update(); 代码没有正确保存数据 - 不应该使用$cms->update(); in postProcess() as triggers exception on adding new page, due partial data = just set $_POST['CMS_IMG'] value.. postProcess()作为触发器添加新页面的异常,因为部分数据=只需设置$_POST['CMS_IMG']值..
  • should generate unique filename (start with id) for each page. 应该为每个页面生成唯一的文件名(以id开头)。
  • should check for isSubmit to avoid processing in wrong chain (if same field name used in CMS categories). 应检查isSubmit以避免在错误的链中处理(如果CMS类别中使用相同的字段名称)。

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();
}

The above solutions just do not fit with PrestaShop's philosophy. 上述解决方案不符合PrestaShop的理念。

Adding a featured image for a CMS page should mimic existing mecanisms (see creation/edition of categories or suppliers logo). 为CMS页面添加特色图像应模仿现有的机制(请参阅类别或供应商徽标的创建/编辑)。

Following is my solution, working for PrestaShop 1.6.1.7. 以下是我的解决方案,适用于PrestaShop 1.6.1.7。 It will add an image field, upload image to img/cms folder and create all thumbnails. 它将添加一个图像字段,将图像上传到img / cms文件夹并创建所有缩略图。

I did not figure out how to delete the image yet, you are more than welcome to comment my answer. 我还没弄清楚如何删除图像,非常欢迎你评论我的回答。 Be careful when updating PrestaShop, files out of the override folder may be updated. 更新PrestaShop时要小心,可能会更新覆盖文件夹之外的文件。

1/ Add the following to defines.inc.php (after line 137): 1 /将以下内容添加到defines.inc.php (第137行之后):

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

2/ Add the following to defines_uri.inc.php (after line 61): 2 /将以下内容添加到defines_uri.inc.php (第61行之后):

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

3/ Add rules to .htaccess file: 3 /添加规则到.htaccess文件:

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 to override/classes/CMS.php : 4 /覆盖classes / CMS.php覆盖/ 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 to override/classes/ImageType.php 5 /覆盖classes / ImageType.php覆盖/ classes / ImageType.php

  • Add a public attribute to the class: public $cms 向该类添加一个公共属性: public $cms

  • Append to $definition=>fields : 'cms' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool') 附加到$definition=>fields'cms' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool')

  • In getByNameNType, append to $types var: 'cms' 在getByNameNType中,附加到$types var: 'cms'

6/ Override classes/Link.php to override/classes/Link.php : 6 /覆盖类/ Link.php覆盖/ 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 : 7 /覆盖controllers / AdminCmsController.php覆盖/ controllers / AdminCmsController.php

  • Append the following to the __contruct method, right before parent::__construct(): 将以下内容附加到__contruct方法,就在parent :: __ construct()之前:

     $this->fieldImageSettings = array( 'name' => 'banner_img', 'dir' => 'cms', ); 
  • Append the following to the postProcess method, right after line 351 (in one of the elseif blocks, look for a condition on submitAddcms and submitAddcmsAndPreview): 将以下内容附加到postProcess方法,紧接在第351行之后(在其中一个elseif块中,查找submitAddcms和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: 在renderForm方法中,从以下开始:

     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 append the following to the attribute $this->fields_form , for example after the content field: 并将以下内容附加到属性$this->fields_form ,例如在content字段之后:

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 method: 添加和afterImageUpload方法:

    protected function afterImageUpload() { $return = true; protected function afterImageUpload(){$ return = true; $generate_hight_dpi_images = (bool)Configuration::get('PS_HIGHT_DPI'); $ 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 8 /覆盖controllers / admin / AdminImagesController.php覆盖/ controllers / admin / AdminImagesController.php

  • In the __construct method, append to $this->fields_list: 'cms' => array('title' => $this->l('CMS'), 'align' => 'center', 'type' => 'bool', 'callback' => 'printEntityActiveIcon', 'orderby' => false) 在__construct方法中,追加到$ this-> fields_list: 'cms' => array('title' => $this->l('CMS'), 'align' => 'center', 'type' => 'bool', 'callback' => 'printEntityActiveIcon', 'orderby' => false)

  • In the __contruct method, append to $this->fields_form=>input : __contruct方法中,追加到$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 method, append to $types var: 'cms' => $this->l('CMS pages') initRegenerate方法中,附加到$types var: 'cms' => $this->l('CMS pages')

  • In the _regenerateThumbnails method, append to $process array: array('type' => 'cms', 'dir' => _PS_CMS_IMG_DIR_) _regenerateThumbnails方法中,附加到$process array: array('type' => 'cms', 'dir' => _PS_CMS_IMG_DIR_)

9/ Update your CMS page template cms.tpl with something like this: 9 /使用以下内容更新CMS页面模板cms.tpl

<!-- Check out the default theme's 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>
 // 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());
     }
 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM