Skip to content

Commit da400fb

Browse files
committed
Deploy all used locales
`bin/magento setup:static-content:deploy --language=all` currently only deploys en_US, instead of the requested "all". In the process repair the language argument in the deployment command. Remove DB dependency and deploy theme specific languages Add deployment config for Admin locale generation Reduce object coupling by introducing a new class Fix code sniffer errors add unit tests Suppress PHPMD.CouplingBetweenObjects resolve static test issues and Semantic Version Checker issue resolve static test results
1 parent f3a160c commit da400fb

File tree

4 files changed

+461
-11
lines changed

4 files changed

+461
-11
lines changed
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Deploy\Package;
9+
10+
use InvalidArgumentException;
11+
use Magento\Framework\App\Area;
12+
use Magento\Framework\App\DeploymentConfig;
13+
use Magento\Framework\AppInterface;
14+
use Magento\Framework\Config\ConfigOptionsListConstants;
15+
use Magento\Framework\Exception\LocalizedException;
16+
use Magento\Framework\Validator\Locale;
17+
use Magento\Store\Model\Config\StoreView;
18+
use Magento\User\Api\Data\UserInterface;
19+
use Magento\User\Model\ResourceModel\User\Collection as UserCollection;
20+
use Magento\User\Model\ResourceModel\User\CollectionFactory as UserCollectionFactory;
21+
use Psr\Log\LoggerInterface;
22+
23+
/**
24+
* Deployment Package Locale Resolver class
25+
*/
26+
class LocaleResolver
27+
{
28+
/**
29+
* Parameter to force deploying certain languages for the admin, without any users having configured them yet.
30+
*/
31+
const ADMIN_LOCALES_FOR_DEPLOY = 'admin_locales_for_deploy';
32+
33+
/**
34+
* @var StoreView
35+
*/
36+
private $storeView;
37+
38+
/**
39+
* @var UserCollectionFactory
40+
*/
41+
private $userCollFactory;
42+
43+
/**
44+
* @var DeploymentConfig
45+
*/
46+
private $deploymentConfig;
47+
48+
/**
49+
* @var Locale
50+
*/
51+
private $locale;
52+
53+
/**
54+
* @var LoggerInterface
55+
*/
56+
private $logger;
57+
58+
/**
59+
* @var array|null
60+
*/
61+
private $usedStoreLocales;
62+
63+
/**
64+
* @var array|null
65+
*/
66+
private $usedAdminLocales;
67+
68+
/**
69+
* LocaleResolver constructor.
70+
*
71+
* @param StoreView $storeView
72+
* @param UserCollectionFactory $userCollectionFactory
73+
* @param DeploymentConfig $deploymentConfig
74+
* @param Locale $locale
75+
* @param LoggerInterface $logger
76+
*/
77+
public function __construct(
78+
StoreView $storeView,
79+
UserCollectionFactory $userCollectionFactory,
80+
DeploymentConfig $deploymentConfig,
81+
Locale $locale,
82+
LoggerInterface $logger
83+
) {
84+
$this->storeView = $storeView;
85+
$this->userCollFactory = $userCollectionFactory;
86+
$this->deploymentConfig = $deploymentConfig;
87+
$this->locale = $locale;
88+
$this->logger = $logger;
89+
}
90+
91+
/**
92+
* Get locales that are used for a given theme.
93+
* If it is a frontend theme, return supported frontend languages.
94+
* If it is an adminhtml theme, return languages that admin users have configured together with deployment config.
95+
*
96+
* @param Package $package
97+
*
98+
* @return array
99+
*/
100+
public function getUsedPackageLocales(Package $package): array
101+
{
102+
switch ($package->getArea()) {
103+
case Area::AREA_ADMINHTML:
104+
$locales = $this->getUsedAdminLocales();
105+
break;
106+
case Area::AREA_FRONTEND:
107+
$locales = $this->getUsedStoreLocales();
108+
break;
109+
default:
110+
$locales = array_merge($this->getUsedAdminLocales(), $this->getUsedStoreLocales());
111+
}
112+
return $this->validateLocales($locales);
113+
}
114+
115+
/**
116+
* Get used admin user locales, en_US is always included by default.
117+
*
118+
* @return array
119+
*/
120+
private function getUsedAdminLocales(): array
121+
{
122+
if ($this->usedAdminLocales === null) {
123+
$deploymentConfig = $this->getDeploymentAdminLocales();
124+
$this->usedAdminLocales = array_merge([AppInterface::DISTRO_LOCALE_CODE], $deploymentConfig);
125+
126+
if (!$this->isDbConnectionAvailable()) {
127+
return $this->usedAdminLocales;
128+
}
129+
130+
/** @var UserCollection $userCollection */
131+
$userCollection = $this->userCollFactory->create();
132+
/** @var UserInterface $adminUser */
133+
foreach ($userCollection as $adminUser) {
134+
$this->usedAdminLocales[] = $adminUser->getInterfaceLocale();
135+
}
136+
}
137+
return $this->usedAdminLocales;
138+
}
139+
140+
/**
141+
* Get used store locales.
142+
*
143+
* @return array
144+
*/
145+
private function getUsedStoreLocales(): array
146+
{
147+
if ($this->usedStoreLocales === null) {
148+
$this->usedStoreLocales = $this->isDbConnectionAvailable()
149+
? $this->storeView->retrieveLocales()
150+
: [AppInterface::DISTRO_LOCALE_CODE];
151+
}
152+
return $this->usedStoreLocales;
153+
}
154+
155+
/**
156+
* Strip out duplicates and break on invalid locale codes.
157+
*
158+
* @param array $usedLocales
159+
*
160+
* @return array
161+
* @throws InvalidArgumentException if unknown locale is provided by the store configuration
162+
*/
163+
private function validateLocales(array $usedLocales): array
164+
{
165+
return array_map(
166+
function ($locale) {
167+
if (!$this->locale->isValid($locale)) {
168+
throw new InvalidArgumentException(
169+
$locale . ' argument has invalid value, run info:language:list for list of available locales'
170+
);
171+
}
172+
173+
return $locale;
174+
},
175+
array_unique($usedLocales)
176+
);
177+
}
178+
179+
/**
180+
* Check if a database connection is already set up.
181+
*
182+
* @return bool
183+
*/
184+
private function isDbConnectionAvailable(): bool
185+
{
186+
try {
187+
$connections = $this->deploymentConfig->get(ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTIONS, []);
188+
} catch (LocalizedException $exception) {
189+
$this->logger->critical($exception);
190+
}
191+
return !empty($connections);
192+
}
193+
194+
/**
195+
* Retrieve deployment configuration for admin locales that have to be deployed.
196+
*
197+
* @return array|mixed|string|null
198+
*/
199+
private function getDeploymentAdminLocales(): array
200+
{
201+
try {
202+
return $this->deploymentConfig
203+
->get(self::ADMIN_LOCALES_FOR_DEPLOY, []);
204+
} catch (LocalizedException $exception) {
205+
return [];
206+
}
207+
}
208+
}

app/code/Magento/Deploy/Package/PackagePool.php

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
use Magento\Deploy\Collector\Collector;
99
use Magento\Deploy\Console\DeployStaticOptions as Options;
10-
use Magento\Framework\AppInterface;
10+
use Magento\Framework\App\ObjectManager;
1111
use Magento\Framework\View\Design\ThemeInterface;
1212
use Magento\Framework\View\Design\Theme\ListInterface;
1313

@@ -41,22 +41,30 @@ class PackagePool
4141
*/
4242
private $collected = false;
4343

44+
/**
45+
* @var LocaleResolver|null
46+
*/
47+
private $localeResolver;
48+
4449
/**
4550
* PackagePool constructor
4651
*
4752
* @param Collector $collector
4853
* @param ListInterface $themeCollection
4954
* @param PackageFactory $packageFactory
55+
* @param LocaleResolver|null $localeResolver
5056
*/
5157
public function __construct(
5258
Collector $collector,
5359
ListInterface $themeCollection,
54-
PackageFactory $packageFactory
60+
PackageFactory $packageFactory,
61+
?LocaleResolver $localeResolver = null
5562
) {
5663
$this->collector = $collector;
5764
$themeCollection->clear()->resetConstraints();
5865
$this->themes = $themeCollection->getItems();
5966
$this->packageFactory = $packageFactory;
67+
$this->localeResolver = $localeResolver ?: ObjectManager::getInstance()->get(LocaleResolver::class);
6068
}
6169

6270
/**
@@ -221,17 +229,18 @@ private function ensurePackagesForRequiredLocales(array $options)
221229
private function ensureRequiredLocales(array $options)
222230
{
223231
if (empty($options[Options::LANGUAGE]) || $options[Options::LANGUAGE][0] === 'all') {
224-
$forcedLocales = [AppInterface::DISTRO_LOCALE_CODE];
232+
$forcedLocales = [];
225233
} else {
226234
$forcedLocales = $options[Options::LANGUAGE];
227235
}
228236

229-
$resultPackages = $this->packages;
230-
foreach ($resultPackages as $package) {
237+
foreach ($this->packages as $package) {
231238
if ($package->getTheme() === Package::BASE_THEME) {
232239
continue;
233240
}
234-
foreach ($forcedLocales as $locale) {
241+
242+
$locales = $forcedLocales ?: $this->localeResolver->getUsedPackageLocales($package);
243+
foreach ($locales as $locale) {
235244
$this->ensurePackage([
236245
'area' => $package->getArea(),
237246
'theme' => $package->getTheme(),

0 commit comments

Comments
 (0)