Skip to content

Commit 1b4ba9f

Browse files
author
Sergii Kovalenko
committed
MAGETWO-56941: CLONE - CLONE - [Github] Allowed countries for customer address in admin using storeview configuration #2946
1 parent 25b6600 commit 1b4ba9f

File tree

14 files changed

+848
-22
lines changed

14 files changed

+848
-22
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>

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

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@
77

88
use Magento\Customer\Api\AddressMetadataInterface;
99
use Magento\Customer\Api\CustomerMetadataInterface;
10+
use Magento\Customer\Api\Data\AddressInterface;
11+
use Magento\Customer\Api\Data\CustomerInterface;
1012
use Magento\Customer\Model\Attribute;
1113
use Magento\Customer\Model\FileProcessor;
1214
use Magento\Customer\Model\FileProcessorFactory;
15+
use Magento\Customer\Model\ResourceModel\Address\Attribute\Source\CountryByWebsite;
1316
use Magento\Eav\Api\Data\AttributeInterface;
1417
use Magento\Eav\Model\Config;
1518
use Magento\Eav\Model\Entity\Attribute\AbstractAttribute;
@@ -292,6 +295,7 @@ protected function getAttributesMeta(Type $entityType)
292295
$this->processFrontendInput($attribute, $meta);
293296

294297
$code = $attribute->getAttributeCode();
298+
295299
// use getDataUsingMethod, since some getters are defined and apply additional processing of returning value
296300
foreach ($this->metaProperties as $metaName => $origName) {
297301
$value = $attribute->getDataUsingMethod($origName);
@@ -304,7 +308,12 @@ protected function getAttributesMeta(Type $entityType)
304308
}
305309

306310
if ($attribute->usesSource()) {
307-
$meta[$code]['arguments']['data']['config']['options'] = $attribute->getSource()->getAllOptions();
311+
if ($code == AddressInterface::COUNTRY_ID) {
312+
$meta[$code]['arguments']['data']['config']['options'] = $this->getCountryByWebsiteSource()
313+
->getAllOptions();
314+
} else {
315+
$meta[$code]['arguments']['data']['config']['options'] = $attribute->getSource()->getAllOptions();
316+
}
308317
}
309318

310319
$rules = $this->eavValidationRules->build($attribute, $meta[$code]['arguments']['data']['config']);
@@ -315,9 +324,43 @@ protected function getAttributesMeta(Type $entityType)
315324

316325
$this->overrideFileUploaderMetadata($entityType, $attribute, $meta[$code]['arguments']['data']['config']);
317326
}
327+
328+
$this->processWebsiteMeta($meta);
318329
return $meta;
319330
}
320331

332+
/**
333+
* @deprecated
334+
* @return CountryByWebsite
335+
*/
336+
private function getCountryByWebsiteSource()
337+
{
338+
return ObjectManager::getInstance()->get(CountryByWebsite::class);
339+
}
340+
341+
/**
342+
* @deprecated
343+
* @return \Magento\Customer\Model\Config\Share
344+
*/
345+
private function getShareConfig()
346+
{
347+
return ObjectManager::getInstance()->get(\Magento\Customer\Model\Config\Share::class);
348+
}
349+
350+
private function processWebsiteMeta(&$meta)
351+
{
352+
if (isset($meta[CustomerInterface::WEBSITE_ID]) && $this->getShareConfig()->isGlobalScope()) {
353+
$meta[CustomerInterface::WEBSITE_ID]['arguments']['data']['config']['isGlobalScope'] = 1;
354+
}
355+
356+
if (isset($meta[AddressInterface::COUNTRY_ID]) && !$this->getShareConfig()->isGlobalScope()) {
357+
$meta[AddressInterface::COUNTRY_ID]['arguments']['data']['config']['filterBy'] = [
358+
'target' => '${ $.provider }:data.customer.website_id',
359+
'field' => 'website_ids'
360+
];
361+
}
362+
}
363+
321364
/**
322365
* Override file uploader UI component metadata
323366
*
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
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\Framework\App\Config\ScopeConfigInterface;
17+
use Magento\Framework\App\ObjectManager;
18+
use Magento\Store\Model\ScopeInterface;
19+
use Magento\Store\Model\StoreManagerInterface;
20+
21+
class CountryByWebsite extends \Magento\Eav\Model\Entity\Attribute\Source\Table
22+
{
23+
/**
24+
* @var \Magento\Directory\Model\ResourceModel\Country\CollectionFactory
25+
*/
26+
private $countriesFactory;
27+
28+
/**
29+
* @var \Magento\Directory\Model\CountryHandler
30+
*/
31+
private $countryHandler;
32+
33+
/**
34+
* @var array
35+
*/
36+
private $options;
37+
38+
/**
39+
* @var \Magento\Store\Model\StoreManagerInterface
40+
*/
41+
private $storeManager;
42+
43+
/**
44+
* @param \Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\CollectionFactory $attrOptionCollectionFactory
45+
* @param \Magento\Eav\Model\ResourceModel\Entity\Attribute\OptionFactory $attrOptionFactory
46+
* @param \Magento\Directory\Model\ResourceModel\Country\CollectionFactory $countriesFactory
47+
*/
48+
public function __construct(
49+
\Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\CollectionFactory $attrOptionCollectionFactory,
50+
\Magento\Eav\Model\ResourceModel\Entity\Attribute\OptionFactory $attrOptionFactory,
51+
\Magento\Directory\Model\ResourceModel\Country\CollectionFactory $countriesFactory,
52+
\Magento\Directory\Model\CountryHandler $countryHandler,
53+
\Magento\Store\Model\StoreManagerInterface $storeManager
54+
)
55+
{
56+
$this->countriesFactory = $countriesFactory;
57+
$this->countryHandler = $countryHandler;
58+
$this->storeManager = $storeManager;
59+
parent::__construct($attrOptionCollectionFactory, $attrOptionFactory);
60+
}
61+
62+
/**
63+
* Retrieve all options
64+
*
65+
* @return array
66+
*/
67+
public function getAllOptions()
68+
{
69+
if (!$this->options) {
70+
$allowedCountries = [];
71+
$websiteIds = [];
72+
73+
foreach ($this->storeManager->getWebsites() as $website) {
74+
$countries = $this->countryHandler
75+
->getAllowedCountries($website->getId(), ScopeInterface::SCOPE_WEBSITE, true);
76+
$allowedCountries = array_merge($allowedCountries, $countries);
77+
78+
foreach ($countries as $countryCode) {
79+
$websiteIds[$countryCode][] = $website->getId();
80+
}
81+
}
82+
83+
$this->options = $this->createCountriesCollection()
84+
->addFieldToFilter('country_id', ['in' => $allowedCountries])
85+
->toOptionArray();
86+
87+
foreach ($this->options as &$option) {
88+
if (isset($websiteIds[$option['value']])) {
89+
$option['website_ids'] = $websiteIds[$option['value']];
90+
}
91+
}
92+
}
93+
94+
return $this->options;
95+
}
96+
97+
/**
98+
* @return \Magento\Directory\Model\ResourceModel\Country\Collection
99+
*/
100+
private function createCountriesCollection()
101+
{
102+
return $this->countriesFactory->create();
103+
}
104+
}

app/code/Magento/Customer/Setup/UpgradeData.php

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,18 @@
77
namespace Magento\Customer\Setup;
88

99
use Magento\Customer\Model\Customer;
10+
use Magento\Directory\Model\CountryHandler;
11+
use Magento\Framework\App\Config\ScopeConfigInterface;
1012
use Magento\Framework\Encryption\Encryptor;
1113
use Magento\Framework\Indexer\IndexerRegistry;
14+
use Magento\Framework\ObjectManager\ObjectManager;
15+
use Magento\Framework\Setup\SetupInterface;
1216
use Magento\Framework\Setup\UpgradeDataInterface;
1317
use Magento\Framework\Setup\ModuleContextInterface;
1418
use Magento\Framework\Setup\ModuleDataSetupInterface;
19+
use Magento\Store\Api\Data\WebsiteInterface;
20+
use Magento\Store\Model\ScopeInterface;
21+
use Magento\Store\Model\StoreManagerInterface;
1522

1623
/**
1724
* @codeCoverageIgnore
@@ -106,12 +113,111 @@ public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface
106113
$this->upgradeCustomerPasswordResetlinkExpirationPeriodConfig($setup);
107114
}
108115

116+
if (version_compare($context->getVersion(), '2.0.9', '<')) {
117+
$setup->getConnection()->beginTransaction();
118+
119+
try {
120+
$this->migrateStoresAllowedCountriesToWebsite($setup);
121+
$setup->getConnection()->commit();
122+
} catch (\Exception $e) {
123+
$setup->getConnection()->rollBack();
124+
throw $e;
125+
}
126+
}
127+
109128
$indexer = $this->indexerRegistry->get(Customer::CUSTOMER_GRID_INDEXER_ID);
110129
$indexer->reindexAll();
111130
$this->eavConfig->clear();
112131
$setup->endSetup();
113132
}
114133

134+
/**
135+
* @deprecated
136+
* @return StoreManagerInterface
137+
*/
138+
private function getStoreManager()
139+
{
140+
return \Magento\Framework\App\ObjectManager::getInstance()->get(StoreManagerInterface::class);
141+
}
142+
143+
/**
144+
* @deprecated
145+
* @return CountryHandler
146+
*/
147+
private function getCountryHandler()
148+
{
149+
return \Magento\Framework\App\ObjectManager::getInstance()->get(CountryHandler::class);
150+
}
151+
152+
/**
153+
* @param array $countries
154+
* @param array $newCountries
155+
* @param $identifier
156+
* @return array
157+
*/
158+
private function mergeAllowedCountries(array $countries, array $newCountries, $identifier)
159+
{
160+
if (!isset($countries[$identifier])) {
161+
$countries[$identifier] = $newCountries;
162+
} else {
163+
$countries[$identifier] =
164+
array_replace($countries[$identifier], $newCountries);
165+
}
166+
167+
return $countries;
168+
}
169+
170+
/**
171+
* @param SetupInterface $setup
172+
* @return void
173+
*/
174+
private function migrateStoresAllowedCountriesToWebsite(SetupInterface $setup)
175+
{
176+
$allowedCountries = [];
177+
//Process Websites
178+
foreach ($this->getStoreManager()->getStores() as $store) {
179+
$allowedCountries = $this->mergeAllowedCountries(
180+
$allowedCountries,
181+
$this->getCountryHandler()->getAllowedCountries($store->getId(), ScopeInterface::SCOPE_STORE),
182+
$store->getWebsiteId()
183+
);
184+
}
185+
//Process stores
186+
foreach ($this->getStoreManager()->getWebsites() as $website) {
187+
$allowedCountries = $this->mergeAllowedCountries(
188+
$allowedCountries,
189+
$this->getCountryHandler()->getAllowedCountries($website->getId(), ScopeInterface::SCOPE_WEBSITE),
190+
$website->getId()
191+
);
192+
}
193+
194+
$connection = $setup->getConnection();
195+
196+
//Remove everything from stores scope
197+
$connection->delete(
198+
$connection->getTableName('core_config_data'),
199+
[
200+
'path = ?' => CountryHandler::ALLOWED_COUNTRIES_PATH,
201+
'scope = ?' => ScopeInterface::SCOPE_STORES
202+
]
203+
);
204+
205+
//Update websites
206+
foreach ($allowedCountries as $scopeId => $countries) {
207+
$connection->update(
208+
$connection->getTableName('core_config_data'),
209+
[
210+
'value' => implode(',', $countries)
211+
],
212+
[
213+
'path = ?' => CountryHandler::ALLOWED_COUNTRIES_PATH,
214+
'scope_id = ?' => $scopeId,
215+
'scope = ?' => ScopeInterface::SCOPE_WEBSITES
216+
]
217+
);
218+
}
219+
}
220+
115221
/**
116222
* @param array $entityAttributes
117223
* @param CustomerSetup $customerSetup

0 commit comments

Comments
 (0)