Files
2026-09-15 10:35:56 +08:00

189 lines
5.1 KiB
PHP

<?php
declare(strict_types=1);
namespace Esun3d\LanguageUrlStoreResolver\Model;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Store\Model\ScopeInterface;
use Magento\Store\Model\ResourceModel\Store\CollectionFactory;
use Psr\Log\LoggerInterface;
class StoreViewRegistry
{
/**
* @var CollectionFactory
*/
private $storeCollectionFactory;
/**
* @var LoggerInterface
*/
private $logger;
/** @var ScopeConfigInterface */
private $scopeConfig;
/**
* @var string[][]|null
*/
private $storesByLanguage;
/**
* @var string[]|null
*/
private $languageByStoreCode;
/** @var string[][][]|null */
private $storesByWebsiteLanguage;
/** @var int[]|null */
private $websiteByStoreCode;
public function __construct(
CollectionFactory $storeCollectionFactory,
LoggerInterface $logger,
ScopeConfigInterface $scopeConfig
) {
$this->storeCollectionFactory = $storeCollectionFactory;
$this->logger = $logger;
$this->scopeConfig = $scopeConfig;
}
/**
* @return string[][]
*/
public function getStoresByLanguage(): array
{
$this->load();
return $this->storesByLanguage;
}
public function getDefaultStoreCodeForLanguage(string $language): ?string
{
$language = strtolower(trim($language));
$stores = $this->getStoresByLanguage();
return isset($stores[$language][0]) ? $stores[$language][0] : null;
}
/** @return string[][] */
public function getStoresByLanguageForWebsite(int $websiteId): array
{
$this->load();
return $this->storesByWebsiteLanguage[$websiteId] ?? [];
}
public function getStoreCodeForLanguageInWebsite(string $language, int $websiteId): ?string
{
$language = strtolower(trim($language));
$stores = $this->getStoresByLanguageForWebsite($websiteId);
return $stores[$language][0] ?? null;
}
public function isLanguageInWebsite(string $language, int $websiteId): bool
{
return $this->getStoreCodeForLanguageInWebsite($language, $websiteId) !== null;
}
public function isStoreCodeInWebsite(string $storeCode, int $websiteId): bool
{
$this->load();
return ($this->websiteByStoreCode[trim($storeCode)] ?? null) === $websiteId;
}
public function getLanguageByStoreCode(string $storeCode): ?string
{
$this->load();
$storeCode = trim($storeCode);
return $this->languageByStoreCode[$storeCode] ?? null;
}
public function isKnownStoreCode(string $storeCode): bool
{
return $this->getLanguageByStoreCode($storeCode) !== null;
}
public function isKnownLanguage(string $language): bool
{
$language = strtolower(trim($language));
$stores = $this->getStoresByLanguage();
return isset($stores[$language]);
}
/**
* @return string[]
*/
public function getAllowedLanguages(): array
{
return array_keys($this->getStoresByLanguage());
}
/**
* @return string[]
*/
public function getAllowedStoreCodes(): array
{
$this->load();
return array_keys($this->languageByStoreCode);
}
private function load(): void
{
if ($this->storesByLanguage !== null
&& $this->languageByStoreCode !== null
&& $this->storesByWebsiteLanguage !== null
&& $this->websiteByStoreCode !== null
) {
return;
}
$this->storesByLanguage = [];
$this->languageByStoreCode = [];
$this->storesByWebsiteLanguage = [];
$this->websiteByStoreCode = [];
$collection = $this->storeCollectionFactory->create();
$collection->setWithoutDefaultFilter();
$collection->addStatusFilter(1);
$collection->setOrder('sort_order', 'ASC');
$collection->setOrder('store_id', 'ASC');
foreach ($collection as $store) {
$storeCode = (string)$store->getCode();
$storeId = (int)$store->getId();
if ($storeId === 0) {
continue;
}
$locale = (string)$this->scopeConfig->getValue(
'general/locale/code',
ScopeInterface::SCOPE_STORE,
$storeCode
);
if (!preg_match('/^([a-z]{2,3})(?:[_-][A-Za-z]{4})?(?:[_-][A-Z]{2})?$/', $locale, $matches)) {
$this->logger->warning(
'[LanguageUrlStoreResolver] Ignored active store view with unsupported locale.',
['store_id' => $storeId, 'store_code' => $storeCode, 'locale' => $locale]
);
continue;
}
$language = strtolower($matches[1]);
$websiteId = (int)$store->getWebsiteId();
$this->storesByLanguage[$language][] = $storeCode;
$this->languageByStoreCode[$storeCode] = $language;
$this->storesByWebsiteLanguage[$websiteId][$language][] = $storeCode;
$this->websiteByStoreCode[$storeCode] = $websiteId;
}
}
}