Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e2c5333

Browse files
committed
Fix conflicts
2 parents 970b827 + 300b5a9 commit e2c5333

17 files changed

Lines changed: 182 additions & 64 deletions

File tree

classes/Address.php

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -545,48 +545,73 @@ public static function initialize($id_address = null, $with_geoloc = false)
545545
{
546546
$context = Context::getContext();
547547

548+
/*
549+
* To save performance, we cache the result, here we resolve a unique hash
550+
* depending on the parameters used to initialize the address.
551+
*/
548552
if ($id_address) {
549553
$context_hash = (int) $id_address;
550554
} elseif ($with_geoloc && isset($context->customer->geoloc_id_country)) {
551-
$context_hash = md5((int) $context->customer->geoloc_id_country . '-' . (int) $context->customer->id_state . '-' .
552-
$context->customer->postcode);
555+
$context_hash = md5((int) $context->customer->geoloc_id_country . '-' . (int) $context->customer->id_state . '-' . $context->customer->postcode);
553556
} else {
554557
$context_hash = md5((string) $context->country->id);
555558
}
556559

557560
$cache_id = 'Address::initialize_' . $context_hash;
558561

559562
if (!Cache::isStored($cache_id)) {
560-
// if an id_address has been specified retrieve the address
563+
/*
564+
* Case 1 - Specific address ID is provided. We just load it.
565+
*/
561566
if ($id_address) {
562567
$address = new Address((int) $id_address);
563568

564569
if (!Validate::isLoadedObject($address)) {
565570
throw new PrestaShopException('Invalid address #' . (int) $id_address);
566571
}
572+
/*
573+
* Case 2 - We try to use geolocation information if allowed. However, geoloc_id_country
574+
* is not set to the customer anywhere in the current codebase. Most geolocation logic either
575+
* native or from modules depend on setting the country directly in the context. So, this will
576+
* probably never work.
577+
*/
567578
} elseif ($with_geoloc && isset($context->customer->geoloc_id_country)) {
568579
$address = new Address();
569580
$address->id_country = (int) $context->customer->geoloc_id_country;
570581
$address->id_state = (int) $context->customer->id_state;
571582
$address->postcode = $context->customer->postcode;
583+
/*
584+
* Case 3 - There is already a country set in the context and it's not the shop country.
585+
* This is pretty common if you either use geolocation modules or let the user select his country
586+
* via a custom country selector on the front office.
587+
*/
572588
} elseif ((int) $context->country->id && ((int) $context->country->id != Configuration::get('PS_SHOP_COUNTRY_ID'))) {
573589
$address = new Address();
574590
$address->id_country = (int) $context->country->id;
575591
$address->id_state = 0;
576592
$address->postcode = '0';
593+
/*
594+
* Case 4 - If there is no country in the context, or the country is the same, we use the shop country.
595+
* We also assign the state and postcode if available.
596+
*/
577597
} elseif ((int) Configuration::get('PS_SHOP_COUNTRY_ID')) {
578598
// set the default address
579599
$address = new Address();
580600
$address->id_country = (int) Configuration::get('PS_SHOP_COUNTRY_ID');
581601
$address->id_state = (int) Configuration::get('PS_SHOP_STATE_ID');
582602
$address->postcode = Configuration::get('PS_SHOP_CODE');
603+
/*
604+
* Case 5 - As a last resort, we just use the default country. It will most likely be the shop country anyway.
605+
*/
583606
} else {
584607
// set the default address
585608
$address = new Address();
586609
$address->id_country = (int) Configuration::get('PS_COUNTRY_DEFAULT');
587610
$address->id_state = 0;
588611
$address->postcode = '0';
589612
}
613+
614+
// Store it in cache, so we don't have to re-initialize it again
590615
Cache::store($cache_id, $address);
591616

592617
return $address;

classes/Carrier.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,6 +1359,11 @@ public function deleteTaxRulesGroup(?array $shops = null)
13591359
*/
13601360
public function getTaxesRate(?Address $address = null)
13611361
{
1362+
/*
1363+
* If no address is provided, we let Address::initialize instantiate one blank
1364+
* for us with the all default/fallback data we can get. We get a blank Address
1365+
* object with a country, sometimes even state and postcode.
1366+
*/
13621367
if (!$address || !$address->id_country) {
13631368
$address = Address::initialize();
13641369
}

classes/Dispatcher.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,14 @@ private function buildRequestUri($requestUri, $isMultiLanguageActivated, ?Shop $
537537
// If friendly URLs are activated and there are more than one languages on the shop, we handle the language
538538
// Set $_GET['isolang'] and remove the language part from the request URI
539539
if ($this->use_routes && $isMultiLanguageActivated) {
540-
// If we find a language in the URL, we assign it and remove it from the URL
540+
/*
541+
* If we find a language in the URL, we assign it and remove it from the URL
542+
*
543+
* @todo Please note that this does not validate the language code in any way.
544+
* It would be better to check if the language actually exists in the shop directly.
545+
* If not, the default language remains used and the url is redirected to the URL of
546+
* the default language later, but only because of the canonical redirect.
547+
*/
541548
if (preg_match('#^/([a-z]{2})(?:/.*)?$#', $requestUri, $matches)) {
542549
$_GET['isolang'] = $matches[1];
543550
$requestUri = substr($requestUri, 3);

classes/Group.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,10 +214,20 @@ public function update($autodate = true, $null_values = false)
214214

215215
public function delete()
216216
{
217-
if ($this->id == (int) Configuration::get('PS_CUSTOMER_GROUP')) {
217+
// Prevent calling the logic in case of an invalid object
218+
if (empty($this->id)) {
218219
return false;
219220
}
220221

222+
// Prevent deletion of groups currently used in configuration
223+
if (in_array($this->id, [
224+
(int) Configuration::get('PS_UNIDENTIFIED_GROUP'),
225+
(int) Configuration::get('PS_GUEST_GROUP'),
226+
(int) Configuration::get('PS_CUSTOMER_GROUP'),
227+
])) {
228+
throw new PrestaShopException('You cannot delete a group that is used in the shop configuration.');
229+
}
230+
221231
if (parent::delete()) {
222232
Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'cart_rule_group` WHERE `id_group` = ' . (int) $this->id);
223233
Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'customer_group` WHERE `id_group` = ' . (int) $this->id);

classes/Product.php

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3423,22 +3423,47 @@ public static function getPriceStatic(
34233423
}
34243424
}
34253425

3426+
/*
3427+
* Instantiate currency - either by using the one in the context or by getting the default currency
3428+
*/
34263429
$id_currency = Validate::isLoadedObject($context->currency) ? (int) $context->currency->id : Currency::getDefaultCurrencyId();
34273430

3431+
/*
3432+
* Now, we need to retrieve address information. We need it to precisely calculate the price,
3433+
* without it, we cannot resolve proper tax, special prices to be used etc.
3434+
*
3435+
* First, if no address ID has been provided, we try to get it from the cart in the context.
3436+
*/
34283437
if (!$id_address && Validate::isLoadedObject($cur_cart)) {
34293438
$id_address = $cur_cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')};
34303439
}
34313440

3432-
// retrieve address informations
3441+
/*
3442+
* Now, we either have the address ID or still null - which is not a problem.
3443+
*
3444+
* Address::initialize will take care of everything and just return an address with required data.
3445+
* We either get a filled Address object if we had an ID.
3446+
* Or, we get a blank Address object with a country, sometimes even state and postcode. Depends on
3447+
* geolocation enabled or if we already assigned some country to the context. See the method insides
3448+
* to see the logic.
3449+
*/
34333450
$address = Address::initialize($id_address, true);
3451+
3452+
// Now, we extract other required data from the address
34343453
$id_country = (int) $address->id_country;
34353454
$id_state = (int) $address->id_state;
34363455
$zipcode = $address->postcode;
34373456

3457+
// Check if tax has been enabled in configuration, if not, it will be always false
34383458
if (!Configuration::get('PS_TAX')) {
34393459
$usetax = false;
34403460
}
34413461

3462+
/*
3463+
* If the customer has a valid VAT number, we calculate the price without tax.
3464+
* @TODO - This is historic and should be totally refactored for multiple reasons.
3465+
* No validation, only one address considered, dependence on configuration from legacy module.
3466+
*/
34423467
if (
34433468
$usetax != false
34443469
&& !empty($address->vat_number)
@@ -3448,6 +3473,7 @@ public static function getPriceStatic(
34483473
$usetax = false;
34493474
}
34503475

3476+
// If no customer ID has been provided, we try to get it from the context, if set
34513477
if (null === $id_customer && Validate::isLoadedObject($context->customer)) {
34523478
$id_customer = $context->customer->id;
34533479
}
@@ -6556,6 +6582,11 @@ public static function getIdTaxRulesGroupByIdProduct($id_product, ?Context $cont
65566582
*/
65576583
public function getTaxesRate(?Address $address = null)
65586584
{
6585+
/*
6586+
* If no address is provided, we let Address::initialize instantiate one blank
6587+
* for us with the all default/fallback data we can get. We get a blank Address
6588+
* object with a country, sometimes even state and postcode.
6589+
*/
65596590
if (!$address || !$address->id_country) {
65606591
$address = Address::initialize();
65616592
}

classes/Tools.php

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,10 @@ public static function getIsset($key)
536536
}
537537

538538
/**
539-
* Change language in cookie while clicking on a flag.
539+
* This method was named "Change language in cookie while clicking on a flag.",
540+
* but as of 25.12.2025, it does not really work at all. Language detection will
541+
* never work because the language is exclusively determined by the URL, the isolang
542+
* is always set and the HTTP_ACCEPT_LANGUAGE is not parsed properly anyway.
540543
*
541544
* @return string iso code
542545
*/
@@ -592,7 +595,17 @@ public static function setCookieLanguage($cookie = null)
592595
}
593596

594597
/**
595-
* If necessary change cookie language ID and context language.
598+
* Detects proper id_language by the isolang parameter in the request and assigns
599+
* it to the context and cookie. The method naming is a bit confusing as it does
600+
* not switch anything. Language is exclusively determined by the URL.
601+
*
602+
* @todo - The behavior is a bit non stable, it should probably throw exceptions
603+
* or somehow notify that nonsense is being present. If you for example pass a non
604+
* existent language in the URL and you get "zz" in isolang, you will end up with:
605+
* $_GET['isolang'] = zz
606+
* $_GET['id_lang'] = null
607+
* $context->cookie->id_lang = default language id from config.inc.php
608+
* $context->language = default language from config.inc.php
596609
*
597610
* @param Context|null $context
598611
*
@@ -611,6 +624,11 @@ public static function switchLanguage(?Context $context = null)
611624
return;
612625
}
613626

627+
/*
628+
* This takes the isolang parameter from $_GET, converts it to an id_lang
629+
* and assigns it into the GET. The isolang in the request always set by the Dispatcher.
630+
* Either to a language code from the URL or the default language.
631+
*/
614632
if (
615633
($iso = Tools::getValue('isolang'))
616634
&& Validate::isLanguageIsoCode($iso)
@@ -622,6 +640,16 @@ public static function switchLanguage(?Context $context = null)
622640
// Only switch if new ID is different from old ID
623641
$newLanguageId = (int) Tools::getValue('id_lang');
624642

643+
/*
644+
* If we got a sensible language ID from the request, we will set it into the cookie
645+
* and set it as the context language. There is already a default language set in the
646+
* context from config.inc.php.
647+
*
648+
* @todo Please note that the cookie language ID has no effect as the language
649+
* is exclusively determined by the URL. It may only by accessed by some really old
650+
* codebase to read the language ID, but they should be updated to use the context
651+
* language directly.
652+
*/
625653
if (
626654
Validate::isUnsignedId($newLanguageId)
627655
&& $newLanguageId !== 0

classes/controller/FrontController.php

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,16 @@ public function init()
284284
throw new PrestaShopException($this->trans('Current theme is unavailable. Please check your theme\'s directory name ("%s") and permissions.', [htmlspecialchars(basename(rtrim(_PS_THEME_DIR_, '/\\')))], 'Admin.Design.Notification'));
285285
}
286286

287+
/*
288+
* Here, we resolve the context->country, the default country that will be used to display
289+
* prices, taxes, delivery options and other country specific data.
290+
*
291+
* The country may further change further down in this method, if we have a cart with an address assigned to it.
292+
* If there is a cart already, the context country is set to the country of that cart.
293+
*
294+
* If you are looking to override the country selection logic, you can use actionFrontControllerInitBefore above
295+
* and pre-set the things in beforehand.
296+
*/
287297
if (Configuration::get('PS_GEOLOCATION_ENABLED')) {
288298
if (($new_default = $this->geolocationManagement($this->context->country)) && Validate::isLoadedObject($new_default)) {
289299
$this->context->country = $new_default;
@@ -459,10 +469,13 @@ public function init()
459469

460470
Product::initPricesComputation();
461471

472+
/*
473+
* If there is an address assigned to the cart in context, the context->country MUST be set to the country of that address.
474+
* We use delivery or invoice address, depending on PS_TAX_ADDRESS_TYPE configuration.
475+
*/
462476
if (isset($cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}) && $cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}) {
463477
$infos = Address::getCountryAndState((int) $cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')});
464-
$country = new Country((int) $infos['id_country']);
465-
$this->context->country = $country;
478+
$this->context->country = new Country((int) $infos['id_country']);
466479
}
467480

468481
if (!Tools::isPHPCLI()) {

composer.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -247,9 +247,6 @@
247247
"phpunit/phpunit": true,
248248
"symfony/phpunit-bridge": true
249249
},
250-
"audit": {
251-
"block-insecure": false
252-
},
253250
"platform": {
254251
"php": "8.1.0"
255252
},

composer.lock

Lines changed: 11 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/PrestaShopBundle/Form/Admin/Configure/ShopParameters/CustomerPreferences/GeneralType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public function buildForm(FormBuilderInterface $builder, array $options)
5151
'Admin.Shopparameters.Feature'
5252
),
5353
'help' => $this->trans(
54-
'After a customer logs in, you can recall and display the content of his/her last shopping cart.',
54+
'If this option is enabled, the customer\'s last cart will be restored when they log back in. Otherwise, a new, empty cart will be created.',
5555
'Admin.Shopparameters.Help'
5656
),
5757
'multistore_configuration_key' => 'PS_CART_FOLLOWING',

0 commit comments

Comments
 (0)