diff --git a/Core/Foundation/Exception/Core_Foundation_Exception_Exception.php b/Core/Foundation/Exception/Core_Foundation_Exception_Exception.php index 16b46fee2..b7953c2ab 100644 --- a/Core/Foundation/Exception/Core_Foundation_Exception_Exception.php +++ b/Core/Foundation/Exception/Core_Foundation_Exception_Exception.php @@ -26,7 +26,7 @@ class Core_Foundation_Exception_Exception extends Exception { - public function __construct($message = null, $code = 0, Exception $previous = null) + public function __construct($message = null, $code = 0, ?Exception $previous = null) { parent::__construct($message, $code, $previous); } diff --git a/Core/Foundation/IoC/Core_Foundation_IoC_Container.php b/Core/Foundation/IoC/Core_Foundation_IoC_Container.php index 093ea79a6..6cc2faf66 100644 --- a/Core/Foundation/IoC/Core_Foundation_IoC_Container.php +++ b/Core/Foundation/IoC/Core_Foundation_IoC_Container.php @@ -105,9 +105,9 @@ class Core_Foundation_IoC_Container if ($classConstructor) { foreach ($classConstructor->getParameters() as $param) { - $paramClass = $param->getClass(); + $paramClass = ($param->getType() && !$param->getType()->isBuiltin()) ? new ReflectionClass($param->getType()>getName()) : null; if ($paramClass) { - $args[] = $this->doMake($param->getClass()->getName(), $alreadySeen); + $args[] = $this->doMake($paramClass->getName(), $alreadySeen); } elseif ($param->isDefaultValueAvailable()) { $args[] = $param->getDefaultValue(); } else { diff --git a/README.md b/README.md index 51ca925c0..7f126b4d4 100644 --- a/README.md +++ b/README.md @@ -47,8 +47,8 @@ The system compatibility will also be checked by the system with installation an #### Hosted Server Configurations * **Web server**: Apache 1.3, Apache 2.x, Nginx or Microsoft IIS -* **PHP version**: PHP 5.6+ to PHP 7.4 -* **MySQL version**: 5.1+ to 5.7 installed with a database created +* **PHP version**: PHP 8.1+ to PHP 8.4 +* **MySQL version**: 5.7+ to 8.4 installed with a database created * SSH or FTP access (ask your hosting service for your credentials) * In the PHP configuration ask your provider to set memory_limit to "128M", upload_max_filesize to "16M" , max_execution_time to "500" and allow_url_fopen "on" * SSL certificate if you plan to process payments internally (not using PayPal for instance) @@ -59,8 +59,8 @@ The system compatibility will also be checked by the system with installation an * **Supported operating system**: Windows, Mac, and Linux * **A prepared package**: WampServer (for Windows), Xampp (for Windows and Mac) or EasyPHP (for Windows) * **Web server**: Apache 1.3, Apache 2.x, Nginx or Microsoft IIS -* **PHP**: PHP 5.6+ to PHP 7.4 -* **MySQL** 5.1+ to 5.7 installed with a database created +* **PHP**: PHP 8.1+ to PHP 8.4 +* **MySQL** 5.7+ to 8.4 installed with a database created * In the PHP configuration, set memory_limit to "128M", upload_max_filesize to "16M" and max_execution_time to "500" * **Required PHP extensions**: PDO_MySQL, cURL, OpenSSL, SOAP, GD, SimpleXML, DOM, Zip, Phar @@ -88,7 +88,7 @@ Please don't disclose security vulnerabilities publicly. If you find any securit ### Documentation & Demo -#### QloApps Documentation +#### QloApps Documentation [https://qloapps.com/qlo-reservation-system](https://qloapps.com/qlo-reservation-system) #### QloApps Demo **Link** : https://demo.qloapps.com diff --git a/admin/filemanager/include/php_image_magician.php b/admin/filemanager/include/php_image_magician.php index 1f384d2e9..0922a7236 100644 --- a/admin/filemanager/include/php_image_magician.php +++ b/admin/filemanager/include/php_image_magician.php @@ -455,7 +455,7 @@ class imageLib // *** Crop this bad boy $crop = imagecreatetruecolor($newWidth, $newHeight); $this->keepTransparancy($optimalWidth, $optimalHeight, $crop); - imagecopyresampled($crop, $this->imageResized, 0, 0, $cropStartX, $cropStartY, $newWidth, $newHeight, $newWidth, $newHeight); + imagecopyresampled($crop, $this->imageResized, 0, 0, (int) $cropStartX, (int) $cropStartY, (int) $newWidth, (int) $newHeight, (int) $newWidth, (int) $newHeight); $this->imageResized = $crop; diff --git a/admin/themes/default/template/controllers/groups/helpers/tree/tree_node_folder_radio.tpl b/admin/themes/default/template/controllers/groups/helpers/tree/tree_node_folder_radio.tpl index 4e635fb1d..2076fd73a 100644 --- a/admin/themes/default/template/controllers/groups/helpers/tree/tree_node_folder_radio.tpl +++ b/admin/themes/default/template/controllers/groups/helpers/tree/tree_node_folder_radio.tpl @@ -29,6 +29,6 @@
';
}
- protected function _displayViewLink($token = null, $id)
+ protected function _displayViewLink($token, $id)
{
$_cacheLang['View'] = $this->l('View');
$href = Tools::safeOutput(self::$currentIndex.'&'.$this->identifier.'='.(int)$id.'&view'.$this->table.'&token='.($token != null ? $token : $this->token));
@@ -1820,7 +1820,7 @@ abstract class AdminTabCore
';
}
- protected function _displayEditLink($token = null, $id)
+ protected function _displayEditLink($token, $id)
{
$_cacheLang['Edit'] = $this->l('Edit');
$href = Tools::safeOutput(self::$currentIndex.'&'.$this->identifier.'='.(int)$id.'&update'.$this->table.'&token='.($token != null ? $token : $this->token));
@@ -1829,7 +1829,7 @@ abstract class AdminTabCore
';
}
- protected function _displayDeleteLink($token = null, $id)
+ protected function _displayDeleteLink($token, $id)
{
$_cacheLang['Delete'] = $this->l('Delete');
$_cacheLang['DeleteItem'] = $this->l('Delete item #', __CLASS__, true, false);
diff --git a/classes/AttributeGroup.php b/classes/AttributeGroup.php
index 385a9eb0d..b2804b726 100644
--- a/classes/AttributeGroup.php
+++ b/classes/AttributeGroup.php
@@ -161,7 +161,7 @@ class AttributeGroupCore extends ObjectModel
return false;
}
}
- $this->cleanPositions();
+ AttributeGroup::cleanPositions();
}
$return = parent::delete();
if ($return) {
diff --git a/classes/CMS.php b/classes/CMS.php
index 3476d9a25..5fdf9a9a8 100644
--- a/classes/CMS.php
+++ b/classes/CMS.php
@@ -74,7 +74,7 @@ class CMSCore extends ObjectModel
public function update($null_values = false)
{
if (parent::update($null_values)) {
- return $this->cleanPositions($this->id_cms_category);
+ return CMS::cleanPositions($this->id_cms_category);
}
return false;
}
@@ -82,12 +82,12 @@ class CMSCore extends ObjectModel
public function delete()
{
if (parent::delete()) {
- return $this->cleanPositions($this->id_cms_category);
+ return CMS::cleanPositions($this->id_cms_category);
}
return false;
}
- public static function getLinks($id_lang, $selection = null, $active = true, Link $link = null)
+ public static function getLinks($id_lang, $selection = null, $active = true, ?Link $link = null)
{
if (!$link) {
$link = Context::getContext()->link;
diff --git a/classes/CMSCategory.php b/classes/CMSCategory.php
index f45cc74a2..4d660ef02 100644
--- a/classes/CMSCategory.php
+++ b/classes/CMSCategory.php
@@ -105,7 +105,7 @@ class CMSCategoryCore extends ObjectModel
}
}
$ret = parent::add($autodate, $null_values);
- $this->cleanPositions($this->id_parent);
+ CMSCategory::cleanPositions($this->id_parent);
return $ret;
}
@@ -130,7 +130,7 @@ class CMSCategoryCore extends ObjectModel
*
* @return array Subcategories lite tree
*/
- public function recurseLiteCategTree($max_depth = 3, $currentDepth = 0, $id_lang = null, $excluded_ids_array = null, Link $link = null)
+ public function recurseLiteCategTree($max_depth = 3, $currentDepth = 0, $id_lang = null, $excluded_ids_array = null, ?Link $link = null)
{
if (!$link) {
$link = Context::getContext()->link;
@@ -164,7 +164,7 @@ class CMSCategoryCore extends ObjectModel
);
}
- public static function getRecurseCategory($id_lang = null, $current = 1, $active = 1, $links = 0, Link $link = null)
+ public static function getRecurseCategory($id_lang = null, $current = 1, $active = 1, $links = 0, ?Link $link = null)
{
if (!$link) {
$link = Context::getContext()->link;
@@ -487,7 +487,7 @@ class CMSCategoryCore extends ObjectModel
return $result['link_rewrite'];
}
- public function getLink(Link $link = null)
+ public function getLink(?Link $link = null)
{
if (!$link) {
$link = Context::getContext()->link;
diff --git a/classes/Carrier.php b/classes/Carrier.php
index 7e4fdc8fb..143d52d22 100644
--- a/classes/Carrier.php
+++ b/classes/Carrier.php
@@ -1057,12 +1057,12 @@ class CarrierCore extends ObjectModel
return $suffix;
}
- public function getIdTaxRulesGroup(Context $context = null)
+ public function getIdTaxRulesGroup(?Context $context = null)
{
return Carrier::getIdTaxRulesGroupByIdCarrier((int)$this->id, $context);
}
- public static function getIdTaxRulesGroupByIdCarrier($id_carrier, Context $context = null)
+ public static function getIdTaxRulesGroupByIdCarrier($id_carrier, ?Context $context = null)
{
if (!$context) {
$context = Context::getContext();
@@ -1079,7 +1079,7 @@ class CarrierCore extends ObjectModel
return Cache::retrieve($key);
}
- public function deleteTaxRulesGroup(array $shops = null)
+ public function deleteTaxRulesGroup(?array $shops = null)
{
if (!$shops) {
$shops = Shop::getContextListShopID();
diff --git a/classes/Cart.php b/classes/Cart.php
index aebd18936..2b3377838 100644
--- a/classes/Cart.php
+++ b/classes/Cart.php
@@ -1028,7 +1028,7 @@ class CartCore extends ObjectModel
* @param string $operator Indicate if quantity must be increased or decreased
*/
public function updateQty($quantity, $id_product, $id_product_attribute = null, $id_customization = false,
- $operator = 'up', $id_address_delivery = 0, Shop $shop = null, $auto_add_cart_rule = true)
+ $operator = 'up', $id_address_delivery = 0, ?Shop $shop = null, $auto_add_cart_rule = true)
{
if (!$shop) {
$shop = Context::getContext()->shop;
@@ -1620,7 +1620,7 @@ class CartCore extends ObjectModel
$param_product = true;
if (is_null($products)) {
$param_product = false;
- $products = $this->getProducts(false, false, null, false);
+ $products = $this->getProducts(false, false, null);
}
if ($type == Cart::ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING) {
@@ -2150,7 +2150,7 @@ class CartCore extends ObjectModel
return $cache[$cache_key];
}
- $product_list = $this->getProducts($flush, false, null, true);
+ $product_list = $this->getProducts($flush, false, null);
// Step 1 : Get product informations (warehouse_list and carrier_list), count warehouse
// Determine the best warehouse to determine the packages
// For that we count the number of time we can use a warehouse for a specific delivery address
@@ -2643,7 +2643,7 @@ class CartCore extends ObjectModel
* );
* If there are no carriers available for an address, return an empty array
*/
- public function getDeliveryOptionList(Country $default_country = null, $flush = false)
+ public function getDeliveryOptionList(?Country $default_country = null, $flush = false)
{
static $cache = array();
if (isset($cache[$this->id]) && !$flush) {
@@ -2979,7 +2979,7 @@ class CartCore extends ObjectModel
* @param bool $flush Force flushing cache
*
*/
- public function simulateCarriersOutput(Country $default_country = null, $flush = false)
+ public function simulateCarriersOutput(?Country $default_country = null, $flush = false)
{
$delivery_option_list = $this->getDeliveryOptionList($default_country, $flush);
@@ -3293,7 +3293,7 @@ class CartCore extends ObjectModel
* @param Country|null $default_country
* @return float Shipping total
*/
- public function getTotalShippingCost($delivery_option = null, $use_tax = true, Country $default_country = null)
+ public function getTotalShippingCost($delivery_option = null, $use_tax = true, ?Country $default_country = null)
{
if (isset(Context::getContext()->cookie->id_country)) {
$default_country = new Country(Context::getContext()->cookie->id_country);
@@ -3328,7 +3328,7 @@ class CartCore extends ObjectModel
* @param array|null $delivery_option
* @return float Shipping total
*/
- public function getCarrierCost($id_carrier, $useTax = true, Country $default_country = null, $delivery_option = null)
+ public function getCarrierCost($id_carrier, $useTax = true, ?Country $default_country = null, $delivery_option = null)
{
if (is_null($delivery_option)) {
$delivery_option = $this->getDeliveryOption($default_country);
@@ -3357,7 +3357,7 @@ class CartCore extends ObjectModel
/**
* @deprecated 1.5.0, use Cart->getPackageShippingCost()
*/
- public function getOrderShippingCost($id_carrier = null, $use_tax = true, Country $default_country = null, $product_list = null)
+ public function getOrderShippingCost($id_carrier = null, $use_tax = true, ?Country $default_country = null, $product_list = null)
{
Tools::displayAsDeprecated();
return $this->getPackageShippingCost((int)$id_carrier, $use_tax, $default_country, $product_list);
@@ -3375,7 +3375,7 @@ class CartCore extends ObjectModel
*
* @return float Shipping total
*/
- public function getPackageShippingCost($id_carrier = null, $use_tax = true, Country $default_country = null, $product_list = null, $id_zone = null)
+ public function getPackageShippingCost($id_carrier = null, $use_tax = true, ?Country $default_country = null, $product_list = null, $id_zone = null)
{
if ($this->isVirtualCart()) {
return 0;
@@ -4827,7 +4827,7 @@ class CartCore extends ObjectModel
// get bookings xaml data
$postData = trim(file_get_contents('php://input'));
libxml_use_internal_errors(true);
- $xml = simplexml_load_string(utf8_decode($postData));
+ $xml = simplexml_load_string(mb_convert_encoding($postData, 'ISO-8859-1'));
$cartData = json_decode(json_encode($xml, true));
$this->id_address_delivery = $cartData->cart->id_address_delivery;
@@ -4847,7 +4847,7 @@ class CartCore extends ObjectModel
return false;
}
- public function updateWs($autodate = true, $null_values = false)
+ public function updateWs($null_values = false)
{
$this->id_shop = Configuration::get('PS_SHOP_DEFAULT');
$objShop = new Shop($this->id_shop);
@@ -4856,14 +4856,14 @@ class CartCore extends ObjectModel
// get bookings xml data
$postData = trim(file_get_contents('php://input'));
libxml_use_internal_errors(true);
- $xml = simplexml_load_string(utf8_decode($postData));
+ $xml = simplexml_load_string(mb_convert_encoding($postData, 'ISO-8859-1'));
$cartData = json_decode(json_encode($xml, true));
$this->id_address_delivery = $cartData->cart->id_address_delivery;
$this->id_address_invoice = $cartData->cart->id_address_invoice;
- if ($this->update($autodate, $null_values)) {
+ if ($this->update($null_values)) {
// set bookings for the cart
$bookingRows = $cartData->cart->associations->cart_bookings->booking;
if (isset($bookingRows->id_hotel)) {
diff --git a/classes/CartRule.php b/classes/CartRule.php
index d8a340c6e..240015b37 100644
--- a/classes/CartRule.php
+++ b/classes/CartRule.php
@@ -263,7 +263,7 @@ class CartRuleCore extends ObjectModel
* @return array
* @throws PrestaShopDatabaseException
*/
- public static function getCustomerCartRules($id_lang, $id_customer, $active = false, $includeGeneric = true, $inStock = false, Cart $cart = null, $free_shipping_only = false, $highlight_only = false)
+ public static function getCustomerCartRules($id_lang, $id_customer, $active = false, $includeGeneric = true, $inStock = false, ?Cart $cart = null, $free_shipping_only = false, $highlight_only = false)
{
if (!CartRule::isFeatureActive()) {
return array();
@@ -926,7 +926,7 @@ class CartRuleCore extends ObjectModel
* @param bool $only_advance_payment_products to calculate discount applied only on products that have advance payment
* @return float|int|string
*/
- public function getContextualValue($use_tax, Context $context = null, $filter = null, $package = null, $use_cache = true, $only_advance_payment_products = false)
+ public function getContextualValue($use_tax, ?Context $context = null, $filter = null, $package = null, $use_cache = true, $only_advance_payment_products = false)
{
if (!CartRule::isFeatureActive()) {
return 0;
@@ -1361,8 +1361,7 @@ class CartRuleCore extends ObjectModel
.(in_array($type, array('carrier', 'shop')) ? ' AND t.deleted = 0' : '').
(in_array($type, array('carrier', 'shop')) ? ' ORDER BY t.name ASC ' : '').
(in_array($type, array('country', 'group', 'cart_rule')) && $i18n ? ' ORDER BY tl.name ASC ' : '').
- $sql_limit,
- false);
+ $sql_limit);
while ($row = Db::getInstance()->nextRow($resource)) {
$array[($row['selected'] || $this->{$type.'_restriction'} == 0) ? 'selected' : 'unselected'][] = $row;
}
@@ -1403,7 +1402,7 @@ class CartRuleCore extends ObjectModel
* @param Context|null $context
* @return mixed
*/
- public static function autoAddToCart(Context $context = null)
+ public static function autoAddToCart(?Context $context = null)
{
if ($context === null) {
$context = Context::getContext();
diff --git a/classes/Category.php b/classes/Category.php
index fcd044edd..7524d1688 100644
--- a/classes/Category.php
+++ b/classes/Category.php
@@ -136,10 +136,8 @@ class CategoryCore extends ObjectModel
{
parent::__construct($id_category, $id_lang, $id_shop);
- $link = new Link();
- $imgLink = $link->getMediaLink(_PS_CAT_IMG_DIR_.(int)$this->id.'.jpg'); // by webkul use media link for images
- $this->id_image = ($this->id && (bool)Tools::file_get_contents($imgLink)) ? (int)$this->id : false;
$this->image_dir = _PS_CAT_IMG_DIR_;
+ $this->id_image = ($this->id && file_exists($this->image_dir . (int) $this->id . '.jpg')) ? (int) $this->id : false;
}
public static function getDescriptionClean($description)
@@ -221,7 +219,7 @@ class CategoryCore extends ObjectModel
$ret = parent::update($null_values);
if ($changed && (!isset($this->doNotRegenerateNTree) || !$this->doNotRegenerateNTree)) {
- $this->cleanPositions((int)$this->id_parent);
+ Category::cleanPositions((int)$this->id_parent);
Category::regenerateEntireNtree();
$this->recalculateLevelDepth($this->id);
}
@@ -703,7 +701,7 @@ class CategoryCore extends ObjectModel
* @return array|int|false Products, number of products or false (no access)
* @throws PrestaShopDatabaseException
*/
- public function getProducts($id_lang, $p, $n, $order_by = null, $order_way = null, $get_total = false, $active = true, $random = false, $random_number_products = 1, $check_access = true, Context $context = null)
+ public function getProducts($id_lang, $p, $n, $order_by = null, $order_way = null, $get_total = false, $active = true, $random = false, $random_number_products = 1, $check_access = true, ?Context $context = null)
{
if (!$context) {
$context = Context::getContext();
@@ -823,7 +821,7 @@ class CategoryCore extends ObjectModel
return self::getChildren(Configuration::get('PS_HOME_CATEGORY'), $id_lang, $active, $id_shop);
}
- public static function getRootCategory($id_lang = null, Shop $shop = null)
+ public static function getRootCategory($id_lang = null, ?Shop $shop = null)
{
$context = Context::getContext();
if (is_null($id_lang)) {
@@ -970,7 +968,7 @@ class CategoryCore extends ObjectModel
* @param int $id_lang
* @return array
*/
- public static function getChildrenWithNbSelectedSubCat($id_parent, $selected_cat, $id_lang, Shop $shop = null, $use_shop_context = true)
+ public static function getChildrenWithNbSelectedSubCat($id_parent, $selected_cat, $id_lang, ?Shop $shop = null, $use_shop_context = true)
{
if (!$shop) {
$shop = Context::getContext()->shop;
@@ -1090,7 +1088,7 @@ class CategoryCore extends ObjectModel
return self::$_links[$id_category.'-'.$id_lang];
}
- public function getLink(Link $link = null, $id_lang = null)
+ public function getLink(?Link $link = null, $id_lang = null)
{
if (!$link) {
$link = Context::getContext()->link;
@@ -1564,7 +1562,7 @@ class CategoryCore extends ObjectModel
* @param Shop $shop
* @return bool
*/
- public function inShop(Shop $shop = null)
+ public function inShop(?Shop $shop = null)
{
if (!$shop) {
$shop = Context::getContext()->shop;
@@ -1576,7 +1574,7 @@ class CategoryCore extends ObjectModel
return ($this->nleft >= $interval['nleft'] && $this->nright <= $interval['nright']);
}
- public static function inShopStatic($id_category, Shop $shop = null)
+ public static function inShopStatic($id_category, ?Shop $shop = null)
{
if (!$shop || !is_object($shop)) {
$shop = Context::getContext()->shop;
diff --git a/classes/ConfigurationTest.php b/classes/ConfigurationTest.php
index 98bdaeb44..25c5599fb 100644
--- a/classes/ConfigurationTest.php
+++ b/classes/ConfigurationTest.php
@@ -145,14 +145,14 @@ class ConfigurationTestCore
public static function test_phpversion()
{
return (
- version_compare(substr(phpversion(), 0, 5), '5.6.0', '>=')
- && version_compare(substr(phpversion(), 0, 5), '8.0', '<')
+ version_compare(substr(phpversion(), 0, 5), '8.1.0', '>=')
+ && version_compare(substr(phpversion(), 0, 5), '8.5', '<')
);
}
public static function test_new_phpversion()
{
- return version_compare(substr(phpversion(), 0, 5), '5.6.0', '>=');
+ return version_compare(substr(phpversion(), 0, 5), '8.1.0', '>=');
}
public static function test_mysql_support()
@@ -188,7 +188,7 @@ class ConfigurationTestCore
public static function test_upload_max_filesize()
{
$upload_max_filesize = preg_replace('/[^0-9\.-]/', '', ini_get('upload_max_filesize'));
- if ($upload_max_filesize >= 16) {
+ if ($upload_max_filesize >= 2) {
return true;
}
return false;
diff --git a/classes/ConnectionsSource.php b/classes/ConnectionsSource.php
index a258b9d48..6c9dc5f9d 100644
--- a/classes/ConnectionsSource.php
+++ b/classes/ConnectionsSource.php
@@ -56,7 +56,7 @@ class ConnectionsSourceCore extends ObjectModel
return $result;
}
- public static function logHttpReferer(Cookie $cookie = null)
+ public static function logHttpReferer(?Cookie $cookie = null)
{
if (!$cookie) {
$cookie = Context::getContext()->cookie;
@@ -86,7 +86,7 @@ class ConnectionsSourceCore extends ObjectModel
return false;
}
- if ((preg_replace('/^www./', '', $parsed['host']) == preg_replace('/^www./', '', Tools::getHttpHost(false, false))) && !strncmp($parsed['path'], $parsed_host['path'], strlen(__PS_BASE_URI__))) {
+ if ((preg_replace('/^www./', '', $parsed['host']) == preg_replace('/^www./', '', Tools::getHttpHost(false, false, true))) && !strncmp($parsed['path'], $parsed_host['path'], strlen(__PS_BASE_URI__))) {
return false;
}
diff --git a/classes/Context.php b/classes/Context.php
index 69c1204b5..5461fce9e 100644
--- a/classes/Context.php
+++ b/classes/Context.php
@@ -29,7 +29,8 @@
*
* @since 1.5.0.1
*/
-class ContextCore
+#[\AllowDynamicProperties]
+ class ContextCore
{
/* @var Context */
protected static $instance;
diff --git a/classes/Cookie.php b/classes/Cookie.php
index 90dbc9509..de404e6ae 100644
--- a/classes/Cookie.php
+++ b/classes/Cookie.php
@@ -24,6 +24,7 @@
* International Registered Trademark & Property of PrestaShop SA
*/
+#[\AllowDynamicProperties]
class CookieCore
{
const SAMESITE_NONE = 'None';
@@ -351,7 +352,7 @@ class CookieCore
*/
protected function _setcookie($cookie = null)
{
- $length = (ini_get('mbstring.func_overload') & 2) ? mb_strlen($cookie, ini_get('default_charset')) : strlen($cookie);
+ $length = (ini_get('mbstring.func_overload') & 2) ? mb_strlen($cookie, ini_get('default_charset')) : Tools::strlen($cookie);
if ($length >= 1048576) {
return false;
}
diff --git a/classes/Country.php b/classes/Country.php
index 8782814e0..a2990ac09 100644
--- a/classes/Country.php
+++ b/classes/Country.php
@@ -254,7 +254,7 @@ class CountryCore extends ObjectModel
* @param string $country Country Name
* @return int Country ID
*/
- public static function getIdByName($id_lang = null, $country)
+ public static function getIdByName($id_lang, $country)
{
$sql = '
SELECT `id_country`
diff --git a/classes/Customer.php b/classes/Customer.php
index fd5fe9f97..0c2ac0023 100644
--- a/classes/Customer.php
+++ b/classes/Customer.php
@@ -242,7 +242,9 @@ class CustomerCore extends ObjectModel
$this->secure_key = md5(uniqid(rand(), true));
$this->last_passwd_gen = date('Y-m-d H:i:s', strtotime('-'.Configuration::get('PS_PASSWD_TIME_FRONT').'minutes'));
- if ($this->newsletter && !Validate::isDate($this->newsletter_date_add)) {
+ if ($this->newsletter
+ && (!$this->newsletter_date_add || !Validate::isDate($this->newsletter_date_add))
+ ) {
$this->newsletter_date_add = date('Y-m-d H:i:s');
}
@@ -795,7 +797,7 @@ class CustomerCore extends ObjectModel
return self::$_defaultGroupId[(int)$id_customer];
}
- public static function getCurrentCountry($id_customer, Cart $cart = null)
+ public static function getCurrentCountry($id_customer, ?Cart $cart = null)
{
if (!$cart) {
$cart = Context::getContext()->cart;
diff --git a/classes/DateRange.php b/classes/DateRange.php
index 075d212b7..21d734a16 100644
--- a/classes/DateRange.php
+++ b/classes/DateRange.php
@@ -55,7 +55,7 @@ class DateRangeCore extends ObjectModel
$rangeSize = 86399;
$dateRange = new DateRange();
$dateRange->time_start = date('Y-m-d');
- $dateRange->time_end = strftime('%Y-%m-%d %H:%M:%S', strtotime($dateRange->time_start) + $rangeSize);
+ $dateRange->time_end = date('Y-m-d H:i:s', strtotime($dateRange->time_start) + $rangeSize);
$dateRange->add();
return $dateRange->id;
}
diff --git a/classes/Discount.php b/classes/Discount.php
index 82f3769fe..66ab5711b 100644
--- a/classes/Discount.php
+++ b/classes/Discount.php
@@ -175,7 +175,7 @@ class DiscountCore extends CartRule
/**
* @deprecated 1.5.0.1
*/
- public static function getCustomerDiscounts($id_lang, $id_customer, $active = false, $includeGenericOnes = true, $hasStock = false, Cart $cart = null)
+ public static function getCustomerDiscounts($id_lang, $id_customer, $active = false, $includeGenericOnes = true, $hasStock = false, ?Cart $cart = null)
{
return parent::getCustomerCartRules($id_lang, $id_customer, $active, $includeGenericOnes, $hasStock, $cart);
}
@@ -191,7 +191,7 @@ class DiscountCore extends CartRule
/**
* @deprecated 1.5.0.1
*/
- public function getValue($nb_discounts = 0, $order_total_products = 0, $shipping_fees = 0, $id_cart = false, $useTax = true, Currency $currency = null, Shop $shop = null)
+ public function getValue($nb_discounts = 0, $order_total_products = 0, $shipping_fees = 0, $id_cart = false, $useTax = true, ?Currency $currency = null, ?Shop $shop = null)
{
$context = Context::getContext();
if ((int)$id_cart) {
diff --git a/classes/Feature.php b/classes/Feature.php
index 8d9816263..9b9035886 100644
--- a/classes/Feature.php
+++ b/classes/Feature.php
@@ -151,7 +151,7 @@ class FeatureCore extends ObjectModel
}
/* Reinitializing position */
- $this->cleanPositions();
+ static::cleanPositions();
return $return;
}
diff --git a/classes/Group.php b/classes/Group.php
index 1ea01a9e1..75fca9585 100644
--- a/classes/Group.php
+++ b/classes/Group.php
@@ -189,7 +189,7 @@ class GroupCore extends ObjectModel
Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'category_group` WHERE `id_group` = '.(int)$this->id);
Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'group_reduction` WHERE `id_group` = '.(int)$this->id);
Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'product_group_reduction_cache` WHERE `id_group` = '.(int)$this->id);
- $this->truncateModulesRestrictions($this->id);
+ self::truncateModulesRestrictions($this->id);
// Add default group (id 3) to customers without groups
Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'customer_group` (
diff --git a/classes/Hook.php b/classes/Hook.php
index 6604c73dd..c408813a2 100644
--- a/classes/Hook.php
+++ b/classes/Hook.php
@@ -618,7 +618,7 @@ class HookCore extends ObjectModel
{
return '
'
.Tools::safeOutput($moduleInstance->displayName).'
diff --git a/classes/ImageManager.php b/classes/ImageManager.php
index 015c83372..c811fdbcf 100644
--- a/classes/ImageManager.php
+++ b/classes/ImageManager.php
@@ -80,7 +80,7 @@ class ImageManagerCore
$size = $y / ($x / $max_x);
}
- ImageManager::resize($image, _PS_TMP_IMG_DIR_.$cache_image, $ratio_x, $size, $image_type);
+ ImageManager::resize($image, _PS_TMP_IMG_DIR_.$cache_image, (int)$ratio_x, (int)$size, $image_type);
}
}
// Relative link will always work, whatever the base uri set in the admin
diff --git a/classes/Link.php b/classes/Link.php
index 69d3f11de..f5c58e6b9 100644
--- a/classes/Link.php
+++ b/classes/Link.php
@@ -483,7 +483,7 @@ class LinkCore
}
} else {
// @FIXME html_entity_decode has been added due to '&' => '%3B' ...
- $request = html_entity_decode($request);
+ $request = html_entity_decode($request ?? '');
if ($request_url_encode) {
$request = urlencode($request);
}
@@ -511,7 +511,7 @@ class LinkCore
* @param int $id_lang Language ID
* @return string link
*/
- public function getLanguageLink($id_lang, Context $context = null)
+ public function getLanguageLink($id_lang, ?Context $context = null)
{
if (!$context) {
$context = Context::getContext();
@@ -644,7 +644,7 @@ class LinkCore
return $url.(!strstr($url, '?') ? '?' : '&').'orderby='.urlencode($orderby).'&orderway='.urlencode($orderway);
}
- protected function getLangLink($id_lang = null, Context $context = null, $id_shop = null)
+ protected function getLangLink($id_lang = null, ?Context $context = null, $id_shop = null)
{
if (!$context) {
$context = Context::getContext();
@@ -700,8 +700,8 @@ class LinkCore
public function matchQuickLink($url)
{
- $quicklink = $this->getQuickLink($url);
- if (isset($quicklink) && $quicklink === ($this->getQuickLink($_SERVER['REQUEST_URI']))) {
+ $quicklink = Link::getQuickLink($url);
+ if (isset($quicklink) && $quicklink === (Link::getQuickLink($_SERVER['REQUEST_URI']))) {
return true;
} else {
return false;
diff --git a/classes/Mail.php b/classes/Mail.php
index 6483afabd..b11a45225 100644
--- a/classes/Mail.php
+++ b/classes/Mail.php
@@ -24,7 +24,15 @@
* International Registered Trademark & Property of PrestaShop SA
*/
-include_once(_PS_SWIFT_DIR_.'swift_required.php');
+include_once(_PS_TOOL_DIR_.'mailer/autoload.php');
+
+use Symfony\Component\Mailer\Exception\ExceptionInterface;
+use Symfony\Component\Mailer\Mailer;
+use Symfony\Component\Mailer\Transport\SendmailTransport;
+use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport;
+use Symfony\Component\Mime\Address;
+use Symfony\Component\Mime\Email;
+use Symfony\Component\Mime\Header\IdentificationHeader;
class MailCore extends ObjectModel
{
@@ -84,10 +92,23 @@ class MailCore extends ObjectModel
* @param string $reply_to Email address for setting the Reply-To header
* @return bool|int Whether sending was successful. If not at all, false, otherwise amount of recipients succeeded.
*/
- public static function Send($id_lang, $template, $subject, $template_vars, $to,
- $to_name = null, $from = null, $from_name = null, $file_attachment = null, $mode_smtp = null,
- $template_path = _PS_MAIL_DIR_, $die = false, $id_shop = null, $bcc = null, $reply_to = null)
- {
+ public static function Send($id_lang,
+ $template,
+ $subject,
+ $template_vars,
+ $to,
+ $to_name = null,
+ $from = null,
+ $from_name = null,
+ $file_attachment = null,
+ $mode_smtp = null,
+ $template_path = _PS_MAIL_DIR_,
+ $die = false,
+ $id_shop = null,
+ $bcc = null,
+ $reply_to = null,
+ $reply_to_name = ''
+ ) {
if (!$id_shop) {
$id_shop = Context::getContext()->shop->id;
}
@@ -121,9 +142,14 @@ class MailCore extends ObjectModel
}
}
- if (!isset($configuration['PS_MAIL_SMTP_ENCRYPTION']) || Tools::strtolower($configuration['PS_MAIL_SMTP_ENCRYPTION']) === 'off') {
- $configuration['PS_MAIL_SMTP_ENCRYPTION'] = false;
+ if (!isset($configuration['PS_MAIL_SMTP_ENCRYPTION'])
+ || Tools::strtolower($configuration['PS_MAIL_SMTP_ENCRYPTION']) === 'off'
+ ) {
+ $isTls = false;
+ } else {
+ $isTls = true;
}
+
if (!isset($configuration['PS_MAIL_SMTP_PORT'])) {
$configuration['PS_MAIL_SMTP_PORT'] = 'default';
}
@@ -180,7 +206,7 @@ class MailCore extends ObjectModel
try {
/* Construct multiple recipients list if needed */
- $message = Swift_Message::newInstance();
+ $email = new Email();
if (is_array($to) && isset($to)) {
foreach ($to as $key => $addr) {
$addr = trim($addr);
@@ -196,14 +222,14 @@ class MailCore extends ObjectModel
}
$addrName = (($addrName == null || $addrName == $addr || !Validate::isGenericName($addrName)) ? '' : self::mimeEncode($addrName));
- $message->addTo($addr, $addrName);
+ $email->addTo(new Address($addr, $addrName));
}
$to_plugin = $to[0];
} else {
/* Simple recipient, one address */
$to_plugin = $to;
$to_name = (($to_name == null || $to_name == $to) ? '' : self::mimeEncode($to_name));
- $message->addTo($to, $to_name);
+ $email->addTo(new Address($to, $to_name));
}
if (isset($bcc) && is_array($bcc)) {
@@ -213,10 +239,10 @@ class MailCore extends ObjectModel
Tools::dieOrLog(Tools::displayError('Error: invalid e-mail address'), $die);
return false;
}
- $message->addBcc($addr);
+ $email->addBcc(new Address($addr));
}
} elseif (isset($bcc)) {
- $message->addBcc($bcc);
+ $email->addBcc(new Address($bcc));
}
/* Connect with the appropriate configuration */
@@ -226,18 +252,19 @@ class MailCore extends ObjectModel
return false;
}
- $connection = Swift_SmtpTransport::newInstance($configuration['PS_MAIL_SERVER'], $configuration['PS_MAIL_SMTP_PORT'], $configuration['PS_MAIL_SMTP_ENCRYPTION'])
+ $transport = (new EsmtpTransport(
+ $configuration['PS_MAIL_SERVER'],
+ $configuration['PS_MAIL_SMTP_PORT'],
+ $isTls
+ ))
->setUsername($configuration['PS_MAIL_USER'])
->setPassword($configuration['PS_MAIL_PASSWD']);
} else {
- $connection = Swift_MailTransport::newInstance();
+ $transport = new SendmailTransport();
}
- if (!$connection) {
- return false;
- }
- $swift = Swift_Mailer::newInstance($connection);
+ $mailer = new Mailer($transport);
/* Get templates content */
$iso = Language::getIsoById((int)$id_lang);
if (!$iso) {
@@ -277,7 +304,7 @@ class MailCore extends ObjectModel
'id_lang' => (int)$id_lang
), null, true);
$template_html .= Tools::file_get_contents($template_path.$iso_template.'.html');
- $template_txt .= strip_tags(html_entity_decode(Tools::file_get_contents($template_path.$iso_template.'.txt'), null, 'utf-8'));
+ $template_txt .= strip_tags(html_entity_decode(Tools::file_get_contents($template_path.$iso_template.'.txt'), ENT_COMPAT, 'utf-8'));
Hook::exec('actionEmailAddAfterContent', array(
'template' => $template,
'template_html' => &$template_html,
@@ -300,19 +327,20 @@ class MailCore extends ObjectModel
$subject = '[' . strip_tags($configuration['PS_SHOP_NAME']) . '] ' . $subject;
}
- $message->setSubject($subject);
-
- $message->setCharset('utf-8');
+ $email->subject($subject);
/* Set Message-ID - getmypid() is blocked on some hosting */
- $message->setId(Mail::generateId());
+ $email
+ ->getHeaders()
+ ->add(new IdentificationHeader('Message-ID', Mail::generateId()))
+ ;
if (!($reply_to && Validate::isEmail($reply_to))) {
$reply_to = $from;
}
if (isset($reply_to) && $reply_to) {
- $message->setReplyTo($reply_to);
+ $email->replyTo(new Address($reply_to, (string) $reply_to_name));
}
$template_vars = array_map(array('Tools', 'htmlentitiesDecodeUTF8'), $template_vars);
@@ -328,10 +356,11 @@ class MailCore extends ObjectModel
}
}
ShopUrl::cacheMainDomainForShop((int)$id_shop);
- /* don't attach the logo as */
+ /* don't attach the logo as */
if (isset($logo)) {
- $template_vars['{shop_logo}'] = $message->embed(Swift_Image::fromPath($logo));
+ $template_vars['{shop_logo}'] = 'cid:shop_logo';
+ $email->embedFromPath($logo, 'shop_logo');
}
if ((Context::getContext()->link instanceof Link) === false) {
@@ -344,22 +373,31 @@ class MailCore extends ObjectModel
$template_vars['{guest_tracking_url}'] = Context::getContext()->link->getPageLink('guest-tracking', true, $id_lang, null, false, $id_shop);
$template_vars['{history_url}'] = Context::getContext()->link->getPageLink('history', true, $id_lang, null, false, $id_shop);
$template_vars['{color}'] = Tools::safeOutput(Configuration::get('PS_MAIL_COLOR', null, null, $id_shop));
+
// Get extra template_vars
$extra_template_vars = array();
+
Hook::exec('actionGetExtraMailTemplateVars', array(
'template' => $template,
'template_vars' => $template_vars,
'extra_template_vars' => &$extra_template_vars,
'id_lang' => (int)$id_lang
), null, true);
+
$template_vars = array_merge($template_vars, $extra_template_vars);
- $swift->registerPlugin(new Swift_Plugins_DecoratorPlugin(array($to_plugin => $template_vars)));
- if ($configuration['PS_MAIL_TYPE'] == Mail::TYPE_BOTH || $configuration['PS_MAIL_TYPE'] == Mail::TYPE_TEXT) {
- $message->addPart($template_txt, 'text/plain', 'utf-8');
- }
+
if ($configuration['PS_MAIL_TYPE'] == Mail::TYPE_BOTH || $configuration['PS_MAIL_TYPE'] == Mail::TYPE_HTML) {
- $message->addPart($template_html, 'text/html', 'utf-8');
+ $template_html = strtr($template_html, $template_vars);
+ $email->html($template_html);
+ if ($configuration['PS_MAIL_TYPE'] == Mail::TYPE_BOTH) {
+ $template_txt = strtr($template_txt, $template_vars);
+ $email->text($template_txt);
+ }
+ } else {
+ $template_txt = strtr($template_txt, $template_vars);
+ $email->text($template_txt);
}
+
if ($file_attachment && !empty($file_attachment)) {
// Multiple attachments?
if (!is_array(current($file_attachment))) {
@@ -368,24 +406,33 @@ class MailCore extends ObjectModel
foreach ($file_attachment as $attachment) {
if (isset($attachment['content']) && isset($attachment['name']) && isset($attachment['mime'])) {
- $message->attach(Swift_Attachment::newInstance()->setFilename($attachment['name'])->setContentType($attachment['mime'])->setBody($attachment['content']));
+ $email->attach($attachment['content'], $attachment['name'], $attachment['mime']);
}
}
}
/* Send mail */
- $message->setFrom(array($from => $from_name));
- $send = $swift->send($message);
+ $email->from(new Address($from, (string) $from_name));
+
+ // Hook to alter Symfony Mailer before sending mail
+ Hook::exec('actionMailAlterMessageBeforeSend', [
+ 'message' => &$message,
+ 'message' => &$email,
+ ]);
+
+ $mailer->send($email);
ShopUrl::resetMainDomainCache();
- if ($send && Configuration::get('PS_LOG_EMAILS')) {
+ if (Configuration::get('PS_LOG_EMAILS')) {
$mail = new Mail();
$mail->template = Tools::substr($template, 0, 62);
- $mail->subject = Tools::substr($subject, 0, 254);
+ $mail->subject = Tools::substr($email->getSubject(), 0, 255);
$mail->id_lang = (int)$id_lang;
- $recipients_to = $message->getTo();
- $recipients_cc = $message->getCc();
- $recipients_bcc = $message->getBcc();
+
+ $recipients_to = self::convertAdressesToArray($email->getTo());
+ $recipients_cc = self::convertAdressesToArray($email->getCc());
+ $recipients_bcc = self::convertAdressesToArray($email->getBcc());
+
if (!is_array($recipients_to)) {
$recipients_to = array();
}
@@ -395,23 +442,21 @@ class MailCore extends ObjectModel
if (!is_array($recipients_bcc)) {
$recipients_bcc = array();
}
- foreach (array_merge($recipients_to, $recipients_cc, $recipients_bcc) as $email => $recipient_name) {
- /** @var Swift_Address $recipient */
+
+ foreach (array_merge($recipients_to, $recipients_cc, $recipients_bcc) as $emailAlias => $recipientName) {
$mail->id = null;
- $mail->recipient = Tools::substr($email, 0, 126);
+ $mail->recipient = Tools::substr($emailAlias, 0, 255);
$mail->add();
}
}
- return $send;
- } catch (Swift_SwiftException $e) {
+ return true;
+ } catch (ExceptionInterface $e) {
PrestaShopLogger::addLog(
- 'Swift Error: '.$e->getMessage(),
+ 'Mailer Error: ' . $e->getMessage(),
3,
null,
- 'Swift_Message',
- null,
- true
+ 'MailerMessage'
);
return false;
@@ -451,34 +496,39 @@ class MailCore extends ObjectModel
* @param bool|string $smtp_encryption Encryption type. "off" or false disable encryption.
* @return bool|string True if succeeded, otherwise the error message
*/
- public static function sendMailTest($smtp_checked, $smtp_server, $content, $subject, $type, $to, $from, $smtp_login, $smtp_password, $smtp_port = 25, $smtp_encryption)
+ public static function sendMailTest($smtp_checked, $smtp_server, $content, $subject, $type, $to, $from, $smtp_login, $smtp_password, $smtp_port, $smtp_encryption)
{
$result = false;
try {
if ($smtp_checked) {
if (Tools::strtolower($smtp_encryption) === 'off') {
- $smtp_encryption = false;
+ $isTls = false;
+ } else {
+ $isTls = true;
}
- $smtp = Swift_SmtpTransport::newInstance($smtp_server, $smtp_port, $smtp_encryption)
+ $transport = (new EsmtpTransport(
+ $smtp_server,
+ $smtp_port,
+ $isTls
+ ))
->setUsername($smtp_login)
- ->setPassword($smtp_password);
- $swift = Swift_Mailer::newInstance($smtp);
+ ->setPassword($smtp_password)
+ ;
} else {
- $swift = Swift_Mailer::newInstance(Swift_MailTransport::newInstance());
+ $transport = new SendmailTransport();
}
- $message = Swift_Message::newInstance();
+ $mailer = new Mailer($transport);
+ $email = (new Email())
+ ->from($from)
+ ->to($to)
+ ->subject($subject)
+ ->text($content)
+ ;
- $message
- ->setFrom($from)
- ->setTo($to)
- ->setSubject($subject)
- ->setBody($content);
-
- if ($swift->send($message)) {
- $result = true;
- }
- } catch (Swift_SwiftException $e) {
+ $mailer->send($signedEmail ?? $email);
+ $result = true;
+ } catch (ExceptionInterface $e) {
$result = $e->getMessage();
}
@@ -493,7 +543,7 @@ class MailCore extends ObjectModel
* @param string $string raw sentence (write directly in file)
* @return mixed
*/
- public static function l($string, $id_lang = null, Context $context = null)
+ public static function l($string, $id_lang = null, ?Context $context = null)
{
global $_LANGMAIL;
@@ -523,15 +573,15 @@ class MailCore extends ObjectModel
return str_replace('"', '"', Tools::stripslashes((array_key_exists($key, $_LANGMAIL) && !empty($_LANGMAIL[$key])) ? $_LANGMAIL[$key] : $string));
}
- /* Rewrite of Swift_Message::generateId() without getmypid() */
+ /* Generate a Message-ID */
protected static function generateId($idstring = null)
{
- $midparams = array(
- 'utctime' => gmstrftime('%Y%m%d%H%M%S'),
+ $midparams = [
+ 'utctime' => date('YmdHis'),
'randint' => mt_rand(),
- 'customstr' => (preg_match("/^(? ((isset($_SERVER['SERVER_NAME']) && !empty($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : php_uname('n')),
- );
+ 'customstr' => ($idstring !== null && preg_match('/^(? !empty($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : php_uname('n'),
+ ];
return vsprintf("%s.%d.%s@%s", $midparams);
}
@@ -624,4 +674,20 @@ class MailCore extends ObjectModel
return '';
}
-}
+
+ /**
+ * @param Address[] $addresses
+ *
+ * @return array