prestashop overriding and combination - overriding
Hi all I have a question regarding the topic, prestashop 1.6.
I added a custom date field on the on the information page:
let's call it "customfield", and it works fine, I can fill a DATE and prestashop stores in the database.
Now I want the same field to be added in the combinations, each combination can have the same or different or null customfield value.
This is what I did regarding combination:
created /override/controllers/admin/templates/products/combinations.tpl (located in the same folder there is a modified information.tpl);
<div class="form-group">
<label class="control-label col-lg-3" for="attribute_customfield">
{l s='Customfield'}
</label>
<div class="col-lg-3">
<input maxlength="12" type="date" id="attribute_customfield" name="attribute_customfield" value="" />
</div>
</div>
/override/classes/Combination.php
class Combination extends CombinationCore
{
public $customfield;
/**
* #see ObjectModel::$definition
*/
public static $definition = array(
'table' => 'product_attribute',
'primary' => 'id_product_attribute',
'fields' => array(
'id_product' => array('type' => self::TYPE_INT, 'shop' => 'both', 'validate' => 'isUnsignedId', 'required' => true),
'location' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'size' => 64),
'ean13' => array('type' => self::TYPE_STRING, 'validate' => 'isEan13', 'size' => 13),
'upc' => array('type' => self::TYPE_STRING, 'validate' => 'isUpc', 'size' => 12),
'quantity' => array('type' => self::TYPE_INT, 'validate' => 'isInt', 'size' => 10),
'reference' => array('type' => self::TYPE_STRING, 'size' => 32),
'supplier_reference' => array('type' => self::TYPE_STRING, 'size' => 32),
/* Shop fields */
'wholesale_price' => array('type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isPrice', 'size' => 27),
'price' => array('type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isNegativePrice', 'size' => 20),
'ecotax' => array('type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isPrice', 'size' => 20),
'weight' => array('type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isFloat'),
'unit_price_impact' => array('type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isNegativePrice', 'size' => 20),
'minimal_quantity' => array('type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedId', 'required' => true),
'default_on' => array('type' => self::TYPE_BOOL, 'allow_null' => true, 'shop' => true, 'validate' => 'isBool'),
'available_date' => array('type' => self::TYPE_DATE, 'shop' => true, 'validate' => 'isDateFormat'),
/*added*/
'customfield' => array('type' => self::TYPE_DATE, 'validate' => 'isDateFormat'),
),
);
}
/override/classes/Product.php
class Product extends ProductCore
{
public $second_reference;
public $customfield;
public function __construct($id_product = null, $full = false, $id_lang = null, $id_shop = null, Context $context = null)
{
self::$definition['fields']['second_reference'] = array('type' => self::TYPE_STRING, 'validate' => 'isString');
self::$definition['fields']['customfield'] = array('type' => self::TYPE_DATE, 'validate' => 'isDateFormat');
parent::__construct($id_product, $full, $id_lang, $id_shop);
}
/**
* #param int $quantity DEPRECATED
* #param string $supplier_reference DEPRECATED
*/
public function addCombinationEntity($wholesale_price, $price, $weight, $unit_impact, $ecotax, $quantity,
$id_images, $reference, $id_supplier, $ean13, $customfield, $default, $location = null, $upc = null, $minimal_quantity = 1, array $id_shop_list = array(), $available_date = null)
{
$id_product_attribute = $this->addAttribute(
$price, $weight, $unit_impact, $ecotax, $id_images,
$reference, $ean13, $customfield, $default, $location, $upc, $minimal_quantity, $id_shop_list, $available_date);
$this->addSupplierReference($id_supplier, $id_product_attribute);
$result = ObjectModel::updateMultishopTable('Combination', array(
'wholesale_price' => (float)$wholesale_price,
), 'a.id_product_attribute = '.(int)$id_product_attribute);
if (!$id_product_attribute || !$result)
return false;
return $id_product_attribute;
}
/**
* Update a product attribute
*
*/
public function updateAttribute($id_product_attribute, $wholesale_price, $price, $weight, $unit, $ecotax,
$id_images, $reference, $ean13, $customfield, $default, $location = null, $upc = null, $minimal_quantity = null, $available_date = null, $update_all_fields = true, array $id_shop_list = array())
{
$combination = new Combination($id_product_attribute);
if (!$update_all_fields)
$combination->setFieldsToUpdate(array(
'price' => !is_null($price),
'wholesale_price' => !is_null($wholesale_price),
'ecotax' => !is_null($ecotax),
'weight' => !is_null($weight),
'unit_price_impact' => !is_null($unit),
'default_on' => !is_null($default),
'minimal_quantity' => !is_null($minimal_quantity),
'available_date' => !is_null($available_date),
));
$price = str_replace(',', '.', $price);
$weight = str_replace(',', '.', $weight);
$combination->price = (float)$price;
$combination->wholesale_price = (float)$wholesale_price;
$combination->ecotax = (float)$ecotax;
$combination->weight = (float)$weight;
$combination->unit_price_impact = (float)$unit;
$combination->reference = pSQL($reference);
$combination->location = pSQL($location);
$combination->ean13 = pSQL($ean13);
$combination->customfield = pSQL($customfield);
$combination->upc = pSQL($upc);
$combination->default_on = (int)$default;
$combination->minimal_quantity = (int)$minimal_quantity;
$combination->available_date = $available_date ? pSQL($available_date) : '0000-00-00';
if (count($id_shop_list))
$combination->id_shop_list = $id_shop_list;
$combination->save();
if (is_array($id_images) && count($id_images))
$combination->setImages($id_images);
$id_default_attribute = (int)Product::updateDefaultAttribute($this->id);
if ($id_default_attribute)
$this->cache_default_attribute = $id_default_attribute;
// Sync stock Reference, EAN13 and UPC for this attribute
if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && StockAvailable::dependsOnStock($this->id, Context::getContext()->shop->id))
Db::getInstance()->update('stock', array(
'reference' => pSQL($reference),
'ean13' => pSQL($ean13),
'customfield' => pSQL($customfield),
'upc' => pSQL($upc),
), 'id_product = '.$this->id.' AND id_product_attribute = '.(int)$id_product_attribute);
Hook::exec('actionProductAttributeUpdate', array('id_product_attribute' => (int)$id_product_attribute));
Tools::clearColorListCache($this->id);
return true;
}
/**
* Add a product attribute
* #since 1.5.0.1
*
* #param float $price Additional price
* #param float $weight Additional weight
* #param float $ecotax Additional ecotax
* #param int $id_images Image ids
* #param string $reference Reference
* #param string $location Location
* #param string $ean13 Ean-13 barcode
* #param bool $default Is default attribute for product
* #param int $minimal_quantity Minimal quantity to add to cart
* #return mixed $id_product_attribute or false
*/
public function addAttribute($price, $weight, $unit_impact, $ecotax, $id_images, $reference, $ean13, $customfield,
$default, $location = null, $upc = null, $minimal_quantity = 1, array $id_shop_list = array(), $available_date = null)
{
if (!$this->id)
return;
$price = str_replace(',', '.', $price);
$weight = str_replace(',', '.', $weight);
$combination = new Combination();
$combination->id_product = (int)$this->id;
$combination->price = (float)$price;
$combination->ecotax = (float)$ecotax;
$combination->quantity = 0;
$combination->weight = (float)$weight;
$combination->unit_price_impact = (float)$unit_impact;
$combination->reference = pSQL($reference);
$combination->location = pSQL($location);
$combination->ean13 = pSQL($ean13);
$combination->customfield = pSQL($customfield);
$combination->upc = pSQL($upc);
$combination->default_on = (int)$default;
$combination->minimal_quantity = (int)$minimal_quantity;
$combination->available_date = $available_date;
if (count($id_shop_list))
$combination->id_shop_list = array_unique($id_shop_list);
$combination->add();
if (!$combination->id)
return false;
$total_quantity = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('
SELECT SUM(quantity) as quantity
FROM '._DB_PREFIX_.'stock_available
WHERE id_product = '.(int)$this->id.'
AND id_product_attribute <> 0 '
);
if (!$total_quantity)
Db::getInstance()->update('stock_available', array('quantity' => 0), '`id_product` = '.$this->id);
$id_default_attribute = Product::updateDefaultAttribute($this->id);
if ($id_default_attribute)
{
$this->cache_default_attribute = $id_default_attribute;
if (!$combination->available_date)
$this->setAvailableDate();
}
if (!empty($id_images))
$combination->setImages($id_images);
Tools::clearColorListCache($this->id);
if (Configuration::get('PS_DEFAULT_WAREHOUSE_NEW_PRODUCT') != 0 && Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT'))
{
$warehouse_location_entity = new WarehouseProductLocation();
$warehouse_location_entity->id_product = $this->id;
$warehouse_location_entity->id_product_attribute = (int)$combination->id;
$warehouse_location_entity->id_warehouse = Configuration::get('PS_DEFAULT_WAREHOUSE_NEW_PRODUCT');
$warehouse_location_entity->location = pSQL('');
$warehouse_location_entity->save();
}
return (int)$combination->id;
}
/**
* Get all available attribute groups
*
* #param int $id_lang Language id
* #return array Attribute groups
*/
public function getAttributesGroups($id_lang)
{
if (!Combination::isFeatureActive())
return array();
$sql = 'SELECT ag.`id_attribute_group`, ag.`is_color_group`, agl.`name` AS group_name, agl.`public_name` AS public_group_name,
a.`id_attribute`, al.`name` AS attribute_name, a.`color` AS attribute_color, product_attribute_shop.`id_product_attribute`,
IFNULL(stock.quantity, 0) as quantity, product_attribute_shop.`price`, product_attribute_shop.`ecotax`, product_attribute_shop.`weight`,
product_attribute_shop.`default_on`, pa.`reference`, pa.`customfield`, product_attribute_shop.`unit_price_impact`,
product_attribute_shop.`minimal_quantity`, product_attribute_shop.`available_date`, ag.`group_type`
FROM `'._DB_PREFIX_.'product_attribute` pa
'.Shop::addSqlAssociation('product_attribute', 'pa').'
'.Product::sqlStock('pa', 'pa').'
LEFT JOIN `'._DB_PREFIX_.'product_attribute_combination` pac ON (pac.`id_product_attribute` = pa.`id_product_attribute`)
LEFT JOIN `'._DB_PREFIX_.'attribute` a ON (a.`id_attribute` = pac.`id_attribute`)
LEFT JOIN `'._DB_PREFIX_.'attribute_group` ag ON (ag.`id_attribute_group` = a.`id_attribute_group`)
LEFT JOIN `'._DB_PREFIX_.'attribute_lang` al ON (a.`id_attribute` = al.`id_attribute`)
LEFT JOIN `'._DB_PREFIX_.'attribute_group_lang` agl ON (ag.`id_attribute_group` = agl.`id_attribute_group`)
'.Shop::addSqlAssociation('attribute', 'a').'
WHERE pa.`id_product` = '.(int)$this->id.'
AND al.`id_lang` = '.(int)$id_lang.'
AND agl.`id_lang` = '.(int)$id_lang.'
GROUP BY id_attribute_group, id_product_attribute
ORDER BY ag.`position` ASC, a.`position` ASC, agl.`name` ASC';
return Db::getInstance()->executeS($sql);
}
/**
* Get product attribute combination by id_product_attribute
* #return array Product attribute combination by id_product_attribute
*/
public function getAttributeCombinationsById($id_product_attribute, $id_lang)
{
if (!Combination::isFeatureActive())
return array();
$sql = 'SELECT pa.*, product_attribute_shop.*, ag.`id_attribute_group`, ag.`is_color_group`, agl.`name` AS group_name, al.`name` AS attribute_name,
a.`id_attribute`
FROM `'._DB_PREFIX_.'product_attribute` pa
'.Shop::addSqlAssociation('product_attribute', 'pa').'
LEFT JOIN `'._DB_PREFIX_.'product_attribute_combination` pac ON pac.`id_product_attribute` = pa.`id_product_attribute`
LEFT JOIN `'._DB_PREFIX_.'attribute` a ON a.`id_attribute` = pac.`id_attribute`
LEFT JOIN `'._DB_PREFIX_.'attribute_group` ag ON ag.`id_attribute_group` = a.`id_attribute_group`
LEFT JOIN `'._DB_PREFIX_.'attribute_lang` al ON (a.`id_attribute` = al.`id_attribute` AND al.`id_lang` = '.(int)$id_lang.')
LEFT JOIN `'._DB_PREFIX_.'attribute_group_lang` agl ON (ag.`id_attribute_group` = agl.`id_attribute_group` AND agl.`id_lang` = '.(int)$id_lang.')
WHERE pa.`id_product` = '.(int)$this->id.'
AND pa.`id_product_attribute` = '.(int)$id_product_attribute.'
GROUP BY pa.`id_product_attribute`, ag.`id_attribute_group`
ORDER BY pa.`id_product_attribute`';
$res = Db::getInstance()->executeS($sql);
//Get quantity of each variations
foreach ($res as $key => $row)
{
$cache_key = $row['id_product'].'_'.$row['id_product_attribute'].'_quantity';
if (!Cache::isStored($cache_key))
{
$result = StockAvailable::getQuantityAvailableByProduct($row['id_product'], $row['id_product_attribute']);
Cache::store(
$cache_key,
$result
);
$res[$key]['quantity'] = $result;
}
else
$res[$key]['quantity'] = Cache::retrieve($cache_key);
}
return $res;
}
}
/override/controllers/front/ProductController.php
class ProductController extends ProductControllerCore
{
/**
* Assign template vars related to attribute groups and colors
*/
protected function assignAttributesGroups()
{
$colors = array();
$groups = array();
// #todo (RM) should only get groups and not all declination ?
$attributes_groups = $this->product->getAttributesGroups($this->context->language->id);
if (is_array($attributes_groups) && $attributes_groups)
{
$combination_images = $this->product->getCombinationImages($this->context->language->id);
$combination_prices_set = array();
foreach ($attributes_groups as $k => $row)
{
// Color management
if (isset($row['is_color_group']) && $row['is_color_group'] && (isset($row['attribute_color']) && $row['attribute_color']) || (file_exists(_PS_COL_IMG_DIR_.$row['id_attribute'].'.jpg')))
{
$colors[$row['id_attribute']]['value'] = $row['attribute_color'];
$colors[$row['id_attribute']]['name'] = $row['attribute_name'];
if (!isset($colors[$row['id_attribute']]['attributes_quantity']))
$colors[$row['id_attribute']]['attributes_quantity'] = 0;
$colors[$row['id_attribute']]['attributes_quantity'] += (int)$row['quantity'];
}
...
}
}
/override/controllers/admin/AdminProductsController.php
<?php
class AdminProductsController extends AdminProductsControllerCore
{
public function processProductAttribute()
{
// Don't process if the combination fields have not been submitted
if (!Combination::isFeatureActive() || !Tools::getValue('attribute_combination_list'))
return;
if (Validate::isLoadedObject($product = $this->object))
{
if ($this->isProductFieldUpdated('attribute_price') && (!Tools::getIsset('attribute_price') || Tools::getIsset('attribute_price') == null))
$this->errors[] = Tools::displayError('The price attribute is required.');
if (!Tools::getIsset('attribute_combination_list') || Tools::isEmpty(Tools::getValue('attribute_combination_list')))
$this->errors[] = Tools::displayError('You must add at least one attribute.');
$array_checks = array(
'reference' => 'isReference',
'supplier_reference' => 'isReference',
'location' => 'isReference',
'ean13' => 'isEan13',
'upc' => 'isUpc',
'wholesale_price' => 'isPrice',
'price' => 'isPrice',
'ecotax' => 'isPrice',
'quantity' => 'isInt',
'weight' => 'isUnsignedFloat',
'unit_price_impact' => 'isPrice',
'default_on' => 'isBool',
'minimal_quantity' => 'isUnsignedInt',
'available_date' => 'isDateFormat'
);
foreach ($array_checks as $property => $check)
if (Tools::getValue('attribute_'.$property) !== false && !call_user_func(array('Validate', $check), Tools::getValue('attribute_'.$property)))
...
$this->isProductFieldUpdated('attribute_ecotax') ? Tools::getValue('attribute_ecotax') : null,
Tools::getValue('id_image_attr'),
Tools::getValue('attribute_reference'),
Tools::getValue('attribute_ean13'),
Tools::getValue('customfield'),
$this->isProductFieldUpdated('attribute_default') ? Tools::getValue('attribute_default') : null,
Tools::getValue('attribute_location'),
Tools::getValue('attribute_upc'),
$this->isProductFieldUpdated('attribute_minimal_quantity') ? Tools::getValue('attribute_minimal_quantity') : null,
$this->isProductFieldUpdated('available_date_attribute') ? Tools::getValue('available_date_attribute') : null, false);
StockAvailable::setProductDependsOnStock((int)$product->id, $product->depends_on_stock, null, (int)$id_product_attribute);
StockAvailable::setProductOutOfStock((int)$product->id, $product->out_of_stock, null, (int)$id_product_attribute);
}
}
else
$this->errors[] = Tools::displayError('You do not have permission to add this.');
}
// Add new
else
{
if ($this->tabAccess['add'] === '1')
{
if ($product->productAttributeExists(Tools::getValue('attribute_combination_list')))
$this->errors[] = Tools::displayError('This combination already exists.');
else
{
$id_product_attribute = $product->addCombinationEntity(
Tools::getValue('attribute_wholesale_price'),
Tools::getValue('attribute_price') * Tools::getValue('attribute_price_impact'),
Tools::getValue('attribute_weight') * Tools::getValue('attribute_weight_impact'),
Tools::getValue('attribute_unity') * Tools::getValue('attribute_unit_impact'),
Tools::getValue('attribute_ecotax'),
0,
Tools::getValue('id_image_attr'),
Tools::getValue('attribute_reference'),
null,
Tools::getValue('attribute_ean13'),
Tools::getValue('attribute_default'),
Tools::getValue('attribute_location'),
Tools::getValue('customfield'),
...
}
}
}
/**
* #param Product $product
* #throws Exception
* #throws SmartyException
*/
public function initFormInformations($product)
{
if (!$this->default_form_language)
$this->getLanguages();
$data = $this->createTemplate($this->tpl_form);
$currency = $this->context->currency;
$data->assign(array(
'languages' => $this->_languages,
'default_form_language' => $this->default_form_language,
'currency' => $currency
));
$this->object = $product;
//$this->display = 'edit';
$data->assign('product_name_redirected', Product::getProductName((int)$product->id_product_redirected, null, (int)$this->context->language->id));
/*
* Form for adding a virtual product like software, mp3, etc...
*/
$product_download = new ProductDownload();
if ($id_product_download = $product_download->getIdFromIdProduct($this->getFieldValue($product, 'id')))
$product_download = new ProductDownload($id_product_download);
$product->{'productDownload'} = $product_download;
$product_props = array();
// global informations
array_push($product_props, 'reference', 'ean13', 'customfield', 'upc',
'available_for_order', 'show_price', 'online_only',
'id_manufacturer'
);
// specific / detailled information
array_push($product_props,
// physical product
'width', 'height', 'weight', 'active',
// virtual product
'is_virtual', 'cache_default_attribute',
// customization
'uploadable_files', 'text_fields'
);
// prices
array_push($product_props,
'price', 'wholesale_price', 'id_tax_rules_group', 'unit_price_ratio', 'on_sale',
'unity', 'minimum_quantity', 'additional_shipping_cost',
'available_now', 'available_later', 'available_date'
);
...
}
/**
* #param Product $product
* #param Currency|array|int $currency
* #return string
*/
public function renderListAttributes($product, $currency)
{
$this->bulk_actions = array('delete' => array('text' => $this->l('Delete selected'), 'confirm' => $this->l('Delete selected items?')));
$this->addRowAction('edit');
$this->addRowAction('default');
$this->addRowAction('delete');
$default_class = 'highlighted';
$this->fields_list = array(
'attributes' => array('title' => $this->l('Attribute - value pair'), 'align' => 'left'),
'price' => array('title' => $this->l('Impact on price'), 'type' => 'price', 'align' => 'left'),
'weight' => array('title' => $this->l('Impact on weight'), 'align' => 'left'),
'reference' => array('title' => $this->l('Reference'), 'align' => 'left'),
'ean13' => array('title' => $this->l('EAN-13'), 'align' => 'left'),
'upc' => array('title' => $this->l('UPC'), 'align' => 'left')
);
if ($product->id)
{
/* Build attributes combinations */
$combinations = $product->getAttributeCombinations($this->context->language->id);
$groups = array();
$comb_array = array();
if (is_array($combinations))
{
$combination_images = $product->getCombinationImages($this->context->language->id);
foreach ($combinations as $k => $combination)
{
$price_to_convert = Tools::convertPrice($combination['price'], $currency);
$price = Tools::displayPrice($price_to_convert, $currency);
$comb_array[$combination['id_product_attribute']]['id_product_attribute'] = $combination['id_product_attribute'];
$comb_array[$combination['id_product_attribute']]['attributes'][] = array($combination['group_name'], $combination['attribute_name'], $combination['id_attribute']);
$comb_array[$combination['id_product_attribute']]['wholesale_price'] = $combination['wholesale_price'];
$comb_array[$combination['id_product_attribute']]['price'] = $price;
$comb_array[$combination['id_product_attribute']]['weight'] = $combination['weight'].Configuration::get('PS_WEIGHT_UNIT');
$comb_array[$combination['id_product_attribute']]['unit_impact'] = $combination['unit_price_impact'];
$comb_array[$combination['id_product_attribute']]['reference'] = $combination['reference'];
$comb_array[$combination['id_product_attribute']]['ean13'] = $combination['ean13'];
$comb_array[$combination['id_product_attribute']]['customfield'] = $combination['customfield'];
$comb_array[$combination['id_product_attribute']]['upc'] = $combination['upc'];
$comb_array[$combination['id_product_attribute']]
...
}
}
/js/admin/product.js
function editProductAttribute (url, parent){
$.ajax({...
success: function(data) {
// color the selected line
parent.siblings().removeClass('selected-line');
parent.addClass('selected-line');
$('#add_new_combination').show();
$('#attribute_quantity').show();
$('#product_att_list').html('');
self.removeButtonCombination('update');
scroll_if_anchor('#add_new_combination');
var wholesale_price = Math.abs(data[0]['wholesale_price']);
var price = data[0]['price'];
var weight = data[0]['weight'];
var unit_impact = data[0]['unit_price_impact'];
var reference = data[0]['reference'];
var ean = data[0]['ean13'];
//MIO
var customfield = data[0]['customfield'];
.....
.....
self.fillCombination(
wholesale_price,
price,
weight,
unit_impact,
reference,
ean,
customfield,
...
);
/**AND LATER**/
this.fillCombination = function(wholesale_price, price_impact, weight_impact, unit_impact, reference,
ean, customfield, quantity, image, old_attr, id_product_attribute, default_attribute, eco_tax, upc, minimal_quantity, available_date)
{
var link = '';
self.init_elems();
$('#stock_mvt_attribute').show();
$('#initial_stock_attribute').hide();
...
getE('attribute_customfield').value = customfield;
These are all the files i overrided and modified
Of course it doesn't work, it doesn't save info into the db correctly, sometimes if the one in information is set the it copies that one instead.
What I did wrong? And what should I do instead
Related
How can I use php mpdf, can not Chinese garbled code?
This is my php code, use dPdf, But the PDF I got was garbled in Chinese,like this: I tried many methods, but they didn't work, My MPDF version is 8.0.8, php verson is v7.4 <?php $defaultConfig = (new ConfigVariables())->getDefaults(); $fontDirs = $defaultConfig['fontDir']; $defaultFontConfig = (new FontVariables())->getDefaults(); $fontData = $defaultFontConfig['fontdata']; //当文件不存在,再生成 // if (!is_file($localFileUrl)) { $mpdf = new Mpdf([ // 'mode' => 'utf-8', 'mode' => '-aCJK', 'format' => 'A4', 'useSubstitutions' => true, 'useAdobeCJK' => true, 'autoScriptToLang' => true, 'autoLangToFont' => true, 'mgl' => 15, 'mgr' => 15, 'mgt' => 16, 'mgb' => 16, 'mgh' => 9, 'mgf' => 9, 'orientation' => 'P', 'fontDir' => array_merge($fontDirs, [ Yii::$app->basePath . '/fontData', ]), 'fontdata' => ArrayHelper::merge($fontData, [ //配置全局字体 'gb' => [ 'R' => 'gb.ttf', 'sip-ext' => 'gb', ], 'default_font' => 'gb' ]) ]); // $mpdf->SetFont('gb'); $mpdf->ignore_invalid_utf8 = true; $mpdf->useAdobeCJK = true; $mpdf->autoLangToFont = true; $mpdf->autoScriptToLang = true; $mpdf->SetDisplayMode('fullpage'); // 设置pdf显示方式 $mpdf->pgwidth = '240mm'; // 设置pdf的尺寸为mm*mm $authPic = Yii::$app->basePath . '/rundata/auth/auth_1.png'; $mpdf->WriteHTML("<img src='{$authPic}'>"); $mpdf->WriteText(74, 95, '中文中文');
WooCommerce - how to retrieve current orderby/sorting selection?
I need to retrieve the current order of products (as ids) on the shop page for further use. Sorting is done via the standard dropdown (date, price: low to high, price: high to low). Using $orderby, I can manage this for date and price ASC. But the value of $orderby is the same for price ASC and DESC. How can I correctly retrieve the current value for each sorting option? if ($orderby == 'date ID') { $ordertype = 'date'; $meta = ''; $order = 'desc'; } elseif ($orderby == 'price') { $ordertype = 'meta_value_num'; $meta = '_price'; $order = 'asc'; } $query = new WC_Product_Query( array( 'limit' => -1, 'orderby' => $ordertype, 'meta_key' => $meta, 'order' => $order, 'return' => 'ids', ) ); $products = $query->get_products(); print_r($products);
I think your standard dropdown needs to be in this order. HTML <select> <option value="date">Date</option> <option value="low_to_high">Low to High</option> <option value="high_to_low">High to Low</option> </select> and based on selection your condition will be. PHP <?php if ($orderby == 'low_to_high') { $ordertype = 'meta_value_num'; $meta = '_price'; $order = 'asc'; }elseif ($orderby == 'high_to_low') { $ordertype = 'meta_value_num'; $meta = '_price'; $order = 'desc'; }else{ $ordertype = 'date'; $meta = ''; $order = 'desc'; } $query = new WC_Product_Query( array( 'limit' => -1, 'orderby' => $ordertype, 'meta_key' => $meta, 'order' => $order, 'return' => 'ids', ) ); $products = $query->get_products(); print_r($products); ?>
Change order of billing fields on checkout page
I’m using the WC filter to order billing fields It seems the filter works fine, but for unknown reasons it revert back on the fly to the default order. add_filter("woocommerce_checkout_fields", "custom_order_fields"); function custom_order_fields($fields) { $order = array( "billing_first_name", "billing_last_name", "billing_country", "billing_address_1", "billing_address_2", "billing_state", "billing_city", "billing_phone", "billing_email" ); foreach($order as $field) { $ordered_fields[$field] = $fields["billing"][$field]; } $fields["billing"] = $ordered_fields; $fields['billing_first_name']['priority'] = 10; $fields['billing_last_name']['priority'] = 20; $fields['billing_country']['priority'] = 30; $fields['billing_address_1']['priority'] = 40; $fields['billing_address_2']['priority'] = 50; $fields['billing_state']['priority'] = 40; $fields['billing_city']['priority'] = 70; $fields['billing_phone']['priority'] = 80; $fields['billing_email']['priority'] = 90; return $fields; }
How about this? function custom_order_fields($fields) { $order = array( "billing_first_name", "billing_last_name", "billing_country", "billing_address_1", "billing_address_2", "billing_state", "billing_city", "billing_phone", "billing_email" ); foreach($order as $key => $field) { if (!empty($fields["billing"][$field])) $fields["billing"][$field]['priority'] = ($key + 1) * 10; } return $fields; } another solution is to build your array $order like this: function custom_order_fields($fields) { $order = array( "billing_first_name" => 10, "billing_last_name" => 20, "billing_country" => 30, "billing_address_1" => 40, "billing_address_2" => 50, "billing_state" => 60, "billing_city" => 70, "billing_phone" => 80, "billing_email" => 90 ); foreach($order as $field => $priority) { if (!empty($fields["billing"][$field])) { $fields["billing"][$field]['priority'] = $priority; } } return $fields; }
debugging WC_Shipping_Method packages
I have created an extended class out of WC_Shipping_Method and needed to debug and printout $packages in calculate_shipping method. var_dump is not showing anything on screen. Is there anyway to display the content of such variable? Another issue I noticed that $this->title is not changed, I run it first time and the shipment name is somehow become fixed! function tutsplus_shipping_method() { if ( ! class_exists( 'TutsPlus_Shipping_Method' ) ) { class TutsPlus_Shipping_Method extends WC_Shipping_Method { /** * Constructor for your shipping class * * #access public * #return void */ public function __construct() { $this->id = 'tutsplus'; $this->method_title = __( 'TutsPlus Shipping', 'tutsplus' ); $this->method_description = __( 'Custom Shipping Method for TutsPlus', 'tutsplus' ); // Availability & Countries $this->availability = 'including'; $this->countries = array( 'US', // Unites States of America 'CA', // Canada 'DE', // Germany 'GB', // United Kingdom 'IT', // Italy 'ES', // Spain 'HR' // Croatia ); $this->init(); $this->enabled = isset( $this->settings['enabled'] ) ? $this->settings['enabled'] : 'yes'; $this->title = isset( $this->settings['title'] ) ? $this->settings['title'] : __( 'TutsPlus Shipping', 'tutsplus' ); } /** * Init your settings * * #access public * #return void */ function init() { // Load the settings API $this->init_form_fields(); $this->init_settings(); // Save settings in admin if you have any defined add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) ); } /** * Define settings field for this shipping * #return void */ function init_form_fields() { $this->form_fields = array( 'enabled' => array( 'title' => __( 'Enable', 'tutsplus' ), 'type' => 'checkbox', 'description' => __( 'Enable this shipping.', 'tutsplus' ), 'default' => 'yes' ), 'title' => array( 'title' => __( 'Title', 'tutsplus' ), 'type' => 'text', 'description' => __( 'Title to be display on site', 'tutsplus' ), 'default' => __( 'TutsPlus Shipping', 'tutsplus' ) ), 'weight' => array( 'title' => __( 'Weight (kg)', 'tutsplus' ), 'type' => 'number', 'description' => __( 'Maximum allowed weight', 'tutsplus' ), 'default' => 100 ), ); } /** * This function is used to calculate the shipping cost. Within this function we can check for weights, dimensions and other parameters. * * #access public * #param mixed $package * #return void */ public function calculate_shipping( $package ) { $weight = 0; $cost = 0; $country = $package["destination"]["country"]; foreach ( $package['contents'] as $item_id => $values ) { $_product = $values['data']; $weight = $weight + $_product->get_weight() * $values['quantity']; } $weight = wc_get_weight( $weight, 'kg' ); if( $weight <= 10 ) { $cost = 0; } elseif( $weight <= 30 ) { $cost = 5; } elseif( $weight <= 50 ) { $cost = 10; } else { $cost = 20; } $countryZones = array( 'HR' => 0, 'US' => 3, 'GB' => 2, 'CA' => 3, 'ES' => 2, 'DE' => 1, 'IT' => 1 ); $zonePrices = array( 0 => 10, 1 => 30, 2 => 50, 3 => 70 ); $zoneFromCountry = $countryZones[ $country ]; $priceFromZone = $zonePrices[ $zoneFromCountry ]; $cost += $priceFromZone; $rate = array( 'id' => $this->id, 'label' => $this->title, 'cost' => $cost ); $this->add_rate( $rate ); } } } } add_action( 'woocommerce_shipping_init', 'tutsplus_shipping_method' ); function add_tutsplus_shipping_method( $methods ) { $methods[] = 'TutsPlus_Shipping_Method'; return $methods; } add_filter( 'woocommerce_shipping_methods', 'add_tutsplus_shipping_method' ); function tutsplus_validate_order( $posted ) { $packages = WC()->shipping->get_packages(); $chosen_methods = WC()->session->get( 'chosen_shipping_methods' ); if( is_array( $chosen_methods ) && in_array( 'tutsplus', $chosen_methods ) ) { foreach ( $packages as $i => $package ) { if ( $chosen_methods[ $i ] != "tutsplus" ) { continue; } $TutsPlus_Shipping_Method = new TutsPlus_Shipping_Method(); $weightLimit = (int) $TutsPlus_Shipping_Method->settings['weight']; $weight = 0; foreach ( $package['contents'] as $item_id => $values ) { $_product = $values['data']; $weight = $weight + $_product->get_weight() * $values['quantity']; } $weight = wc_get_weight( $weight, 'kg' ); if( $weight > $weightLimit ) { $message = sprintf( __( 'Sorry, %d kg exceeds the maximum weight of %d kg for %s', 'tutsplus' ), $weight, $weightLimit, $TutsPlus_Shipping_Method->title ); $messageType = "error"; if( ! wc_has_notice( $message, $messageType ) ) { wc_add_notice( $message, $messageType ); } } } } } add_action( 'woocommerce_review_order_before_cart_contents', 'tutsplus_validate_order' , 10 ); add_action( 'woocommerce_after_checkout_validation', 'tutsplus_validate_order' , 10 );
Symfony2 form type class not found
I get this error: Fatal error: Class 'DBP\InterfazIcedbpBundle\Form\Type\PreferencesIcecatType' not found in C:\xampp\htdocs\InterfaceICEDBP\src\DBP\InterfazIcedbpBundle\Controller\PreferencesIcecatController.php on line 66 I am trying to create e form clase so it is reusable and i have followed the manual. I am using symfony 2.3.4, in Windows with XAMPP I've already tried to clear the cache in both enviroments, restart apache and MariaDB, Do you have any clue? Thank you very much! I have done other type for other form I have and it works perfectly, so i think is something wrong in some where but not related with namespaces. This is my Controller, it is in the folder \src\DBP\InterfazIcedbpBundle\Controller namespace DBP\InterfazIcedbpBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use DBP\InterfazIcedbpBundle\Entity\Preicedbp\category; use DBP\InterfazIcedbpBundle\Entity\Preicedbp\supplier; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Request; use Doctrine\ORM\Mapping as ORM; use DBP\InterfazIcedbpBundle\Form\Type\PreferencesIcecatType; class PreferencesIcecatController extends Controller { public function indexAction(Request $request) { $em = $this->getDoctrine()->getManager(); $categories = $em->getRepository('DBPInterfazIcedbpBundle:Preicedbp\Category')->getAllCategories(); $categories = $em->getRepository('DBPInterfazIcedbpBundle:Preicedbp\Category')->getCategoriesJSON($categories); $suppliers = $em->getRepository('DBPInterfazIcedbpBundle:Preicedbp\Supplier')->getAllSuppliers(); $distributors = $em->getRepository('DBPInterfazIcedbpBundle:Preicedbp\Distributor')->getAllDistributors(); $distributors = $em->getRepository('DBPInterfazIcedbpBundle:Preicedbp\Distributor')->getDistributorsJSON($distributors); $query = $em->createQuery( 'SELECT c.catId FROM DBPInterfazIcedbpBundle:Preicedbp\ImpCategories c WHERE c.idImpPreferences=1 ORDER BY c.catId ASC'); $_selected = $query->getResult(); $categories_selected = ""; foreach($_selected as $cat) { $categories_selected .= $cat['catId'].","; } //$categories_selected = $em->getRepository('DBPInterfazIcedbpBundle:Category')->getCategoriesSelectedJSON($categories_selected); $query = $em->createQuery( 'SELECT c.distributorId FROM DBPInterfazIcedbpBundle:Preicedbp\ImpDistributors c WHERE c.idImpPreferences=1 ORDER BY c.distributorId ASC'); $_selected = $query->getResult(); $distributors_selected = ""; foreach($_selected as $dist) { $distributors_selected .= $dist['distributorId'].","; } $query = $em->createQuery( 'SELECT c.supplierId FROM DBPInterfazIcedbpBundle:Preicedbp\ImpSuppliers c WHERE c.idImpPreferences=1 ORDER BY c.supplierId ASC'); $_selected = $query->getResult(); $suppliers_selected = ""; foreach($_selected as $sup) { $suppliers_selected .= $sup['supplierId'].","; } $preferences = $this->getDoctrine()->getRepository('DBPInterfazIcedbpBundle:Preicedbp\ImpPreferences')->find(1); $pref_id = $preferences->getId(); $options = array('suppliers_selected'=>$suppliers_selected, 'id'=>$pref_id); $form = $this->createForm(new PreferencesIcecatType(),$options); if ($request->isMethod('POST')) { //Obtenemos los datos del formulario $form->bind($request); $datos = $form->getData(); $datos->setTypeUpdate(1); //Guardamos imp_preferences automáticamente $em->persist($datos); $em->flush(); //Recogemos las categorias, suppliers y dist que se guardan a parte $cat_selected = $form["cat_selected"]->getData(); $sup_selected = $form["sup_selected"]->getData(); $dist_selected = $form["dist_selected"]->getData(); //Primero borramos lo que hay para luego insertarlo de nuevo (así me olvido de mirar si está ya insertado o no). $query = $em->createQuery('DELETE FROM DBPInterfazIcedbpBundle:Preicedbp\ImpSuppliers c WHERE c.idImpPreferences='.$pref_id); $query->getResult(); $query = $em->createQuery('DELETE FROM DBPInterfazIcedbpBundle:Preicedbp\ImpDistributors c WHERE c.idImpPreferences='.$pref_id); $query->getResult(); $query = $em->createQuery('DELETE FROM DBPInterfazIcedbpBundle:Preicedbp\ImpCategories c WHERE c.idImpPreferences='.$pref_id); $query->getResult(); $categorias = explode(",",$cat_selected); foreach($categorias as $cat) { if(empty($cat)) continue; $conn = $em->getConnection(); $query = "INSERT INTO imp_categories VALUES($pref_id,$cat)"; $stmt = $conn->prepare($query); $stmt->execute(array()); } $fabricantes = explode(",",$sup_selected); foreach($fabricantes as $sup) { if(empty($sup)) continue; $conn = $em->getConnection(); $query = "INSERT INTO imp_suppliers VALUES($pref_id,$sup)"; $stmt = $conn->prepare($query); $stmt->execute(array()); } $distribuidores = explode(",",$dist_selected); foreach($distribuidores as $dist) { if(empty($dist)) continue; $conn = $em->getConnection(); $query = "INSERT INTO imp_distributors VALUES($pref_id,$dist)"; $stmt = $conn->prepare($query); $stmt->execute(array()); } $this->get('session')->getFlashBag()->add('notice', 'La configuración se ha guardado con éxito!!'); } //Aquí vuelvo a sacar las categorias seleccionadas porque al cambiar tengo que volver a sacarlas. //$em = $this->getDoctrine()->getEntityManager(); $query = $em->createQuery( 'SELECT c.catId FROM DBPInterfazIcedbpBundle:Preicedbp\ImpCategories c WHERE c.idImpPreferences=1 ORDER BY c.catId ASC'); $_selected = $query->getResult(); $categories_selected = ""; foreach($_selected as $cat) { $categories_selected .= $cat['catId'].","; } //$categories_selected = $em->getRepository('DBPInterfazIcedbpBundle:Category')->getCategoriesSelectedJSON($categories_selected); $query = $em->createQuery( 'SELECT c.distributorId FROM DBPInterfazIcedbpBundle:Preicedbp\ImpDistributors c WHERE c.idImpPreferences=1 ORDER BY c.distributorId ASC'); $_selected = $query->getResult(); $distributors_selected = ""; foreach($_selected as $dist) { $distributors_selected .= $dist['distributorId'].","; } $query = $em->createQuery( 'SELECT c.supplierId FROM DBPInterfazIcedbpBundle:Preicedbp\ImpSuppliers c WHERE c.idImpPreferences=1 ORDER BY c.supplierId ASC'); $_selected = $query->getResult(); $suppliers_selected = ""; foreach($_selected as $sup) { $suppliers_selected .= $sup['supplierId'].","; } return $this->render('DBPInterfazIcedbpBundle:Preferences:icecat_preicedbp.html.twig', array('categories'=>$categories, 'suppliers'=>$suppliers, 'distributors'=>$distributors, 'categories_selected'=>$categories_selected, 'distributors_selected'=>$distributors_selected, 'suppliers_selected'=>$suppliers_selected, 'preferences'=>$preferences,'form' => $form->createView())); } } And this is my Type in \src\DBP\InterfazIcedbpBundle\Form\Type <?php namespace DBP\InterfazIcedbpBundle\Form\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolverInterface; use DBP\InterfazIcedbpBundle\Form\DataTransformer\StringToArrayTransformer; class PreferencesIcecatType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $suppliers_selected = $options['suppliers_selected']; $pref_id = $options['id']; //añadimos las categorias, fabricantes y distribuidores en un campo hidden $builder->add('cat_selected', 'hidden', array( 'data' => '', 'mapped'=>false, )); $builder->add('sup_selected', 'hidden', array( 'data' => $suppliers_selected,'mapped'=>false, )); $builder->add('dist_selected', 'hidden', array( 'data' => '','mapped'=>false, )); $builder->add('id', 'hidden', array('data'=>$pref_id,'property_path'=>'id')); //$builder->add('id', 'hidden', array()); //Añadimos el resto de campos $builder->add('onMarket', 'choice', array('label'=>'Mercado','choices' => array( '0' => 'Sólo productos que no estén en el mercado', '1' => 'Sólo productos en el mercado', '2' => 'Todos'),'multiple' => false)); $builder->add('quality', 'choice', array('label'=>'Calidad','choices' => array( 'ICECAT' => 'ICECAT', 'SUPPLIER' => 'SUPPLIER', 'NO-EDITOR' => 'NO-EDITOR', 'TODOS'=>'TODOS'),'multiple' => false)); $builder->add('importProducts', 'choice', array('label'=>'Filtrar por','choices' => array( '1' => 'Categorias', '2' => 'Fabricantes', '3' => 'Distribuidores', '0'=>'TODOS'),'multiple' => false,'expanded'=>true)); //$entityManager = $options['em']; $transformer = new StringToArrayTransformer($em); $builder->add($builder->create('languages', 'choice', array('label'=>'Lenguajes','choices' => array( 'ES' => 'ES', 'EN' => 'EN', ),'multiple' => true,'expanded'=>false))->addModelTransformer($transformer)); $builder->add($builder->create('countryMarket', 'choice', array('label'=>'Mercado','choices' => array( 'ES' => 'ES', 'EN' => 'EN', ),'multiple' => true,'expanded'=>false))->addModelTransformer($transformer)); $builder->add('onlyUpdateExistings', 'checkbox', array( 'label' => 'Actualizar sólo existentes', 'required' => false, )); $builder->add('sel_cat', 'checkbox', array( 'label' => 'Seleccionar/Deseleccionar', 'required' => false, 'mapped'=>false, )); $builder->add('sel_sup', 'checkbox', array( 'label' => 'Seleccionar/Deseleccionar', 'required' => false,'mapped'=>false, )); $builder->add('sel_dist', 'checkbox', array( 'label' => 'Seleccionar/Deseleccionar', 'required' => false,'mapped'=>false, )); $builder->add('show_only_cat', 'checkbox', array( 'label' => 'Mostrar sólo seleccionadas', 'required' => false,'mapped'=>false, )); $builder->add('show_only_sup', 'checkbox', array( 'label' => 'Mostrar sólo seleccionados', 'required' => false,'mapped'=>false, )); $builder->add('show_only_dist', 'checkbox', array( 'label' => 'Mostrar sólo seleccionados', 'required' => false,'mapped'=>false, )); $builder->add('user_icecat', 'text', array( )); $builder->add('pass_icecat', 'text', array( )); $builder->add('icecat_route', 'text', array( )); $builder->add('icecat_subdir', 'text', array( )); } public function getName() { return 'preferences_icecat'; } }
try to add this to your controller: use DBP\InterfazIcedbpBundle\Form\Type\PreferencesIcecatType; The error says that cant found your form class, so say it where it is.
Maybe there is a typo error. In your use in your controller, the name of your FormType file, the name of your FormType class. Check the namespaces.