168 lines
5.6 KiB
PHP
168 lines
5.6 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace Esun3d\LanguageUrlStoreResolver\ViewModel;
|
|
|
|
use Esun3d\LanguageUrlStoreResolver\Model\StoreViewRegistry;
|
|
use Magento\Framework\App\Config\ScopeConfigInterface;
|
|
use Magento\Framework\UrlInterface;
|
|
use Magento\Framework\View\Element\Block\ArgumentInterface;
|
|
use Magento\Store\Model\ScopeInterface;
|
|
use Magento\Store\Model\StoreManagerInterface;
|
|
|
|
class LocaleSwitcher implements ArgumentInterface
|
|
{
|
|
public function __construct(
|
|
private StoreManagerInterface $storeManager,
|
|
private StoreViewRegistry $storeViewRegistry,
|
|
private ScopeConfigInterface $scopeConfig,
|
|
private UrlInterface $urlBuilder
|
|
) {
|
|
}
|
|
|
|
/**
|
|
* @return array{markets:array<string,mixed>,currentMarket:string,currentLanguage:string}
|
|
*/
|
|
public function getConfig(): array
|
|
{
|
|
$currentWebsite = $this->storeManager->getWebsite();
|
|
$currentWebsiteCode = (string)$currentWebsite->getCode();
|
|
$currentStoreCode = (string)$this->storeManager->getStore()->getCode();
|
|
$currentLanguage = $this->storeViewRegistry->getLanguageByStoreCode($currentStoreCode) ?: '';
|
|
$relativePath = $this->getRelativeContentPath($currentWebsiteCode, $currentLanguage);
|
|
$query = $this->getCleanQuery();
|
|
$markets = [];
|
|
|
|
foreach ($this->storeManager->getWebsites(false) as $website) {
|
|
$websiteId = (int)$website->getId();
|
|
$defaultStore = $website->getDefaultStore();
|
|
if (!$defaultStore || !$defaultStore->isActive()) {
|
|
continue;
|
|
}
|
|
|
|
$defaultLanguage = $this->storeViewRegistry->getLanguageByStoreCode((string)$defaultStore->getCode());
|
|
if ($defaultLanguage === null) {
|
|
continue;
|
|
}
|
|
|
|
$languages = [];
|
|
foreach ($website->getStores() as $store) {
|
|
if (!$store->isActive()) {
|
|
continue;
|
|
}
|
|
|
|
$language = $this->storeViewRegistry->getLanguageByStoreCode((string)$store->getCode());
|
|
if ($language === null) {
|
|
continue;
|
|
}
|
|
|
|
$languages[$language] = [
|
|
'label' => (string)$store->getName(),
|
|
'storeCode' => (string)$store->getCode(),
|
|
'url' => $this->buildUrl(
|
|
$this->getWebsiteBaseUrl((string)$website->getCode()),
|
|
$language,
|
|
$defaultLanguage,
|
|
$relativePath,
|
|
$query
|
|
),
|
|
];
|
|
}
|
|
|
|
if (!$languages) {
|
|
continue;
|
|
}
|
|
|
|
$targetLanguage = isset($languages[$currentLanguage]) ? $currentLanguage : $defaultLanguage;
|
|
$markets[(string)$website->getCode()] = [
|
|
'label' => (string)$website->getName(),
|
|
'websiteId' => $websiteId,
|
|
'defaultLanguage' => $defaultLanguage,
|
|
'url' => $languages[$targetLanguage]['url'] ?? reset($languages)['url'],
|
|
'languages' => $languages,
|
|
];
|
|
}
|
|
|
|
return [
|
|
'markets' => $markets,
|
|
'currentMarket' => $currentWebsiteCode,
|
|
'currentLanguage' => $currentLanguage,
|
|
];
|
|
}
|
|
|
|
private function getRelativeContentPath(string $websiteCode, string $currentLanguage): string
|
|
{
|
|
$currentPath = trim((string)parse_url($this->getRequestUri(), PHP_URL_PATH), '/');
|
|
$basePath = trim((string)parse_url($this->getWebsiteBaseUrl($websiteCode), PHP_URL_PATH), '/');
|
|
|
|
if ($basePath !== '' && ($currentPath === $basePath || str_starts_with($currentPath, $basePath . '/'))) {
|
|
$currentPath = ltrim(substr($currentPath, strlen($basePath)), '/');
|
|
}
|
|
|
|
$segments = $currentPath === '' ? [] : explode('/', $currentPath);
|
|
if ($segments && strtolower($segments[0]) === strtolower($currentLanguage)) {
|
|
array_shift($segments);
|
|
}
|
|
|
|
return implode('/', $segments);
|
|
}
|
|
|
|
/** @return array<string,mixed> */
|
|
private function getCleanQuery(): array
|
|
{
|
|
$query = [];
|
|
parse_str((string)parse_url($this->getRequestUri(), PHP_URL_QUERY), $query);
|
|
unset($query['market'], $query['store'], $query['___store'], $query['___from_store']);
|
|
|
|
return $query;
|
|
}
|
|
|
|
private function getRequestUri(): string
|
|
{
|
|
return isset($_SERVER['REQUEST_URI'])
|
|
? (string)$_SERVER['REQUEST_URI']
|
|
: $this->urlBuilder->getCurrentUrl();
|
|
}
|
|
|
|
/** @param array<string,mixed> $query */
|
|
private function buildUrl(
|
|
string $baseUrl,
|
|
string $language,
|
|
string $defaultLanguage,
|
|
string $relativePath,
|
|
array $query
|
|
): string {
|
|
$url = rtrim($baseUrl, '/') . '/';
|
|
if ($language !== $defaultLanguage) {
|
|
$url .= rawurlencode($language) . '/';
|
|
}
|
|
if ($relativePath !== '') {
|
|
$url .= ltrim($relativePath, '/');
|
|
}
|
|
if ($query) {
|
|
$url .= '?' . http_build_query($query);
|
|
}
|
|
|
|
return $url;
|
|
}
|
|
|
|
private function getWebsiteBaseUrl(string $websiteCode): string
|
|
{
|
|
$baseUrl = (string)$this->scopeConfig->getValue(
|
|
'web/secure/base_url',
|
|
ScopeInterface::SCOPE_WEBSITE,
|
|
$websiteCode
|
|
);
|
|
|
|
if ($baseUrl === '') {
|
|
$baseUrl = (string)$this->scopeConfig->getValue(
|
|
'web/unsecure/base_url',
|
|
ScopeInterface::SCOPE_WEBSITE,
|
|
$websiteCode
|
|
);
|
|
}
|
|
|
|
return $baseUrl;
|
|
}
|
|
}
|