diff --git a/vendor/magento/module-deploy/Package/LocaleResolver.php b/vendor/magento/module-deploy/Package/LocaleResolver.php new file mode 100644 index 00000000000..d9909edf312 --- /dev/null +++ b/vendor/magento/module-deploy/Package/LocaleResolver.php @@ -0,0 +1,208 @@ +storeView = $storeView; + $this->userCollFactory = $userCollectionFactory; + $this->deploymentConfig = $deploymentConfig; + $this->locale = $locale; + $this->logger = $logger; + } + + /** + * Get locales that are used for a given theme. + * If it is a frontend theme, return supported frontend languages. + * If it is an adminhtml theme, return languages that admin users have configured together with deployment config. + * + * @param Package $package + * + * @return array + */ + public function getUsedPackageLocales(Package $package): array + { + switch ($package->getArea()) { + case Area::AREA_ADMINHTML: + $locales = $this->getUsedAdminLocales(); + break; + case Area::AREA_FRONTEND: + $locales = $this->getUsedStoreLocales(); + break; + default: + $locales = array_merge($this->getUsedAdminLocales(), $this->getUsedStoreLocales()); + } + return $this->validateLocales($locales); + } + + /** + * Get used admin user locales, en_US is always included by default. + * + * @return array + */ + private function getUsedAdminLocales(): array + { + if ($this->usedAdminLocales === null) { + $deploymentConfig = $this->getDeploymentAdminLocales(); + $this->usedAdminLocales = array_merge([AppInterface::DISTRO_LOCALE_CODE], $deploymentConfig); + + if (!$this->isDbConnectionAvailable()) { + return $this->usedAdminLocales; + } + + /** @var UserCollection $userCollection */ + $userCollection = $this->userCollFactory->create(); + /** @var UserInterface $adminUser */ + foreach ($userCollection as $adminUser) { + $this->usedAdminLocales[] = $adminUser->getInterfaceLocale(); + } + } + return $this->usedAdminLocales; + } + + /** + * Get used store locales. + * + * @return array + */ + private function getUsedStoreLocales(): array + { + if ($this->usedStoreLocales === null) { + $this->usedStoreLocales = $this->isDbConnectionAvailable() + ? $this->storeView->retrieveLocales() + : [AppInterface::DISTRO_LOCALE_CODE]; + } + return $this->usedStoreLocales; + } + + /** + * Strip out duplicates and break on invalid locale codes. + * + * @param array $usedLocales + * + * @return array + * @throws InvalidArgumentException if unknown locale is provided by the store configuration + */ + private function validateLocales(array $usedLocales): array + { + return array_map( + function ($locale) { + if (!$this->locale->isValid($locale)) { + throw new InvalidArgumentException( + $locale . ' argument has invalid value, run info:language:list for list of available locales' + ); + } + + return $locale; + }, + array_unique($usedLocales) + ); + } + + /** + * Check if a database connection is already set up. + * + * @return bool + */ + private function isDbConnectionAvailable(): bool + { + try { + $connections = $this->deploymentConfig->get(ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTIONS, []); + } catch (LocalizedException $exception) { + $this->logger->critical($exception); + } + return !empty($connections); + } + + /** + * Retrieve deployment configuration for admin locales that have to be deployed. + * + * @return array|mixed|string|null + */ + private function getDeploymentAdminLocales(): array + { + try { + return $this->deploymentConfig + ->get(self::ADMIN_LOCALES_FOR_DEPLOY, []); + } catch (LocalizedException $exception) { + return []; + } + } +} diff --git a/vendor/magento/module-deploy/Package/PackagePool.php b/vendor/magento/module-deploy/Package/PackagePool.php index b9c0418df86..10146cf0a0e 100644 --- a/vendor/magento/module-deploy/Package/PackagePool.php +++ b/vendor/magento/module-deploy/Package/PackagePool.php @@ -7,7 +7,7 @@ namespace Magento\Deploy\Package; use Magento\Deploy\Collector\Collector; use Magento\Deploy\Console\DeployStaticOptions as Options; -use Magento\Framework\AppInterface; +use Magento\Framework\App\ObjectManager; use Magento\Framework\View\Design\ThemeInterface; use Magento\Framework\View\Design\Theme\ListInterface; @@ -41,22 +41,31 @@ class PackagePool */ private $collected = false; + /** + * @var LocaleResolver|null + */ + private $localeResolver; + + /** * PackagePool constructor * * @param Collector $collector * @param ListInterface $themeCollection * @param PackageFactory $packageFactory + * @param LocaleResolver|null $localeResolver */ public function __construct( Collector $collector, ListInterface $themeCollection, - PackageFactory $packageFactory + PackageFactory $packageFactory, + ?LocaleResolver $localeResolver = null ) { $this->collector = $collector; $themeCollection->clear()->resetConstraints(); $this->themes = $themeCollection->getItems(); $this->packageFactory = $packageFactory; + $this->localeResolver = $localeResolver ?: ObjectManager::getInstance()->get(LocaleResolver::class); } /** @@ -209,17 +218,17 @@ class PackagePool private function ensureRequiredLocales(array $options) { if (empty($options[Options::LANGUAGE]) || $options[Options::LANGUAGE][0] === 'all') { - $forcedLocales = [AppInterface::DISTRO_LOCALE_CODE]; + $forcedLocales = []; } else { $forcedLocales = $options[Options::LANGUAGE]; } - $resultPackages = $this->packages; - foreach ($resultPackages as $package) { + foreach ($this->packages as $package) { if ($package->getTheme() === Package::BASE_THEME) { continue; } - foreach ($forcedLocales as $locale) { + $locales = $forcedLocales ?: $this->localeResolver->getUsedPackageLocales($package); + foreach ($locales as $locale) { $this->ensurePackage([ 'area' => $package->getArea(), 'theme' => $package->getTheme(), diff --git a/setup/src/Magento/Setup/Console/Command/DeployStaticContentCommand.php b/setup/src/Magento/Setup/Console/Command/DeployStaticContentCommand.php index 6a4231259a1..c6facffb7c6 100644 --- a/setup/src/Magento/Setup/Console/Command/DeployStaticContentCommand.php +++ b/setup/src/Magento/Setup/Console/Command/DeployStaticContentCommand.php @@ -20,14 +20,14 @@ use Magento\Framework\Exception\LocalizedException; use Magento\Deploy\Service\DeployStaticContent; /** - * Deploy static content command + * Command to Deploy Static Content * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class DeployStaticContentCommand extends Command { /** - * Default language value + * Default language value. Always used for adminhtml, fallback if no frontend locale is supplied. */ const DEFAULT_LANGUAGE_VALUE = 'en_US'; @@ -82,7 +82,7 @@ class DeployStaticContentCommand extends Command } /** - * {@inheritdoc} + * @inheritdoc * @throws \InvalidArgumentException * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ @@ -96,7 +96,10 @@ class DeployStaticContentCommand extends Command } /** - * {@inheritdoc} + * @inheritdoc + * @param InputInterface $input + * @param OutputInterface $output + * * @throws \InvalidArgumentException * @throws LocalizedException */ @@ -119,7 +122,8 @@ class DeployStaticContentCommand extends Command $this->inputValidator->validate($input); $options = $input->getOptions(); - $options[Options::LANGUAGE] = $input->getArgument(Options::LANGUAGES_ARGUMENT) ?: ['all']; + $languageOption = $options[Options::LANGUAGE] ?: ['all']; + $options[Options::LANGUAGE] = $input->getArgument(Options::LANGUAGES_ARGUMENT) ?: $languageOption; $refreshOnly = isset($options[Options::REFRESH_CONTENT_VERSION_ONLY]) && $options[Options::REFRESH_CONTENT_VERSION_ONLY]; @@ -161,6 +165,8 @@ class DeployStaticContentCommand extends Command } /** + * Retrieve application state + * * @return State */ private function getAppState()