...
 
Commits (43)
......@@ -35,7 +35,7 @@
</h3>
<p>
<a class="btn btn-default" href="{$backup_url}">
<i class="icon-download"></i>
<i class="icon-download"></i>
{l s='Download the backup file (%s MB)' sprintf=$backup_weight}
</a>
</p>
......@@ -59,12 +59,25 @@
</ol>
<form action="{$currentIndex|escape:'html':'UTF-8'}&amp;add{$table}&amp;token={$token|escape:'html':'UTF-8'}" method="post" class="form-horizontal">
<button type="submit" class="btn btn-default">
<i class="icon-save"></i>
<i class="icon-save"></i>
{l s='I have read the disclaimer. Please create a new backup.'}
</button>
</form>
</div>
{if $host_mode}
<div class="alert alert-info">
<h4>{l s='How to restore a database backup'}</h4>
{l s='If you need to restore a database backup, we invite you to subscribe to a [1][2]technical support plan[/2][/1].' tags=['<strong>', '<a class="_blank" href="http://addons.prestashop.com/support/16298-support-essentiel-plan.html">']}
<br />
{l s='Our team will take care of restoring your database safely.'}
<br />
<br />
{l s='Why can\'t I restore it by myself?'}
<br />
{l s='Your shop is hosted by PrestaShop. Although you can create backup files here below, there are core settings you cannot access for security reasons, like the database management. Thus, only our team can proceed to a restoration.'}
</div>
{else}
<div class="alert alert-info">
<h4>{l s='How to restore a database backup in 10 easy steps'}</h4>
<ol>
......@@ -80,5 +93,6 @@
<li>{l s='Click on the "Go" button and please wait patiently for the import process to conclude. This may take several minutes.'}</li>
</ol>
</div>
{/if}
{/block}
......@@ -29,7 +29,7 @@
<p>{l s='Once connected, your new modules will be automatically installed.'}</p>
</div>
<div class="row modules-addons-buttons">
<a class="btn btn-default btn-primary _blank" href="{$addons_register_link|escape:'html':'UTF-8'}"><i class="icon-pencil"></i> {l s='Sign up'}</a><a href="#" class="addons_connect btn btn-default" data-toggle="modal" data-target="#modal_addons_connect" title="{l s='Connect to Prestashop Marketplace account'}"><i class="icon-user"></i> {l s='Log in'}</a>
<a class="btn btn-default btn-primary _blank" href="{$addons_register_link|escape:'html':'UTF-8'}"><i class="icon-pencil"></i> {l s='Sign up'}</a><a href="#" class="addons_connect btn btn-default" data-toggle="modal" data-target="#modal_addons_connect" title="{l s='Connect to PrestaShop Marketplace account'}"><i class="icon-user"></i> {l s='Log in'}</a>
</div>
</div>
{/if}
......
......@@ -78,7 +78,7 @@
autoUpload: false,
singleFileUploads: true,
maxFileSize: {$post_max_size},
start: function (e) {
start: function (e) {
{$id|escape:'html':'UTF-8'}_upload_button.start();
$('#{$id|escape:'html':'UTF-8'}-upload-button').unbind('click'); //Important as we bind it for every elements in add function
},
......@@ -94,7 +94,7 @@
$('#{$id|escape:'html':'UTF-8'}-errors').html('<strong>'+data.result.{$name|escape:'html':'UTF-8'}[i].name+'</strong> : '+data.result.{$name|escape:'html':'UTF-8'}[i].error).parent().show();
$('#{$id|escape:'html':'UTF-8'}-files-list').html('').parent().hide();
}
else
else
{
$(data.context).appendTo($('#{$id|escape:'html':'UTF-8'}-success'));
$('#{$id|escape:'html':'UTF-8'}-success').parent().show();
......@@ -115,9 +115,10 @@
$("#countImage").html(parseInt($("#countImage").html()) + 1);
$("#img" + id).remove();
$("#imageTable").tableDnDUpdate();
$('#legend_1').val('');
}
}
}
}
......@@ -148,7 +149,7 @@
var button = $('<button/>').addClass('btn btn-default pull-right').prop('type', 'button').html('<i class="icon-trash"></i> {l s='Remove file'}').appendTo(data.context).on('click', function() {
{$id|escape:'html':'UTF-8'}_total_files--;
data.files = null;
var total_elements = $(this).parent().siblings('div.form-group').length;
$(this).parent().remove();
......@@ -160,13 +161,13 @@
$('#{$id|escape:'html':'UTF-8'}-files-list').parent().show();
$('#{$id|escape:'html':'UTF-8'}-upload-button').show().bind('click', function () {
if (data.files != null)
data.submit();
data.submit();
});
{$id|escape:'html':'UTF-8'}_total_files++;
}).on('fileuploadprocessalways', function (e, data) {
var index = data.index, file = data.files[index];
if (file.error) {
$('#{$id|escape:'html':'UTF-8'}-errors').append('<div class="form-group"><i class="icon-picture-o"></i> <strong>'+file.name+'</strong> ('+humanizeSize(file.size)+') : '+file.error+'</div>').parent().show();
$('#{$id|escape:'html':'UTF-8'}-files-list').html('').parent().hide();
......@@ -181,7 +182,7 @@
params[id] = $(this).val();
});
data.formData = params;
data.formData = params;
});
$('#{$id|escape:'html':'UTF-8'}-add-button').on('click', function() {
......@@ -190,4 +191,4 @@
$('#{$id|escape:'html':'UTF-8'}').trigger('click');
});
});
</script>
\ No newline at end of file
</script>
......@@ -76,7 +76,7 @@
<i class="icon-book"></i>
{l s='Training'}
</a>
{if $iso_is_fr && host_mode == 0}
{if $iso_is_fr && !host_mode}
<p>Questions • Renseignements • Formations :
<strong>+33 (0)1.40.18.30.04</strong>
</p>
......
......@@ -262,10 +262,10 @@
<ul id="header_employee_box">
{if (!isset($logged_on_addons) || !$logged_on_addons) && (isset($display_addons_connection) && $display_addons_connection)}
<li>
<a href="#" class="addons_connect toolbar_btn" data-toggle="modal" data-target="#modal_addons_connect" title="{l s='Connect to Prestashop Marketplace account'}">
<a href="#" class="addons_connect toolbar_btn" data-toggle="modal" data-target="#modal_addons_connect" title="{l s='Connect to PrestaShop Marketplace account'}">
<i class="icon-chain-broken"></i>
<span class="string-long">{l s='Connect to Prestashop Marketplace account'}</span>
<span class="string-short">{l s='Prestashop Marketplace'}</span>
<span class="string-long">{l s='Connect to PrestaShop Marketplace account'}</span>
<span class="string-short">{l s='PrestaShop Marketplace'}</span>
</a>
</li>
{/if}
......
......@@ -31,7 +31,7 @@
</div>
</div>
{/if}
{if count($errors) && !empty($errors.0) && (!isset($disableDefaultErrorOutPut) || $disableDefaultErrorOutPut == false)}
{if count($errors) && array_shift($errors) != '' && (!isset($disableDefaultErrorOutPut) || $disableDefaultErrorOutPut == false)}
<div class="bootstrap">
<div class="alert alert-danger">
<button type="button" class="close" data-dismiss="alert">&times;</button>
......
......@@ -366,7 +366,7 @@ class AddressCore extends ObjectModel
$address = new Address();
$address->id_country = (int)$context->customer->geoloc_id_country;
$address->id_state = (int)$context->customer->id_state;
$address->zipcode = $context->customer->postcode;
$address->postcode = $context->customer->postcode;
}
else
{
......
......@@ -2764,19 +2764,21 @@ class ProductCore extends ObjectModel
$res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql);
foreach ($res as $row)
{
$array_tmp = array(
'price' => $row['price'],
'ecotax' => $row['ecotax'],
'attribute_price' => (isset($row['attribute_price']) ? $row['attribute_price'] : null)
);
self::$_pricesLevel2[$cache_id_2][(int)$row['id_product_attribute']] = $array_tmp;
if (is_array($res) && count($res))
foreach ($res as $row)
{
$array_tmp = array(
'price' => $row['price'],
'ecotax' => $row['ecotax'],
'attribute_price' => (isset($row['attribute_price']) ? $row['attribute_price'] : null)
);
self::$_pricesLevel2[$cache_id_2][(int)$row['id_product_attribute']] = $array_tmp;
if (isset($row['default_on']) && $row['default_on'] == 1)
self::$_pricesLevel2[$cache_id_2][0] = $array_tmp;
}
if (isset($row['default_on']) && $row['default_on'] == 1)
self::$_pricesLevel2[$cache_id_2][0] = $array_tmp;
}
}
if (!isset(self::$_pricesLevel2[$cache_id_2][(int)$id_product_attribute]))
return;
......
......@@ -100,8 +100,7 @@ class ProductSaleCore
LEFT JOIN `'._DB_PREFIX_.'tax_rule` tr ON (product_shop.`id_tax_rules_group` = tr.`id_tax_rules_group`)
AND tr.`id_country` = '.(int)Context::getContext()->country->id.'
AND tr.`id_state` = 0
LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = tr.`id_tax`)
'.Product::sqlStock('p');
LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = tr.`id_tax`)';
if (Group::isFeatureActive())
{
......
......@@ -84,8 +84,8 @@ class ProfileCore extends ObjectModel
$result = Db::getInstance()->execute('INSERT INTO '._DB_PREFIX_.'access (SELECT '.(int)$this->id.', id_tab, 0, 0, 0, 0 FROM '._DB_PREFIX_.'tab)');
$result &= Db::getInstance()->execute('
INSERT INTO '._DB_PREFIX_.'module_access
(`id_profile`, `id_module`, `configure`, `view`)
(SELECT '.(int)$this->id.', id_module, 0, 1 FROM '._DB_PREFIX_.'module)
(`id_profile`, `id_module`, `configure`, `view`, `uninstall`)
(SELECT '.(int)$this->id.', id_module, 0, 1, 0 FROM '._DB_PREFIX_.'module)
');
return $result;
}
......@@ -116,7 +116,7 @@ class ProfileCore extends ObjectModel
if (!isset(self::$_cache_accesses[$id_profile]))
self::$_cache_accesses[$id_profile] = array();
if (!isset(self::$_cache_accesses[$id_profile][$type]))
{
self::$_cache_accesses[$id_profile][$type] = array();
......
......@@ -105,7 +105,7 @@ class StateCore extends ObjectModel
{
if (empty($state))
return false;
$cache_id = 'State::getNameById_'.pSQL($state);
$cache_id = 'State::getIdByName_'.pSQL($state);
if (!Cache::isStored($cache_id))
{
$result = (int)Db::getInstance()->getValue('
......
......@@ -2600,7 +2600,7 @@ exit;
switch ($type)
{
case 'by' :
$list = array(0 => 'name', 1 => 'price', 2 => 'date_add', 3 => 'date_upd', 4 => 'position', 5 => 'manufacturer_name', 6 => 'quantity');
$list = array(0 => 'name', 1 => 'price', 2 => 'date_add', 3 => 'date_upd', 4 => 'position', 5 => 'manufacturer_name', 6 => 'quantity', 7 => 'reference');
$value = (is_null($value) || $value === false || $value === '') ? (int)Configuration::get('PS_PRODUCTS_ORDER_BY') : $value;
$value = (isset($list[$value])) ? $list[$value] : ((in_array($value, $list)) ? $value : 'position');
$order_by_prefix = '';
......
......@@ -65,7 +65,7 @@ class TranslateCore
return Translate::getModuleTranslation(Module::$classInModule[$class_name_controller], $string, $class_name_controller, $sprintf, $addslashes);
}
$string = preg_replace("/\\*'/", "\'", $string);
$string = preg_replace("/\\\*'/", "\'", $string);
$key = md5($string);
if (isset($_LANGADM[$class.$key]))
$str = $_LANGADM[$class.$key];
......@@ -93,7 +93,7 @@ class TranslateCore
*/
public static function getGenericAdminTranslation($string, $key = null, &$lang_array)
{
$string = preg_replace("/\\*'/", "\'", $string);
$string = preg_replace("/\\\*'/", "\'", $string);
if (is_null($key))
$key = md5($string);
......@@ -128,6 +128,7 @@ class TranslateCore
static $translations_merged = array();
$name = $module instanceof Module ? $module->name : $module;
$language = Context::getContext()->language;
if (!isset($translations_merged[$name]) && isset(Context::getContext()->language))
......@@ -149,7 +150,7 @@ class TranslateCore
$translations_merged[$name] = true;
}
}
$string = preg_replace("/\\*'/", "\'", $string);
$string = preg_replace("/\\\*'/", "\'", $string);
$key = md5($string);
$cache_key = $name.'|'.$string.'|'.$source.'|'.(int)$js;
......@@ -182,7 +183,7 @@ class TranslateCore
$ret = stripslashes($_MODULES[$default_key]);
// if translation was not found in module, look for it in AdminController or Helpers
elseif (!empty($_LANGADM))
$ret = Translate::getGenericAdminTranslation($string, $key, $_LANGADM);
$ret = stripslashes(Translate::getGenericAdminTranslation($string, $key, $_LANGADM));
else
$ret = stripslashes($string);
......@@ -229,7 +230,7 @@ class TranslateCore
if (!isset($_LANGPDF) || !is_array($_LANGPDF))
return str_replace('"', '&quot;', $string);
$string = preg_replace("/\\*'/", "\'", $string);
$string = preg_replace("/\\\*'/", "\'", $string);
$key = md5($string);
$str = (array_key_exists('PDF'.$key, $_LANGPDF) ? $_LANGPDF['PDF'.$key] : $string);
......
......@@ -2327,9 +2327,8 @@ class AdminControllerCore extends Controller
public function setMedia()
{
//Bootstrap + Specific Admin Theme
//Bootstrap
$this->addCSS(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/css/'.$this->bo_css, 'all', 0);
$this->addCSS(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/css/overrides.css', 'all', 99);
$this->addJquery();
$this->addjQueryPlugin(array('scrollTo', 'alerts', 'chosen', 'autosize', 'fancybox' ));
......@@ -2356,6 +2355,9 @@ class AdminControllerCore extends Controller
// Execute Hook AdminController SetMedia
Hook::exec('actionAdminControllerSetMedia');
// Specific Admin Theme
$this->addCSS(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/css/overrides.css', 'all', PHP_INT_MAX);
}
/**
......
<?php
/*
/**
* 2007-2015 PrestaShop
*
* NOTICE OF LICENSE
......@@ -687,13 +687,13 @@ class FrontControllerCore extends Controller
if (!in_array($_SERVER['SERVER_NAME'], array('localhost', '127.0.0.1')))
{
/* Check if Maxmind Database exists */
if (file_exists(_PS_GEOIP_DIR_.'GeoLiteCity.dat'))
if (@filemtime(_PS_GEOIP_DIR_._PS_GEOIP_CITY_FILE_))
{
if (!isset($this->context->cookie->iso_code_country) || (isset($this->context->cookie->iso_code_country) && !in_array(strtoupper($this->context->cookie->iso_code_country), explode(';', Configuration::get('PS_ALLOWED_COUNTRIES')))))
{
include_once(_PS_GEOIP_DIR_.'geoipcity.inc');
$gi = geoip_open(realpath(_PS_GEOIP_DIR_.'GeoLiteCity.dat'), GEOIP_STANDARD);
$gi = geoip_open(realpath(_PS_GEOIP_DIR_._PS_GEOIP_CITY_FILE_), GEOIP_STANDARD);
$record = geoip_record_by_addr($gi, Tools::getRemoteAddr());
if (is_object($record))
......
......@@ -1912,8 +1912,8 @@ class OrderCore extends ObjectModel
if ($res = (int)Db::getInstance()->getvalue('
SELECT `id_order_invoice`
FROM `'._DB_PREFIX_.'order_invoice`
WHERE `id_order` = '.(int)$this->id.'
AND `number` > 0'));
WHERE `id_order` = '.(int)$this->id.
(Configuration::get('PS_INVOICE') ? ' AND `number` > 0' : '')))
return $res;
return false;
}
......
......@@ -62,6 +62,7 @@ abstract class HTMLTemplateCore
'title' => $this->title,
'date' => $this->date,
'shop_name' => $shop_name,
'shop_details' => Configuration::get('PS_SHOP_DETAILS', null, null, (int)$id_shop),
'width_logo' => $width,
'height_logo' => $height
));
......@@ -88,7 +89,6 @@ abstract class HTMLTemplateCore
'shop_fax' => Configuration::get('PS_SHOP_FAX', null, null, (int)$id_shop),
'shop_phone' => Configuration::get('PS_SHOP_PHONE', null, null, (int)$id_shop),
'shop_email' => Configuration::get('PS_SHOP_EMAIL', null, null, (int)$id_shop),
'shop_details' => Configuration::get('PS_SHOP_DETAILS', null, null, (int)$id_shop),
'free_text' => Configuration::get('PS_INVOICE_FREE_TEXT', (int)Context::getContext()->language->id, null, (int)$id_shop)
));
......
......@@ -734,7 +734,7 @@ class StockManagerCore implements StockManagerInterface
$stock_quantity += Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('SELECT SUM(s.`usable_quantity`) as quantity
FROM '._DB_PREFIX_.'stock s
LEFT JOIN '._DB_PREFIX_.'warehouse_carrier wc ON wc.`id_warehouse` = s.`id_warehouse`
LEFT JOIN ps_carrier c ON wc.`id_carrier` = c.`id_reference`
LEFT JOIN '._DB_PREFIX_.'carrier c ON wc.`id_carrier` = c.`id_reference`
WHERE s.`id_product` = '.(int)$id_product.' AND s.`id_product_attribute` = '.(int)$id_product_attribute.' AND s.`id_warehouse` = '.$result['id_warehouse'].' AND c.`id_carrier` IN ('.rtrim($delivery_option[(int)Context::getContext()->cart->id_address_delivery], ',').') GROUP BY s.`id_product`');
else
$stock_quantity += Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('SELECT SUM(s.`usable_quantity`) as quantity
......
<?php
/*
/**
* 2007-2015 PrestaShop
*
* NOTICE OF LICENSE
......@@ -91,6 +91,7 @@ define('_PS_FRONT_CONTROLLER_DIR_', _PS_CORE_DIR_.'/controllers/front/');
define('_PS_TOOL_DIR_', _PS_CORE_DIR_.'/tools/');
define('_PS_GEOIP_DIR_', _PS_TOOL_DIR_.'geoip/');
define('_PS_GEOIP_CITY_FILE_', 'GeoLiteCity.dat');
define('_PS_PEAR_XML_PARSER_PATH_', _PS_TOOL_DIR_.'pear_xml_parser/');
define('_PS_SWIFT_DIR_', _PS_TOOL_DIR_.'swift/');
define('_PS_TAASC_PATH_', _PS_TOOL_DIR_.'taasc/');
......@@ -195,4 +196,3 @@ define('_PS_SMARTY_CONSOLE_OPEN_BY_URL_', 1);
define('_PS_SMARTY_CONSOLE_OPEN_', 2);
define('_PS_JQUERY_VERSION_', '1.11.0');
......@@ -352,13 +352,42 @@ class AdminDashboardControllerCore extends AdminController
$articles_limit = 2;
foreach ($rss->channel->item as $item)
{
if ($articles_limit > 0 && Validate::isCleanHtml((string)$item->title) && Validate::isCleanHtml((string)$item->description))
if ($articles_limit > 0 && Validate::isCleanHtml((string)$item->title) && Validate::isCleanHtml((string)$item->description)
&& isset($item->link) && isset($item->title))
{
if (in_array($this->context->mode, array(Context::MODE_HOST, Context::MODE_HOST_CONTRIB)))
$utm_content = 'cloud';
else
$utm_content = 'download';
$shop_default_country_id = (int)Configuration::get('PS_COUNTRY_DEFAULT');
$shop_default_iso_country = (string)Tools::strtoupper(Country::getIsoById($shop_default_country_id));
$analytics_params = array('utm_source' => 'back-office',
'utm_medium' => 'rss',
'utm_campaign' => 'back-office-'.$shop_default_iso_country,
'utm_content' => $utm_content
);
$url_query = parse_url($item->link, PHP_URL_QUERY);
parse_str($url_query, $link_query_params);
if ($link_query_params)
{
$full_url_params = array_merge($link_query_params, $analytics_params);
$base_url = explode('?', (string)$item->link);
$base_url = (string)$base_url[0];
$article_link = $base_url.'?'.http_build_query($full_url_params);
}
else
$article_link = (string)$item->link.'?'.http_build_query($analytics_params);
$return['rss'][] = array(
'date' => Tools::displayDate(date('Y-m-d', strtotime((string)$item->pubDate))),
'title' => (string)Tools::htmlentitiesUTF8($item->title),
'short_desc' => Tools::truncateString(strip_tags((string)$item->description), 150),
'link' => (string)$item->link,
'link' => (string)$article_link,
);
}
else
break;
$articles_limit --;
......
<?php
/*
/**
* 2007-2015 PrestaShop
*
* NOTICE OF LICENSE
......@@ -140,7 +140,7 @@ class AdminGeolocationControllerCore extends AdminController
{
$this->display = 'options';
if (!$this->isGeoLiteCityAvailable())
$this->displayWarning($this->l('In order to use Geolocation, please download').'
$this->displayWarning($this->l('In order to use Geolocation, please download').'
<a href="http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz">'.$this->l('this file').'</a> '.
$this->l('and extract it (using Winrar or Gzip) into the /tools/geoip/ directory.'));
......@@ -149,9 +149,9 @@ class AdminGeolocationControllerCore extends AdminController
protected function isGeoLiteCityAvailable()
{
if (file_exists(_PS_GEOIP_DIR_.'GeoLiteCity.dat'))
if (@filemtime(_PS_GEOIP_DIR_._PS_GEOIP_CITY_FILE_))
return true;
return false;
}
}
......@@ -48,7 +48,9 @@ class AdminLoginControllerCore extends AdminController
$this->addJquery();
$this->addjqueryPlugin('validate');
$this->addJS(_PS_JS_DIR_.'jquery/plugins/validate/localization/messages_'.$this->context->language->iso_code.'.js');
$this->addCSS(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/css/admin-theme.css');
$this->addCSS(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/css/admin-theme.css', 'all', 0);
// Specific Admin Theme
$this->addCSS(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/css/overrides.css', 'all', PHP_INT_MAX);
$this->addJS(_PS_JS_DIR_.'vendor/spin.js');
$this->addJS(_PS_JS_DIR_.'vendor/ladda.js');
}
......
......@@ -1059,6 +1059,7 @@ class AdminProductsControllerCore extends AdminController
$reduction = (float)(Tools::getValue('sp_reduction'));
$reduction_tax = Tools::getValue('sp_reduction_tax');
$reduction_type = !$reduction ? 'amount' : Tools::getValue('sp_reduction_type');
$reduction_type = $reduction_type == '-' ? 'amount' : $reduction_type;
$from = Tools::getValue('sp_from');
if (!$from)
$from = '0000-00-00 00:00:00';
......@@ -1066,7 +1067,11 @@ class AdminProductsControllerCore extends AdminController
if (!$to)
$to = '0000-00-00 00:00:00';
if ($reduction_type == 'percentage' && ((float)$reduction <= 0 || (float)$reduction > 100))
if (($price == '-1') && ((float)$reduction == '0'))
$this->errors[] = Tools::displayError('No submitted reduction value');
elseif (strtotime($to) < strtotime($from))
$this->errors[] = Tools::displayError('Invalid date range');
elseif ($reduction_type == 'percentage' && ((float)$reduction <= 0 || (float)$reduction > 100))
$this->errors[] = Tools::displayError('Submitted reduction value (0-100) is out-of-range');
elseif ($this->_validateSpecificPrice($id_shop, $id_currency, $id_country, $id_group, $id_customer, $price, $from_quantity, $reduction, $reduction_type, $from, $to, $id_product_attribute))
{
......@@ -2399,11 +2404,11 @@ class AdminProductsControllerCore extends AdminController
$helper->icon = 'icon-archive';
$helper->color = 'color1';
$helper->title = $this->l('Out of stock items', null, null, false);
if (ConfigurationKPI::get('PERCENT_PRODUCT_STOCK') !== false)
$helper->value = ConfigurationKPI::get('PERCENT_PRODUCT_STOCK');
$helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=percent_product_stock';
if (ConfigurationKPI::get('PERCENT_PRODUCT_OUT_OF_STOCK') !== false)
$helper->value = ConfigurationKPI::get('PERCENT_PRODUCT_OUT_OF_STOCK');
$helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=percent_product_out_of_stock';
$helper->tooltip = $this->l('X% of your products for sale are out of stock.', null, null, false);
$helper->refresh = (bool)(ConfigurationKPI::get('PERCENT_PRODUCT_STOCK_EXPIRE') < $time);
$helper->refresh = (bool)(ConfigurationKPI::get('PERCENT_PRODUCT_OUT_OF_STOCK_EXPIRE') < $time);
$helper->href = Context::getContext()->link->getAdminLink('AdminProducts').'&productFilter_sav!quantity=0&productFilter_active=1&submitFilterproduct=1';
$kpis[] = $helper->generate();
}
......@@ -2416,7 +2421,7 @@ class AdminProductsControllerCore extends AdminController
if (ConfigurationKPI::get('PRODUCT_AVG_GROSS_MARGIN') !== false)
$helper->value = ConfigurationKPI::get('PRODUCT_AVG_GROSS_MARGIN');
$helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=product_avg_gross_margin';
$helper->tooltip = $this->l('The gross margin is the margin made on the sold of a product regarding its purchase price, on all your products for sale.', null, null, false);
$helper->tooltip = $this->l('The gross margin is the difference between the retail price and the wholesale price, on all your products for sale.', null, null, false);
$helper->refresh = (bool)(ConfigurationKPI::get('PRODUCT_AVG_GROSS_MARGIN_EXPIRE') < $time);
$kpis[] = $helper->generate();
......@@ -4883,7 +4888,7 @@ class AdminProductsControllerCore extends AdminController
public function processImageLegends()
{
if (Validate::isLoadedObject($product = new Product((int)Tools::getValue('id_product'))))
if (Tools::getValue('key_tab') == 'Images' && Validate::isLoadedObject($product = new Product((int)Tools::getValue('id_product'))))
{
$languages = Language::getLanguages(false);
foreach ($_POST as $key => $val)
......
......@@ -134,6 +134,19 @@ class AdminStatsControllerCore extends AdminStatsTabController
return round($row['products'] ? 100 * $row['with_stock'] / $row['products'] : 0, 2).'%';
}
public static function getPercentProductOutOfStock()
{
$row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow('
SELECT SUM(IF(IFNULL(stock.quantity, 0) = 0, 1, 0)) as without_stock, COUNT(*) as products
FROM `'._DB_PREFIX_.'product` p
'.Shop::addSqlAssociation('product', 'p').'
LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa ON p.id_product = pa.id_product
'.Product::sqlStock('p', 'pa').'
WHERE product_shop.active = 1');
return round($row['products'] ? 100 * $row['without_stock'] / $row['products'] : 0, 2).'%';
}
public static function getProductAverageGrossMargin()
{
$sql = 'SELECT AVG(1 - (IF(IFNULL(product_attribute_shop.wholesale_price, 0) = 0, product_shop.wholesale_price,product_attribute_shop.wholesale_price) / (IFNULL(product_attribute_shop.price, 0) + product_shop.price)))
......@@ -562,6 +575,12 @@ class AdminStatsControllerCore extends AdminStatsTabController
ConfigurationKPI::updateValue('PERCENT_PRODUCT_STOCK_EXPIRE', strtotime('+4 hour'));
break;
case 'percent_product_out_of_stock':
$value = AdminStatsController::getPercentProductOutOfStock();
ConfigurationKPI::updateValue('PERCENT_PRODUCT_OUT_OF_STOCK', $value);
ConfigurationKPI::updateValue('PERCENT_PRODUCT_OUT_OF_STOCK_EXPIRE', strtotime('+4 hour'));
break;
case 'product_avg_gross_margin':
$value = AdminStatsController::getProductAverageGrossMargin();
ConfigurationKPI::updateValue('PRODUCT_AVG_GROSS_MARGIN', $value);
......
......@@ -26,7 +26,7 @@
class PageNotFoundControllerCore extends FrontController
{
public $php_self = '404';
public $php_self = 'pagenotfound';
public $page_name = 'pagenotfound';
public $ssl = true;
......
......@@ -252,10 +252,14 @@ class ProductControllerCore extends FrontController
else
$return_link = 'javascript: history.back();';
$accessories = $this->product->getAccessories($this->context->language->id);
if ($this->product->cache_is_pack || count($accessories))
$this->context->controller->addCSS(_THEME_CSS_DIR_.'product_list.css');
$this->context->smarty->assign(array(
'stock_management' => Configuration::get('PS_STOCK_MANAGEMENT'),
'customizationFields' => $customization_fields,
'accessories' => $this->product->getAccessories($this->context->language->id),
'accessories' => $accessories,
'return_link' => $return_link,
'product' => $this->product,
'product_manufacturer' => new Manufacturer((int)$this->product->id_manufacturer, $this->context->language->id),
......
......@@ -1043,9 +1043,9 @@ CREATE TABLE `PREFIX_module` (
CREATE TABLE `PREFIX_module_access` (
`id_profile` int(10) unsigned NOT NULL,
`id_module` int(10) unsigned NOT NULL,
`view` tinyint(1) NOT NULL,
`configure` tinyint(1) NOT NULL,
`uninstall` tinyint(1) NOT NULL,
`view` tinyint(1) NOT NULL DEFAULT '0',
`configure` tinyint(1) NOT NULL DEFAULT '0',
`uninstall` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id_profile`,`id_module`)
) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8 COLLATION;
......@@ -1452,7 +1452,7 @@ CREATE TABLE `PREFIX_product` (
`redirect_type` ENUM('', '404', '301', '302') NOT NULL DEFAULT '',
`id_product_redirected` int(10) unsigned NOT NULL DEFAULT '0',
`available_for_order` tinyint(1) NOT NULL DEFAULT '1',
`available_date` date NOT NULL,
`available_date` date NOT NULL DEFAULT '0000-00-00',
`condition` ENUM('new', 'used', 'refurbished') NOT NULL DEFAULT 'new',
`show_price` tinyint(1) NOT NULL DEFAULT '1',
`indexed` tinyint(1) NOT NULL DEFAULT '0',
......@@ -1494,7 +1494,7 @@ CREATE TABLE IF NOT EXISTS `PREFIX_product_shop` (
`redirect_type` ENUM('', '404', '301', '302') NOT NULL DEFAULT '',
`id_product_redirected` int(10) unsigned NOT NULL DEFAULT '0',
`available_for_order` tinyint(1) NOT NULL DEFAULT '1',
`available_date` date NOT NULL,
`available_date` date NOT NULL DEFAULT '0000-00-00',
`condition` enum('new','used','refurbished') NOT NULL DEFAULT 'new',
`show_price` tinyint(1) NOT NULL DEFAULT '1',
`indexed` tinyint(1) NOT NULL DEFAULT '0',
......@@ -1525,7 +1525,7 @@ CREATE TABLE `PREFIX_product_attribute` (
`unit_price_impact` DECIMAL(20,6) NOT NULL DEFAULT '0.00',
`default_on` tinyint(1) unsigned NOT NULL DEFAULT '0',
`minimal_quantity` int(10) unsigned NOT NULL DEFAULT '1',
`available_date` date NOT NULL,
`available_date` date NOT NULL DEFAULT '0000-00-00',
PRIMARY KEY (`id_product_attribute`),
KEY `product_attribute_product` (`id_product`),
KEY `reference` (`reference`),
......@@ -1544,7 +1544,7 @@ CREATE TABLE `PREFIX_product_attribute_shop` (
`unit_price_impact` DECIMAL(20,6) NOT NULL DEFAULT '0.00',
`default_on` tinyint(1) unsigned NOT NULL DEFAULT '0',
`minimal_quantity` int(10) unsigned NOT NULL DEFAULT '1',
`available_date` date NOT NULL,
`available_date` date NOT NULL DEFAULT '0000-00-00',
PRIMARY KEY (`id_product_attribute`, `id_shop`)
) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8 COLLATION;
......
......@@ -47,4 +47,13 @@ CREATE TABLE `PREFIX_cms_category_shop` (
ALTER TABLE `PREFIX_customization_field_lang` ADD `id_shop` INT(10) UNSIGNED NOT NULL DEFAULT '1' AFTER `id_lang`;
ALTER TABLE `PREFIX_customization_field_lang` DROP PRIMARY KEY, ADD PRIMARY KEY (`id_customization_field`, `id_shop`, `id_lang`);
/* PHP:customization_field_multishop_lang(); */;
\ No newline at end of file
/* PHP:customization_field_multishop_lang(); */;
ALTER TABLE `PREFIX_product` CHANGE `available_date` `available_date` DATE NOT NULL DEFAULT '0000-00-00';
ALTER TABLE `PREFIX_product_shop` CHANGE `available_date` `available_date` DATE NOT NULL DEFAULT '0000-00-00';
ALTER TABLE `PREFIX_product_attribute` CHANGE `available_date` `available_date` DATE NOT NULL DEFAULT '0000-00-00';
ALTER TABLE `PREFIX_product_attribute_shop` CHANGE `available_date` `available_date` DATE NOT NULL DEFAULT '0000-00-00';
ALTER TABLE `PREFIX_module_access` CHANGE `view` `view` TINYINT( 1 ) NOT NULL DEFAULT '0',
CHANGE `configure` `configure` TINYINT( 1 ) NOT NULL DEFAULT '0',
CHANGE `uninstall` `uninstall` TINYINT( 1 ) NOT NULL DEFAULT '0';
......@@ -197,7 +197,7 @@ function getBlogRss() {
success : function(jsonData) {
if (typeof jsonData !== 'undefined' && jsonData !== null && !jsonData.has_errors) {
for (var article in jsonData.rss) {
var article_html = '<article><h4><a href="'+jsonData.rss[article].link+'" class="_blank">'+jsonData.rss[article].title+'</a></h4><span class="dash-news-date text-muted">'+jsonData.rss[article].date+'</span><p>'+jsonData.rss[article].short_desc+' <a href="'+jsonData.rss[article].link+'">'+read_more+'</a><p></article><hr/>';
var article_html = '<article><h4><a href="'+jsonData.rss[article].link+'" class="_blank" onclick="return !window.open(this.href);">'+jsonData.rss[article].title+'</a></h4><span class="dash-news-date text-muted">'+jsonData.rss[article].date+'</span><p>'+jsonData.rss[article].short_desc+' <a href="'+jsonData.rss[article].link+'">'+read_more+'</a><p></article><hr/>';
$('.dash_news .dash_news_content').append(article_html);
}
}
......
......@@ -446,8 +446,6 @@ function wishlistProductChange(id_product, id_product_attribute, id_old_wishlist
},
success: function (data)
{
console.log(data);
console.log(data.msg);
if (data.success == true) {
$('#wlp_' + id_product + '_' + id_product_attribute).fadeOut('slow');
$('#wishlist_' + id_old_wishlist + ' td:nth-child(2)').text($('#wishlist_' + id_old_wishlist + ' td:nth-child(2)').text() - quantity);
......
......@@ -400,7 +400,7 @@ function updateAddressSelection()
var name = $(this).find('.cart_quantity_input').attr('name')+'_hidden';
$(this).find('.cart_quantity_input').attr('name', $(this).find('.cart_quantity_input').attr('name').replace(/_\d+$/, '_'+idAddress_delivery));
if ($(this).find('[name="' + name + '"]').length > 0)
$(this).find('[name="' + name +' "]').attr('name', name.replace(/_\d+_hidden$/, '_'+idAddress_delivery+'_hidden'));
$(this).find('[name="' + name +'"]').attr('name', name.replace(/_\d+_hidden$/, '_'+idAddress_delivery+'_hidden'));
}
if ($(this).find('.cart_quantity_delete').length > 0 && $(this).find('.cart_quantity_delete').attr('id').length > 0)
......
......@@ -984,7 +984,7 @@ function getProductAttribute()
for (var i in attributesCombinations)
for (var a in tab_attributes)
if (attributesCombinations[i]['id_attribute'] === tab_attributes[a])
request += '/'+attributesCombinations[i]['group'] + attribute_anchor_separator + attributesCombinations[i]['attribute'];
request += '/' + attributesCombinations[i]['id_attribute'] + '-' + attributesCombinations[i]['group'] + attribute_anchor_separator + attributesCombinations[i]['attribute'];
request = request.replace(request.substring(0, 1), '#/');
var url = window.location + '';
......@@ -1033,8 +1033,8 @@ function checkUrl()
count = 0;
for (var z in tabValues)
for (var a in attributesCombinations)
if (attributesCombinations[a]['group'] === decodeURIComponent(tabValues[z][0])
&& attributesCombinations[a]['attribute'] === decodeURIComponent(tabValues[z][1]))
if (attributesCombinations[a]['group'] === decodeURIComponent(tabValues[z][1])
&& attributesCombinations[a]['id_attribute'] === decodeURIComponent(tabValues[z][0]))
{
count++;
......
......@@ -56,7 +56,7 @@
<br />
<div class="form-group">
<label>{l s='Choose one of the following:' mod='cheque'}</label>
<selectid="currency_payment" class="form-control" name="currency_payment">
<select id="currency_payment" class="form-control" name="currency_payment">
{foreach from=$currencies item=currency}
<option value="{$currency.id_currency}"{if isset($currencies) && $currency.id_currency == $cust_currency} selected="selected"{/if}>{$currency.name}</option>
{/foreach}
......
......@@ -212,7 +212,7 @@
{if isset($carrier.instance->delay[$cookie->id_lang])}
<i class="icon-info-sign"></i>
{strip}
{$first.instance->delay[$cookie->id_lang]|escape:'htmlall':'UTF-8'}
{$carrier.instance->delay[$cookie->id_lang]|escape:'htmlall':'UTF-8'}
&nbsp;
{if count($first.product_list) <= 1}
({l s='For this product:'}
......