HelperForm and checkbox in Prestashop - php

I try to add checkbox to my module config for PrestaShop 1.5. I use HelperForm as in manual but there is empty $helper->fields_value
public function getContent()
{
$output = null;
if (Tools::isSubmit('submit'.$this->name))
{
$fast_email = strval(Tools::getValue('fast_email'));
if (!$fast_email || empty($fast_email) || !Validate::isGenericName($fast_email))
$output .= $this->displayError( $this->l('Invalid Configuration value') );
else
{
Configuration::updateValue('fast_email', $fast_email);
$output .= $this->displayConfirmation($this->l('Settings updated'));
}
$fast_email_sender = strval(Tools::getValue('fast_email_sender'));
if ( !Validate::isGenericName($fast_email_sender))
$output .= $this->displayError( $this->l('Invalid Configuration value') );
else
{
Configuration::updateValue('fast_email_sender', $fast_email_sender);
$output .= $this->displayConfirmation($this->l('Settings updated'));
}
$fast_phone = strval(Tools::getValue('fast_phone'));
Configuration::updateValue('fast_phone', $fast_phone);
var_dump(Tools::getValue('fast_phone'));
$output .= $this->displayConfirmation($this->l('Settings updated'));
}
return $output.$this->displayForm();
}
public function displayForm()
{
// Get default Language
$default_lang = (int)Configuration::get('PS_LANG_DEFAULT');
$options = array(
array(
'id_option' => 1, // The value of the 'value' attribute of the <option> tag.
'name' => 'email' // The value of the text content of the <option> tag.
),
array(
'id_option' => 2,
'name' => 'phone'
),
);
// var_dump($options);
// Init Fields form array
$fields_form[0]['form'] = array(
'legend' => array(
'title' => $this->l('Settings'),
),
'input' => array(
array(
'type' => 'text',
'label' => $this->l('admin email'),
'name' => 'fast_email',
'size' => 20,
'required' => true
)
,
array(
'type' => 'checkbox', // This is an <input type="checkbox"> tag.
'label' => $this->l('Options'), // The <label> for this <input> tag.
'desc' => $this->l('Choose options.'), // A help text, displayed right next to the <input> tag.
'name' => 'fast_phone', // The content of the 'id' attribute of the <input> tag.
'values' => array(
'query' => $options, // $options contains the data itself.
'id' => 'id_option', // The value of the 'id' key must be the same as the key for 'value' attribute of the <option> tag in each $options sub-array.
'name' => 'name' // The value of the 'name' key must be the same as the key for the text content of the <option> tag in each $options sub-array.
),
),
array(
'type' => 'radio',
'label' => $this->l('email'),
'name' => 'fast_email_sender', // The content of the 'id' attribute of the <input> tag.
'required' => true,
'class' => 't',
'values' => array( // $values contains the data itself.
array(
'id' => 'active_on', // The content of the 'id' attribute of the <input> tag, and of the 'for' attribute for the <label> tag.
'value' => 1, // The content of the 'value' attribute of the <input> tag.
'label' => $this->l('Enabled') // The <label> for this radio button.
),
array(
'id' => 'active_off',
'value' => 0,
'label' => $this->l('Disabled')
)
),
)
),
'submit' => array(
'title' => $this->l('Save'),
'class' => 'button'
)
);
$helper = new HelperForm();
// Module, t oken and currentIndex
$helper->module = $this;
$helper->name_controller = $this->name;
$helper->token = Tools::getAdminTokenLite('AdminModules');
$helper->currentIndex = AdminController::$currentIndex.'&configure='.$this->name;
// Language
$helper->default_form_language = $default_lang;
$helper->allow_employee_form_lang = $default_lang;
// Title and toolbar
$helper->title = $this->displayName;
$helper->show_toolbar = true; // false -> remove toolbar
$helper->toolbar_scroll = true; // yes - > Toolbar is always visible on the top of the screen.
$helper->submit_action = 'submit'.$this->name;
$helper->toolbar_btn = array(
'save' =>
array(
'desc' => $this->l('Save'),
'href' => AdminController::$currentIndex.'&configure='.$this->name.'&save'.$this->name.
'&token='.Tools::getAdminTokenLite('AdminModules'),
),
'back' => array(
'href' => AdminController::$currentIndex.'&token='.Tools::getAdminTokenLite('AdminModules'),
'desc' => $this->l('Back to list')
)
);
// Load current value
$helper->fields_value['fast_email'] = Configuration::get('fast_email');
$helper->fields_value['fast_email_sender'] = Configuration::get('fast_email_sender');
$helper->fields_value['fast_phone'] = Configuration::get('fast_phone');
return $helper->generateForm($fields_form);
}
I add in install Configuration::updateValue('fast_phone','') when I checked it and save it doesn't update. I check config and it empty before and after submit

I know this theat is old but for others i give the solution :
According to documentation, the getContent method has to be written like that :
public function getContent()
{
$output = null;
// Save settings values
if (Tools::isSubmit('submit'.$this->name)) // Check if form is submitted
{
Configuration::updateValue('MODULE_OPTION1', Tools::getValue('MODULE_OPTION1'));
Configuration::updateValue('MODULE_OPTION2', Tools::getValue('MODULE_OPTION2'));
Configuration::updateValue('MODULE_OPTION3', Tools::getValue('MODULE_OPTION3'));
$output .= $this->displayConfirmation($this->l('Settings updated'));
}
return $output.$this->displayForm();
}
Of course it can be improved : checking values...

Related

How to combine a fields_list + .tpl view in 1 admincontroller?

I can't figure out how to display, in my custom admin controller, 1 fields_list + content of a .tpl file. The goal is to display my product keys in stock + some extra features below (content from a tpl file).
I can display either the fields list OR the message from the .tpl file. But not combined... I found a tutorial online and this comes very close, but not working.
<?php
require_once(_PS_MODULE_DIR_ . 'avanto_key/classes/AvantoStock.php');
class AdminAvantokeyStockController extends ModuleAdminController
{
protected $position_identifier = 'id_avanto_keys';
public function __construct()
{
//$this->fields_form = $this->fieldForm();
$this->bootstrap = true;
$this->table = 'avanto_keys'; // DB table name where your object data stored
$this->className = "AvantoStock"; // The class name of my object
//$this->identifier = 'id_avanto_keys';
//$this->list_id = 'id_avanto_keys';
$this->_defaultOrderBy = 'id_avanto_keys';
//$this->lang = FALSE;
$this->addRowAction('edit');
$this->addRowAction('delete');
$this->bulk_actions = array('delete' => array('text' => $this->l('Delete selected'),
'confirm' => $this->l('Delete selected items?')), );
//Shop::addTableAssociation($this->table, array('type' => 'shop'));
parent::__construct();
$this->_select = 'pl.`name` as product_name, a.`serial_key` as serial_display';
$this->_join = 'LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON (pl.`id_product` = a.`id_product` AND pl.`id_lang`
= '.(int)$this->context->language->id.')';
}
public function renderView()
{
$tpl = $this->context->smarty->createTemplate(
dirname(__FILE__).
'/../../views/templates/admin/view.tpl');
return $tpl->fetch();
}
public function renderList()
{
$this->toolbar_title = $this->l('Stock Management');
$this->toolbar_btn['new'] = null;
$this->fields_list = array(
'id_avanto_keys' => array(
'title' => $this->l('ID Key'),
'width' => 140,
),
'id_product' => array(
'title' => $this->l('Product ID'),
'width' => 140,
),
'serial_key' => array(
'title' => $this->l('Serial Keys'),
'width' => 140,
),
'product_name' => array(
'title' => $this->l('Product Name'),
'width' => 140,
),
);
return parent::renderList();
}
public function init()
{
parent::init();
}
public function initContent()
{
$this->context->smarty->assign(array(
'form' => $form,
'base_dir' => _PS_MODULE_DIR_,
));
$this->setTemplate('stock.tpl');
$lists = parent::initContent();
$this->renderList();
$lists .= parent::initContent();
return $lists;
}
public function renderForm()
{
$this->display = 'edit';
$this->initToolbar();
$this->fields_form = array(
'tinymce' => true,
'legend' => array(
'title' => $this->l('Edit product key'),
),
'input' => array(
array(
'type' => 'text',
'label' => $this->l('Key ID'),
'name' => 'id_product',
),
array(
'type' => 'text',
'label' => $this->l('Product ID'),
'name' => 'id_avanto_keys',
),
array(
'type' => 'text',
'label' => $this->l('Serial Key'),
'required' => true,
'name' => 'serial_key',
),
),
'submit' => array(
'title' => $this->l('Save'),
'class' => 'btn btn-default pull-right'
)
);
return parent::renderForm();
}
}
?>
The code above only displays the message hello world and not my product listing.
Anyone has an idea how to combine this?
Thanks in advance!!!
It's a little bit confused, we have to make some tidy :):
First:
The fields of the list it's better to declare in the __construct so:
public function __construct()
{
$this->module = 'YourModuleName'; // Here you have to put your module name
$this->bootstrap = true;
$this->table = 'avanto_keys'; // DB table name where your object data stored
$this->className = "AvantoStock"; // The class name of my object
//$this->identifier = 'id_avanto_keys';
//$this->list_id = 'id_avanto_keys';
$this->_defaultOrderBy = 'id_avanto_keys';
//$this->lang = FALSE;
$this->explicitSelect = true; // This if you do a select manually after
$this->addRowAction('edit');
$this->addRowAction('delete');
$this->bulk_actions = array('delete' => array('text' => $this->l('Delete selected'),
'confirm' => $this->l('Delete selected items?')), );
//Shop::addTableAssociation($this->table, array('type' => 'shop'));
$this->_select = 'pl.`name` as product_name, a.`serial_key` as serial_display';
$this->_join = 'LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON (pl.`id_product` = a.`id_product` AND pl.`id_lang`
= '.(int)$this->context->language->id.')';
$this->fields_list = array(
'id_avanto_keys' => array(
'title' => $this->l('ID Key'),
'width' => 140,
),
'id_product' => array(
'title' => $this->l('Product ID'),
'width' => 140,
),
'serial_key' => array(
'title' => $this->l('Serial Keys'),
'width' => 140,
),
'product_name' => array(
'title' => $this->l('Product Name'),
'width' => 140,
),
);
parent::__construct();
}
Second
The parent renderList method make other stuff, let's separate that from what do you want to display:
public function renderList()
{
// Here we retrieve the list (without doing any strange thing)
$list = parent::renderList();
// Assign some vars to pass to our custom tpl
$this->context->smarty->assign(
array(
'var1' => "Test",
'var2' => "Test2"
)
);
// Get the custom tpl rendered
$content = $this->context->smarty->fetch(_PS_MODULE_DIR_ . "avanto_key/views/templates/admin/avantokeystock/customcontent.tpl");
// return the list plus your content
return $list . $content;
}
Third
Leave the parent initContent as is, do not override, because he make a lot of stuffs
I guess that is a great point to start :)
Try this way and let me know ;)

Render helper form from prestashop admin controller

I am trying to add a helper form that lets the user upload images for two languages that the user can select.
However I am stuck with the form and cannot render it in the view. Here is my controller code:
<?php
class AdminWineoHeaderImgController extends ModuleAdminController
{
public function __construct()
{
$this->bootstrap = true;
$this->lang = (!isset($this->context->cookie) ||
!is_object($this->context->cookie)) ? intval(Configuration::get('PS_LANG_DEFAULT')) : intval($this->context->cookie->id_lang);
parent::__construct();
}
public function display()
{
parent::display();
}
public function renderList()
{
$this->renderForm();
$return = $this->context->smarty->fetch(_PS_MODULE_DIR_.'wineoheaderimg/views/templates/hook/adminwineoimg.tpl');
return $return;
}
public function renderForm()
{
$fields_form = array(
'form' => array(
'legend' => array(
'title' => $this->module->l('Wineo Header Img Configuration'),
'icon' => 'icon-envelope',
),
'input' => array(
array(
'type' => 'file',
'label' => $this->module->l('Add images'),
'name' => 'enable_grades',
'id' => 'uploadwineoheaderimg',
'required' => false,
'desc' => $this->module->l('Choose images that will appear on the front page.'),
),
array(
'type' => 'select',
'label' => $this->l('Languages:'),
'name' => 'category',
'required' => true,
'options' => array(
'query' => $options = array(
array(
'id_option' => 1, // The value of the 'value' attribute of the <option> tag.
'name' => 'EN', // The value of the text content of the <option> tag.
),
array(
'id_option' => 2,
'name' => 'BG',
),
),
'id' => 'id_option',
'name' => 'name',
),
),
),
'submit' => array('title' => $this->module->l('Save')),
),
);
$helper = new HelperForm();
$helper->table = 'wineoheaderimg';
$helper->default_form_language = (int) Configuration::get('PS_LANG_DEFAULT');
$helper->allow_employee_form_lang = (int) Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG');
$helper->submit_action = 'wineo_header_img_pc_form';
$helper->currentIndex = $this->context->link->getAdminLink('AdminModules', false).'&configure='.$this->module->name.'&tab_module='.$this->module->tab.'&module_name='.$this->module->name;
$helper->token = Tools::getAdminTokenLite('AdminModules');
$helper->tpl_vars = array(
'fields_value' => array(
'wineo_header_img' => Tools::getValue('enable_grades', Configuration::get('WINEO_HEADER_IMG')),
),
'languages' => $this->context->controller->getLanguages(),
);
return $helper->generateForm(array($fields_form));
}
}
Where should I call the method renderForm()? I have tried in the admin hooks and basically everywhere I could imagine.
Any help will be appreciated!
Well you are calling renderForm() inside renderList(), (I assume you want the form to display by default when you open controller page) but you don't assign the form to template.
public function renderList()
{
$form = $this->renderForm();
// To load form inside your template
$this->context->smarty->assign('form_tpl', $form);
return $this->context->smarty->fetch(_PS_MODULE_DIR_.'wineoheaderimg/views/templates/hook/adminwineoimg.tpl');
// To return form html only
return $form;
}
So if you want the form inside your adminwineoimg.tpl
{* Some HTML *}
{$form_tpl}
{* Some HTML *}

PrestaShop: How to remove 'new' button from my backoffice controller

I want to remove the add button from the bo list view toolbar in prestashop is there any way ,(only for my page which I created as a seperate module
or atleast when I click the add button it must not do anything .
require_once(_PS_MODULE_DIR_.'addsocialmedia/addsocialmedia.php');
require_once(_PS_MODULE_DIR_.'addsocialmedia/classes/SocialMedia.php');
class AdminAddSocialMediaController extends ModuleAdminController
{
public $module;
public $html;
public $tabName = 'renderForm';
public function __construct()
{
$this->tab = 'socialmedia';
$this->module = new addsocialmedia();
$this->addRowAction('edit');
$this->explicitSelect = false;
$this->context = Context::getContext();
$this->id_lang = $this->context->language->id;
$this->lang = false;
$this->ajax = 1;
$this->path = _MODULE_DIR_.'addsocialmedia';
$this->default_form_language = $this->context->language->id;
$this->table = _DB_KITS_PREFIX_.'social_media';
$this->className = 'SocialMedia';
$this->identifier = 'id_social_media';
$this->allow_export = true;
$this->_select = '
id_social_media,
name_social_media,
social_media_url,
status
';
$this->name = 'SocialMedia';
$this->bootstrap = true;
$this->initList();
parent::__construct();
}
private function initList()
{
$this->fields_list =
array(
'id_social_media' => array(
'title' => $this->l('Social Media ID'),
'width' => 25,
'type' => 'text',
),
'name_social_media' => array(
'title' => $this->l('Social Media Name'),
'width' => 140,
'type' => 'text',
),
'social_media_url' => array(
'title' => $this->l('Social Media Url'),
'width' => 140,
'type' => 'text',
),
'status' => array(
'title' => $this->l('Enabled'),
'align' => 'text-center',
'status' => 'status',
'type' => 'bool',
'orderby' => false,
'callback' => 'changeStatus',
),
);
$helper = new HelperList();
$helper->shopLinkType = '';
$helper->simple_header = true;
// Actions to be displayed in the "Actions" column
$helper->actions = array('edit');
$helper->identifier = 'code';
$helper->show_toolbar = true;
$helper->title = 'HelperList';
$helper->table = $this->name.'check';
$helper->token = Tools::getAdminTokenLite('AdminModules');
$helper->currentIndex = AdminController::$currentIndex.'&configure='.$this->name;
return $helper;
}
public function initPageHeaderToolbar()
{
$this->page_header_toolbar_title = $this->l('Edit Social Media Image and url/link');
parent::initPageHeaderToolbar();
}
public function initToolbar()
{
parent::initToolbar();
$this->context->smarty->assign('toolbar_scroll', 1);
$this->context->smarty->assign('show_toolbar', 1);
$this->context->smarty->assign('toolbar_btn', $this->toolbar_btn);
}
public function postProcess()
{
parent::postProcess();
$id = (int)Tools::getValue('id_social_media');
$file = Tools::fileAttachment('social_media_image_name');
if (!empty($file['name']) && $id > 0)
{
if (ImageManager::validateUpload($file, Tools::convertBytes(ini_get('upload_max_filesize'))))
die('Image size exceeds limit in your Bigticket Back Office settings');
if (!is_dir('../modules/addsocialmedia/social_media_img'))
#mkdir('../modules/addsocialmedia/social_media_img', 0777, true);
if (!is_dir('../modules/addsocialmedia/social_media_img/'.$id))
#mkdir('../modules/addsocialmedia/social_media_img/'.$id, 0777, true);
$path = '../modules/addsocialmedia/social_media_img/'.$id.'/';
$absolute_path = $path.$file['name'];
move_uploaded_file($file['tmp_name'], $absolute_path);
$imgPath = 'social_media_img/'.$id.'/'.$file['name'];
//Save in DB if needed
Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.''._DB_KITS_PREFIX_.'social_media`
SET `social_media_image_name` = "'.pSQL($imgPath).'"
WHERE `id_social_media` = '.(int)$id);
}
if (Tools::isSubmit('changeStatusVal') && $this->id_object) {
if ($this->tabAccess['edit'] === '1') {
$this->action = 'change_status_val';
d("chnage");
} else {
$this->errors[] = Tools::displayError('You do not have permission to change this.');
}
}
}
//Call back for change status
public function changeStatus($value, $socialMedia)
{
return '<a class="list-action-enable '.($value ? 'action-enabled' : 'action-disabled').'" href="index.php?'.htmlspecialchars('tab=AdminAddSocialMedia&id_social_media='
.(int)$socialMedia['id_social_media'].'&changeStatusVal&token='.Tools::getAdminTokenLite('AdminAddSocialMedia')).'">
'.($value ? '<i class="icon-check"></i>' : '<i class="icon-remove"></i>').
'</a>';
}
/**
* Toggle the Social media to Enabled or Disabled flag- Here the update action occurs
*/
public function processChangeStatusVal()
{
d("hii");
$socialMedia = new SocialMedia($this->id_object);
if (!Validate::isLoadedObject($socialMedia)) {
$this->errors[] = Tools::displayError('An error occurred while updating the Status .');
}
d("going to change");
$socialMedia->status = $socialMedia->status ? 0 : 1;
if (!$socialMedia->update()) {
$this->errors[] = Tools::displayError('An error occurred while updating Social Media Status .');
}
Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token);
}
//When a winner is deleted , delete the image
public function processDelete()
{
$ob=parent::processDelete();
PrestaShopLogger::addLog(sprintf($this->l('%s DELETED social media IMAGE', 'AdminTab', false, false), $this->className), 1, null, $this->className, (int)$id, true, (int)$this->context->employee->id);
if ($ob->deleted==1){
$id = (int)Tools::getValue('id_social_media');
$unlink_path = '../modules/addsocialmedia/social_media_img/'.$id.'/';
unlink($unlink_path); // this must delete the img folder from the winners module dir
//log the delete
PrestaShopLogger::addLog(sprintf($this->l('%s DELETED social media IMAGE', 'AdminTab', false, false), $this->className), 1, null, $this->className, (int)$id, true, (int)$this->context->employee->id);
}
}
//If the user updates the image delete the old image from server
public function processUpdate(){
//d("updating..");
$id = (int)Tools::getValue('id_social_media');
$file = Tools::fileAttachment('social_media_image_name');
if (!empty($file['name']) && $id > 0)
{
$get_previous_image_sql = 'SELECT social_media_image_name FROM `'._DB_PREFIX_._DB_KITS_PREFIX_.'social_media`
where id_social_media='.$id.'';
$get_previous_image_path = Db::getInstance()->getValue($get_previous_image_sql) ;
//d($get_previous_image_path);
$unlink_path = '../modules/addsocialmedia/'.$get_previous_image_path.'';
unlink($unlink_path); // this must delete the img folder from the winners module dir
//log the delete when deleting
PrestaShopLogger::addLog(sprintf($this->l('%s DELETED social media IMAGE while updating new image', 'AdminTab', false, false), $this->className), 1, null, $this->className, (int)$id, true, (int)$this->context->employee->id);
}
}
// This form is populated when add or edit is clicked
public function renderForm()
{
$firstArray =
array(array(
'type' => 'text',
'label' => $this->l('Name'),
'name' => 'name_social_media',
'required' => true,
'col' => '4',
'hint' => $this->l('Invalid characters:').' 0-9!<>,;?=+()##"°{}_$%:'
),
array(
'type' => 'text',
'label' => $this->l('Social Media URL'),
'name' => 'social_media_url',
'required' => true,
'col' => '4',
'hint' => $this->l('Invalid characters:').' 0-9!<>,;?=+()##"°{}_$%:'
),
array(
'type' => 'file',
'label' => $this->l('Social Media Image'),
'name' => 'social_media_image_name',
'display_image' => true,
'required' => false,
'desc' => $this->l('Add .JPG or .PNG File Format.Prefered Width:381 pixels and Height 285 pixels.Prefered File size -50KB .'),
'hint' => array(
$this->l('Add .JPG or .PNG File Format.Prefered Width:381 pixels and Height 285 pixels.Prefered File size -50KB .')
)
),
array(
'type' => 'switch',
'label' => $this->l('Enable Or Disable this Social Media'),
'name' => 'status',
'required' => false,
'class' => 't',
'is_bool' => true,
'values' => array(
array(
'id' => 'status_on',
'value' => 1,
'label' => $this->l('Enabled')
),
array(
'id' => 'status_off',
'value' => 0,
'label' => $this->l('Disabled')
)
),
'hint' => $this->l('Enable or disable this Social Media From front END.')
),
);
if (Tools::getIsset('addkits_social_media') ){
$secondArray = array(
array(
'type' => 'hidden',
'label' => $this->l('Add Date'),
'name' => 'date_add',
'col' => '4',
'values'=>date("Y-m-d H:i:s"),
'hint' => $this->l('Invalid characters:').' 0-9!<>,;?=+()##"°{}_$%:'
),
array(
'type' => 'hidden',
'label' => $this->l('Winner Image Name'),
'name' => 'social_media_image_name',
'col' => '4',
'values'=>"default_value"
)
);
$mainArray = array_merge($firstArray,$secondArray);
}
if (Tools::getIsset('updatekits_social_media') ){
$thirdArray = array(
array(
'type' => 'hidden',
'label' => $this->l('Update Date'),
'name' => 'date_upd',
'col' => '4',
'values'=>date("Y-m-d H:i:s"),
'hint' => $this->l('Invalid characters:').' 0-9!<>,;?=+()##"°{}_$%:'
),
array(
'type' => 'hidden',
'label' => $this->l('Winner Image Name'),
'name' => 'social_media_image_name',
'col' => '4',
'values'=>"default_value"
));
$mainArray = array_merge($firstArray,$thirdArray);
}
$this->fields_form = array(
'tinymce' => true,
'legend' => array(
'title' => $this->l('Configure your Social Media Image and URL'),
'icon' => 'icon-user'
),
'input' => $mainArray
);
//Assign value to hidden
$this->fields_value['date_add'] = $date = date("Y-m-d H:i:s");
$this->fields_value['social_media_image_name'] ="default_image.jpg";
$this->fields_form['submit'] = array(
'title' => $this->l('Save'),
);
$date = date("Y-m-d H:i:s");
$this->addJqueryUI('ui.datepicker');
return parent::renderForm();
}
You have to override the initToolbar method:
public function initToolbar() {
parent::initToolbar();
unset( $this->toolbar_btn['new'] );
}
Cheers ;)
Yes it is at the helper of your module. Could you put the code of the page so I am indicating or remove. Otherwise solution less "clean" applied CSS to hide this button.
Regards,

PrestaShop FormHelper preload multilanguage values

here I am seeing a small problem, I have two tables template and template_text, in template table I store the template type and visibility data and in the template_text table I store the template text in many languages, atm. I have two langs. such as EN and DE. So, when I am editing the template I preload the current template values into the form, but there is a problem with the values like autoemailer_title and autoemailer_body, when the from helper generates the form field it is generating this fields this way autoemailer_title_1, autoemailer_title_2 according the language ID, so, the question would be how to preload all this values the right way? I could use javascript and ajax get request to get the values and then set them by using the input ID, but I think there is a better way using the form helper.
$fields_form = array(
'form' => array(
'legend' => array(
'title' => $this->l($params['title']),
'icon' => 'icon-cogs'
),
'input' => array(
array(
'type' => 'select', // This is a <select> tag.
'label' => $this->l('Template type'), // The <label> for this <select> tag.
'desc' => $this->l('Choose a template type'), // A help text, displayed right next to the <select> tag.
'name' => 'autoemailer_type', // The content of the 'id' attribute of the <select> tag.
'required' => true, // If set to true, this option must be set.
'options' => array(
'query' => array(
array(
'id_option' => 'static', // The value of the 'value' attribute of the <option> tag.
'name' => 'Static' // The value of the text content of the <option> tag.
),
array(
'id_option' => 'dynamic',
'name' => 'Dynamic'
),
), // $options contains the data itself.
'id' => 'id_option', // The value of the 'id' key must be the same as the key for 'value' attribute of the <option> tag in each $options sub-array.
'name' => 'name' // The value of the 'name' key must be the same as the key for the text content of the <option> tag in each $options sub-array.
)
),
array(
'type' => 'text',
'label' => $this->l('News letter title'),
'name' => 'autoemailer_title',
'desc' => $this->l('Title'),
'lang' => true,
// 'style' => 'width:300px',
'class' => 'fixed-width-lg',
),
array(
'type' => 'textarea',
'label' => $this->l('Text'),
'name' => 'autoemailer_body',
'desc' => $this->l('Email body'),
'lang' => true,
'cols' => 60,
'rows' => 10,
'class' => 'rte', // we need this for setuping the tiny mce editor
'autoload_rte' => true, // we need this for setuping the tiny mce editor
),
),
'submit' => array(
'title' => $this->l('Save')
)
)
);
$helper = new HelperForm();
$helper->show_toolbar = false;
$helper->table = $this->table;
$lang = new Language((int)Configuration::get('PS_LANG_DEFAULT'));
$helper->default_form_language = $lang->id;
$helper->allow_employee_form_lang = Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG') ? Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG') : 0;
$this->fields_form = array();
$helper->identifier = $this->identifier;
$helper->submit_action = 'newTemplate';
$helper->currentIndex = $this->getThisUrl() . '&emailer_action=main';
$helper->token = Tools::getAdminTokenLite('AdminModules');
return $helper->generateForm(array($fields_form));
Solved this one. So, when we have more than one lang then the attribute for which we apply the multilangiage option becomes an array, so to set the value according the language we can just do this way :
$lang_id = 1; // setting the language ID, usually it's done by foreaching the records from ps_lang table
$helper->fields_value['description'][$lang_id] = 'my default value'; // setting the default value
return $helper->generateForm(array($fields_form)); // returning the output of generated form

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.
I couldn't find any codes/modules which support this feature in 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. This approach is not the most elegant way to implement this in PrestaShop, but I hope it helps you to move forward.
Step 1, Update the model so it can 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, Implement the code needed to upload the image in the backoffice:
Override 'controllers/admin/AdminCmsController.php' in '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, Implement the code for the frontend
Overide 'controllers/front/CmsController.php' in '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, e.g. 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/
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
Step 0, Note that new field needs to be manually added in SQL table (use SQL or PhpMyAdmin structure edit):
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:
/cache/class_index.php
Step 4, use your image in the template
..
Or more universal form (also usable in category subpages - use CMS_IMG attribute (-> or . depends on code):
{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:
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()
2. Multiple fixes to postProcess()
code does not correctly save data - should not use $cms->update(); in postProcess() as triggers exception on adding new page, due partial data = just set $_POST['CMS_IMG'] value..
should generate unique filename (start with id) for each page.
should check for isSubmit to avoid processing in wrong chain (if same field name 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();
}
The above solutions just do not fit with PrestaShop's philosophy.
Adding a featured image for a CMS page should mimic existing mecanisms (see creation/edition of categories or suppliers logo).
Following is my solution, working for PrestaShop 1.6.1.7. It will add an image field, upload image to img/cms folder and create all thumbnails.
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.
1/ Add the following to defines.inc.php (after line 137):
define('_PS_CMS_IMG_DIR_', _PS_IMG_DIR_.'cms/');
2/ Add the following to defines_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 to 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 to override/classes/ImageType.php
Add a public attribute to the class: public $cms
Append to $definition=>fields: 'cms' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool')
In getByNameNType, append to $types var: 'cms'
6/ Override classes/Link.php to 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:
Append the following to the __contruct method, right before 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):
$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 append 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 method:
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, append to $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:
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')
In the _regenerateThumbnails method, append to $process array: array('type' => 'cms', 'dir' => _PS_CMS_IMG_DIR_)
9/ Update your CMS page template cms.tpl with something like this:
<!-- 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>
To prevent the loose of the image when you're updating the datas. (This appends with the 1.7) I suggest the following improvement in 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();
}
That adds an else condition to the original one
// 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());
}
}

Categories