Skip to content

Commit cf3fbe6

Browse files
ma4nnsreichelkiatng
authored
New feature: Highlight popular countries in country select (#4089)
* allow to configure top countries that will be shown on top in the country dropdown * refactored Mage_Checkout_Block_Onepage_Abstract::getCountryHtmlSelect() to use related method in Mage_Directory to avoid code duplication, moved new code for top countries also to Mage_Directory * improved onchange listener for virtual orders * moved sorting of top countries further down so result is not cached and erroneously used in other places * re-added and deprecated method getCountryOptions() because it is public api * added missing translations * Update Data.php Removed empty space. --------- Co-authored-by: Sven Reichel <[email protected]> Co-authored-by: Ng Kiat Siong <[email protected]>
1 parent b266126 commit cf3fbe6

File tree

6 files changed

+61
-18
lines changed

6 files changed

+61
-18
lines changed

app/code/core/Mage/Checkout/Block/Onepage/Abstract.php

+7-17
Original file line numberDiff line numberDiff line change
@@ -161,22 +161,12 @@ public function getAddressesHtmlSelect($type)
161161
*/
162162
public function getCountryHtmlSelect($type)
163163
{
164-
$countryId = $this->getAddress()->getCountryId();
165-
if (is_null($countryId)) {
166-
$countryId = Mage::helper('core')->getDefaultCountry();
167-
}
168-
$select = $this->getLayout()->createBlock('core/html_select')
169-
->setName($type . '[country_id]')
170-
->setId($type . ':country_id')
171-
->setTitle(Mage::helper('checkout')->__('Country'))
172-
->setClass('validate-select')
173-
->setValue($countryId)
174-
->setOptions($this->getCountryOptions());
175-
if ($type === 'shipping') {
176-
$select->setExtraParams('onchange="if(window.shipping)shipping.setSameAsBilling(false);"');
177-
}
178-
179-
return $select->getHtml();
164+
return Mage::getBlockSingleton('directory/data')->getCountryHtmlSelect(
165+
$this->getAddress()->getCountryId(),
166+
$type . '[country_id]',
167+
$type . ':country_id',
168+
$this->helper('checkout')->__('Country'),
169+
);
180170
}
181171

182172
/**
@@ -197,6 +187,7 @@ public function getRegionHtmlSelect($type)
197187
}
198188

199189
/**
190+
* @deprecated
200191
* @return bool|mixed
201192
* @throws Mage_Core_Model_Store_Exception
202193
*/
@@ -240,5 +231,4 @@ public function isShow()
240231
{
241232
return true;
242233
}
243-
/* */
244234
}

app/code/core/Mage/Directory/Block/Data.php

+27-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
*
2020
* @category Mage
2121
* @package Mage_Directory
22+
* @phpstan-type Option array{label: string, value: non-falsy-string}
2223
*
2324
* @method int getRegionId()
2425
*/
@@ -78,7 +79,7 @@ public function getCountryHtmlSelect($defValue = null, $name = 'country_id', $id
7879
->setTitle(Mage::helper('directory')->__($title))
7980
->setClass('validate-select')
8081
->setValue($defValue)
81-
->setOptions($options)
82+
->setOptions($this->sortCountryOptions($options))
8283
->getHtml();
8384

8485
Varien_Profiler::stop('TEST: ' . __METHOD__);
@@ -172,4 +173,29 @@ public function getRegionsJs()
172173
Varien_Profiler::stop('TEST: ' . __METHOD__);
173174
return $regionsJs;
174175
}
176+
177+
/**
178+
* @template T of Option[]
179+
* @param T $countryOptions
180+
* @return array{0: array{label: string, value: Option[]}, 1: array{label: string, value: Option[]}}|T
181+
*/
182+
private function sortCountryOptions(array $countryOptions): array
183+
{
184+
$topCountryCodes = $this->helper('directory')->getTopCountryCodes();
185+
$headOptions = $tailOptions = [];
186+
187+
foreach ($countryOptions as $countryOption) {
188+
if (in_array($countryOption['value'], $topCountryCodes)) {
189+
$headOptions[] = $countryOption;
190+
} else {
191+
$tailOptions[] = $countryOption;
192+
}
193+
}
194+
195+
if (empty($headOptions)) {
196+
return $countryOptions;
197+
}
198+
199+
return [['label' => $this->__('Popular'), 'value' => $headOptions], ['label' => $this->__('Others'), 'value' => $tailOptions]];
200+
}
175201
}

app/code/core/Mage/Directory/Helper/Data.php

+12
Original file line numberDiff line numberDiff line change
@@ -310,4 +310,16 @@ public static function getConfigCurrencyBase(): string
310310
{
311311
return (string) Mage::getStoreConfig(Mage_Directory_Model_Currency::XML_PATH_CURRENCY_BASE);
312312
}
313+
314+
/** @return list<string> */
315+
public function getTopCountryCodes(): array
316+
{
317+
$topCountries = array_filter(explode(',', (string)Mage::getStoreConfig('general/country/top_countries')));
318+
319+
$transportObject = new Varien_Object();
320+
$transportObject->setData('top_countries', $topCountries);
321+
Mage::dispatchEvent('directory_get_top_countries', ['topCountries' => $transportObject]);
322+
323+
return $transportObject->getData('top_countries');
324+
}
313325
}

app/code/core/Mage/Directory/etc/system.xml

+11
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,17 @@
279279
<show_in_store>0</show_in_store>
280280
<can_be_empty>1</can_be_empty>
281281
</optional_zip_countries>
282+
<top_countries translate="label comment">
283+
<label>Top Countries</label>
284+
<frontend_type>multiselect</frontend_type>
285+
<sort_order>40</sort_order>
286+
<source_model>adminhtml/system_config_source_country</source_model>
287+
<show_in_default>1</show_in_default>
288+
<show_in_website>1</show_in_website>
289+
<show_in_store>1</show_in_store>
290+
<can_be_empty>1</can_be_empty>
291+
<comment>Choose popular countries that should be grouped on top of the country select.</comment>
292+
</top_countries>
282293
</fields>
283294
</country>
284295
<region translate="label">

app/locale/en_US/Mage_Directory.csv

+3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"Base currency is used for all online payment transactions. Scope is defined by the catalog price scope (""Catalog"" > ""Price"" > ""Catalog Price Scope"").","Base currency is used for all online payment transactions. Scope is defined by the catalog price scope (""Catalog"" > ""Price"" > ""Catalog Price Scope"")."
88
"Can't convert rate from ""%s-%s"".","Can't convert rate from ""%s-%s""."
99
"Cannot retrieve rate from %s.","Cannot retrieve rate from %s."
10+
"Choose popular countries that should be grouped on top of the country list.","Choose popular countries that should be grouped on top of the country list."
1011
"Connection Timeout in Seconds","Connection Timeout in Seconds"
1112
"Continue &raquo;","Continue &raquo;"
1213
"Country","Country"
@@ -37,6 +38,7 @@
3738
"List of regions in specified country","List of regions in specified country"
3839
"No API Key was specified or an invalid API Key was specified.","No API Key was specified or an invalid API Key was specified."
3940
"One or more invalid symbols have been specified.","One or more invalid symbols have been specified."
41+
"Popular","Popular"
4042
"Postal Code is Optional for the following countries","Postal Code is Optional for the following countries"
4143
"Region","Region"
4244
"Region API","Region API"
@@ -52,6 +54,7 @@
5254
"The account this API request is coming from is inactive.","The account this API request is coming from is inactive."
5355
"The current request did not return any results.","The current request did not return any results."
5456
"The maximum allowed API amount of monthly API requests has been reached.","The maximum allowed API amount of monthly API requests has been reached."
57+
"Top Countries","Top Countries"
5558
"Unable to initialize the import model.","Unable to initialize the import model."
5659
"Undefined rate from ""%s-%s"".","Undefined rate from ""%s-%s""."
5760
"WARNING:","WARNING:"

skin/frontend/base/default/js/opcheckout.js

+1
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,7 @@ Shipping.prototype = {
408408
this.form = form;
409409
if ($(this.form)) {
410410
$(this.form).observe('submit', function(event){this.save();Event.stop(event);}.bind(this));
411+
$(this.form).select('#shipping\\:country_id').first()?.addEventListener('change', () => { if (window.shipping) shipping.setSameAsBilling(false) });
411412
}
412413
this.addressUrl = addressUrl;
413414
this.saveUrl = saveUrl;

0 commit comments

Comments
 (0)