Skip to content

Commit 5402084

Browse files
author
Sergii Kovalenko
committed
MAGETWO-56936: [Backport] [Github] Allowed countries for customer address in admin using storeview configuration #2946
1 parent 0ff8138 commit 5402084

File tree

17 files changed

+878
-20
lines changed

17 files changed

+878
-20
lines changed

app/code/Magento/Backend/etc/adminhtml/system.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@
198198
<resource>Magento_Config::config_general</resource>
199199
<group id="country" translate="label" type="text" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1">
200200
<label>Country Options</label>
201-
<field id="allow" translate="label" type="multiselect" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1">
201+
<field id="allow" translate="label" type="multiselect" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1">
202202
<label>Allow Countries</label>
203203
<source_model>Magento\Directory\Model\Config\Source\Country</source_model>
204204
<can_be_empty>1</can_be_empty>
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Customer\Model;
8+
9+
use Magento\Customer\Model\Config\Share;
10+
use Magento\Directory\Model\CountryHandlerInterface;
11+
use Magento\Framework\App\Config\ScopeConfigInterface;
12+
use Magento\Framework\Data\Collection\AbstractDb;
13+
use Magento\Store\Api\Data\WebsiteInterface;
14+
use Magento\Store\Model\ScopeInterface;
15+
use Magento\Store\Model\StoreManagerInterface;
16+
17+
/**
18+
* Class CountryHandler.
19+
* @package Magento\Customer\Model
20+
*/
21+
class CountryHandler implements CountryHandlerInterface
22+
{
23+
/**
24+
* @var ScopeConfigInterface
25+
*/
26+
private $scopeConfig;
27+
28+
/**
29+
* @var StoreManagerInterface
30+
*/
31+
private $storeManager;
32+
33+
/**
34+
* @var Share
35+
*/
36+
private $customerConfigShare;
37+
38+
/**
39+
* CountryHandler constructor.
40+
* @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
41+
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
42+
* @param \Magento\Customer\Model\Config\Share $configShare
43+
*/
44+
public function __construct(
45+
ScopeConfigInterface $scopeConfig,
46+
StoreManagerInterface $storeManager,
47+
Share $configShare
48+
) {
49+
$this->scopeConfig = $scopeConfig;
50+
$this->storeManager = $storeManager;
51+
$this->customerConfigShare = $configShare;
52+
}
53+
54+
/**
55+
* @inheritdoc
56+
*/
57+
public function getAllowedCountries(
58+
$filter = null,
59+
$scope = ScopeInterface::SCOPE_WEBSITE,
60+
$ignoreGlobalScope = false
61+
) {
62+
if (empty($filter)) {
63+
$filter = $this->storeManager->getWebsite()->getId();
64+
}
65+
66+
if ($this->customerConfigShare->isGlobalScope() && !$ignoreGlobalScope) {
67+
//Check if we have shared accounts - than merge all website allowed countries
68+
$filter = array_map(function (WebsiteInterface $website) {
69+
return $website->getId();
70+
}, $this->storeManager->getWebsites());
71+
$scope = ScopeInterface::SCOPE_WEBSITES;
72+
}
73+
74+
switch ($scope) {
75+
case ScopeInterface::SCOPE_WEBSITES:
76+
case ScopeInterface::SCOPE_STORES:
77+
$allowedCountries = [];
78+
foreach ($filter as $singleFilter) {
79+
$allowedCountries = array_merge(
80+
$allowedCountries,
81+
$this->getCountriesFromConfig($this->getSingleScope($scope), $singleFilter)
82+
);
83+
}
84+
break;
85+
default:
86+
$allowedCountries = $this->getCountriesFromConfig($scope, $filter);
87+
}
88+
89+
return $this->makeCountriesUnique($allowedCountries);
90+
}
91+
92+
/**
93+
* @param array $allowedCountries
94+
* @return array
95+
*/
96+
private function makeCountriesUnique(array $allowedCountries)
97+
{
98+
return array_combine($allowedCountries, $allowedCountries);
99+
}
100+
101+
/**
102+
* @param string $scope
103+
* @param int $filter
104+
* @return array
105+
*/
106+
private function getCountriesFromConfig($scope, $filter)
107+
{
108+
return explode(
109+
',',
110+
(string) $this->scopeConfig->getValue(
111+
self::ALLOWED_COUNTRIES_PATH,
112+
$scope,
113+
$filter
114+
)
115+
);
116+
}
117+
118+
/**
119+
* @inheritdoc
120+
*/
121+
public function loadByScope(AbstractDb $collection, $filter, $scope = ScopeInterface::SCOPE_STORE)
122+
{
123+
$allowCountries = $this->getAllowedCountries($filter, $scope);
124+
125+
if (!empty($allowCountries)) {
126+
$collection->addFieldToFilter("country_id", ['in' => $allowCountries]);
127+
}
128+
129+
return $collection;
130+
}
131+
132+
/**
133+
* @param string $scope
134+
* @return string
135+
*/
136+
private function getSingleScope($scope)
137+
{
138+
if ($scope == ScopeInterface::SCOPE_WEBSITES) {
139+
return ScopeInterface::SCOPE_WEBSITE;
140+
}
141+
142+
if ($scope == ScopeInterface::SCOPE_STORES) {
143+
return ScopeInterface::SCOPE_STORE;
144+
}
145+
146+
return $scope;
147+
}
148+
}

app/code/Magento/Customer/Model/Customer/DataProvider.php

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
*/
66
namespace Magento\Customer\Model\Customer;
77

8+
use Magento\Customer\Api\Data\AddressInterface;
9+
use Magento\Customer\Api\Data\CustomerInterface;
10+
use Magento\Customer\Model\ResourceModel\Address\Attribute\Source\CountryWithWebsites;
811
use Magento\Eav\Api\Data\AttributeInterface;
912
use Magento\Eav\Model\Config;
1013
use Magento\Eav\Model\Entity\Type;
@@ -195,7 +198,12 @@ protected function getAttributesMeta(Type $entityType)
195198
}
196199

197200
if ($attribute->usesSource()) {
198-
$meta[$code]['arguments']['data']['config']['options'] = $attribute->getSource()->getAllOptions();
201+
if ($code == AddressInterface::COUNTRY_ID) {
202+
$meta[$code]['arguments']['data']['config']['options'] = $this->getCountryByWebsiteSource()
203+
->getAllOptions();
204+
} else {
205+
$meta[$code]['arguments']['data']['config']['options'] = $attribute->getSource()->getAllOptions();
206+
}
199207
}
200208

201209
$rules = $this->eavValidationRules->build($attribute, $meta[$code]['arguments']['data']['config']);
@@ -204,9 +212,47 @@ protected function getAttributesMeta(Type $entityType)
204212
}
205213
$meta[$code]['arguments']['data']['config']['componentType'] = Field::NAME;
206214
}
215+
216+
$this->processWebsiteMeta($meta);
207217
return $meta;
208218
}
209219

220+
/**
221+
* @deprecated
222+
* @return CountryWithWebsites
223+
*/
224+
private function getCountryByWebsiteSource()
225+
{
226+
return ObjectManager::getInstance()->get(CountryWithWebsites::class);
227+
}
228+
229+
/**
230+
* @deprecated
231+
* @return \Magento\Customer\Model\Config\Share
232+
*/
233+
private function getShareConfig()
234+
{
235+
return ObjectManager::getInstance()->get(\Magento\Customer\Model\Config\Share::class);
236+
}
237+
238+
/**
239+
* @param array $meta
240+
* @return void
241+
*/
242+
private function processWebsiteMeta(&$meta)
243+
{
244+
if (isset($meta[CustomerInterface::WEBSITE_ID]) && $this->getShareConfig()->isGlobalScope()) {
245+
$meta[CustomerInterface::WEBSITE_ID]['arguments']['data']['config']['isGlobalScope'] = 1;
246+
}
247+
248+
if (isset($meta[AddressInterface::COUNTRY_ID]) && !$this->getShareConfig()->isGlobalScope()) {
249+
$meta[AddressInterface::COUNTRY_ID]['arguments']['data']['config']['filterBy'] = [
250+
'target' => '${ $.provider }:data.customer.website_id',
251+
'field' => 'website_ids'
252+
];
253+
}
254+
}
255+
210256
/**
211257
* Process attributes by frontend input type
212258
*

app/code/Magento/Customer/Model/ResourceModel/Address/Attribute/Source/Country.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
*/
1212
namespace Magento\Customer\Model\ResourceModel\Address\Attribute\Source;
1313

14+
use Magento\Framework\App\ObjectManager;
15+
use Magento\Store\Model\StoreManagerInterface;
16+
1417
class Country extends \Magento\Eav\Model\Entity\Attribute\Source\Table
1518
{
1619
/**
@@ -41,7 +44,7 @@ public function getAllOptions()
4144
{
4245
if (!$this->_options) {
4346
$this->_options = $this->_createCountriesCollection()->loadByStore(
44-
$this->getAttribute()->getStoreId()
47+
$this->getStoreManager()->getStore()->getId()
4548
)->toOptionArray();
4649
}
4750
return $this->_options;
@@ -54,4 +57,13 @@ protected function _createCountriesCollection()
5457
{
5558
return $this->_countriesFactory->create();
5659
}
60+
61+
/**
62+
* @deprecated
63+
* @return StoreManagerInterface
64+
*/
65+
private function getStoreManager()
66+
{
67+
return ObjectManager::getInstance()->get(StoreManagerInterface::class);
68+
}
5769
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
/**
8+
* Customer country with website specified attribute source
9+
*
10+
* @author Magento Core Team <[email protected]>
11+
*/
12+
namespace Magento\Customer\Model\ResourceModel\Address\Attribute\Source;
13+
14+
use Magento\Customer\Api\Data\CustomerInterface;
15+
use Magento\Customer\Model\Customer;
16+
use Magento\Directory\Model\CountryHandlerInterface;
17+
use Magento\Framework\App\Config\ScopeConfigInterface;
18+
use Magento\Framework\App\ObjectManager;
19+
use Magento\Store\Model\ScopeInterface;
20+
use Magento\Store\Model\StoreManagerInterface;
21+
22+
class CountryWithWebsites extends \Magento\Eav\Model\Entity\Attribute\Source\Table
23+
{
24+
/**
25+
* @var \Magento\Directory\Model\ResourceModel\Country\CollectionFactory
26+
*/
27+
private $countriesFactory;
28+
29+
/**
30+
* @var \Magento\Customer\Model\CountryHandler
31+
*/
32+
private $countryHandler;
33+
34+
/**
35+
* @var array
36+
*/
37+
private $options;
38+
39+
/**
40+
* @var \Magento\Store\Model\StoreManagerInterface
41+
*/
42+
private $storeManager;
43+
44+
/**
45+
* CountryWithWebsites constructor.
46+
* @param \Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\CollectionFactory $attrOptionCollectionFactory
47+
* @param \Magento\Eav\Model\ResourceModel\Entity\Attribute\OptionFactory $attrOptionFactory
48+
* @param \Magento\Directory\Model\ResourceModel\Country\CollectionFactory $countriesFactory
49+
* @param \Magento\Directory\Model\CountryHandlerInterface $countryHandler
50+
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
51+
*/
52+
public function __construct(
53+
\Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\CollectionFactory $attrOptionCollectionFactory,
54+
\Magento\Eav\Model\ResourceModel\Entity\Attribute\OptionFactory $attrOptionFactory,
55+
\Magento\Directory\Model\ResourceModel\Country\CollectionFactory $countriesFactory,
56+
\Magento\Directory\Model\CountryHandlerInterface $countryHandler,
57+
\Magento\Store\Model\StoreManagerInterface $storeManager
58+
) {
59+
$this->countriesFactory = $countriesFactory;
60+
$this->countryHandler = $countryHandler;
61+
$this->storeManager = $storeManager;
62+
parent::__construct($attrOptionCollectionFactory, $attrOptionFactory);
63+
}
64+
65+
/**
66+
* Retrieve all options
67+
*
68+
* @return array
69+
*/
70+
public function getAllOptions()
71+
{
72+
if (!$this->options) {
73+
$allowedCountries = [];
74+
$websiteIds = [];
75+
76+
foreach ($this->storeManager->getWebsites() as $website) {
77+
$countries = $this->countryHandler
78+
->getAllowedCountries($website->getId(), ScopeInterface::SCOPE_WEBSITE, true);
79+
$allowedCountries = array_merge($allowedCountries, $countries);
80+
81+
foreach ($countries as $countryCode) {
82+
$websiteIds[$countryCode][] = $website->getId();
83+
}
84+
}
85+
86+
$this->options = $this->createCountriesCollection()
87+
->addFieldToFilter('country_id', ['in' => $allowedCountries])
88+
->toOptionArray();
89+
90+
foreach ($this->options as &$option) {
91+
if (isset($websiteIds[$option['value']])) {
92+
$option['website_ids'] = $websiteIds[$option['value']];
93+
}
94+
}
95+
}
96+
97+
return $this->options;
98+
}
99+
100+
/**
101+
* @return \Magento\Directory\Model\ResourceModel\Country\Collection
102+
*/
103+
private function createCountriesCollection()
104+
{
105+
return $this->countriesFactory->create();
106+
}
107+
}

0 commit comments

Comments
 (0)