<?php
namespace NetInventors\NetiNextStoreLocator\Storefront\Page\Store\Detail;
use NetInventors\NetiNextStoreLocator\Components\CmsPageRenderer;
use NetInventors\NetiNextStoreLocator\Components\ContactForm\ContactForm;
use NetInventors\NetiNextStoreLocator\Core\Content\Store\StoreEntity;
use NetInventors\NetiNextStoreLocator\Service\PluginConfig;
use NetInventors\NetiNextStoreLocator\Service\PluginConfigFactory;
use Shopware\Core\Content\Seo\SeoUrlPlaceholderHandlerInterface;
use NetInventors\NetiNextStoreLocator\Service\StoreBusinessHoursService;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\Routing\Exception\MissingRequestParameterException;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Shopware\Storefront\Page\GenericPageLoader;
use Shopware\Storefront\Page\MetaInformation;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
class StoreDetailPageLoader
{
/**
* @var GenericPageLoader
*/
private $genericLoader;
/**
* @var StoreDetailLoader
*/
private $storeDetailLoader;
/**
* @var SystemConfigService
*/
private $systemConfig;
/**
* @var EntityRepositoryInterface
*/
private $mediaRepository;
/**
* @var ContactForm
*/
private $contactForm;
/**
* @var CmsPageRenderer
*/
private $cmsPageRenderer;
/**
* @var EventDispatcherInterface
*/
private $eventDispatcher;
private SeoUrlPlaceholderHandlerInterface $seoUrlReplacer;
private string $shopwareVersion;
private StoreBusinessHoursService $businessHoursService;
public function __construct(
GenericPageLoader $genericLoader,
StoreDetailLoader $storeDetailLoader,
SystemConfigService $systemConfig,
EntityRepositoryInterface $mediaRepository,
ContactForm $contactForm,
CmsPageRenderer $cmsPageRenderer,
EventDispatcherInterface $eventDispatcher,
SeoUrlPlaceholderHandlerInterface $seoUrlReplacer,
string $shopwareVersion,
StoreBusinessHoursService $businessHoursService
) {
$this->genericLoader = $genericLoader;
$this->storeDetailLoader = $storeDetailLoader;
$this->systemConfig = $systemConfig;
$this->mediaRepository = $mediaRepository;
$this->contactForm = $contactForm;
$this->cmsPageRenderer = $cmsPageRenderer;
$this->eventDispatcher = $eventDispatcher;
$this->seoUrlReplacer = $seoUrlReplacer;
$this->shopwareVersion = $shopwareVersion;
$this->businessHoursService = $businessHoursService;
}
public function load(Request $request, SalesChannelContext $context): StoreDetailPage
{
$page = $this->genericLoader->load($request, $context);
/** @var StoreDetailPage $page */
$page = StoreDetailPage::createFrom($page);
/** @var string|null $storeId */
$storeId = $request->attributes->get('id');
if (!$storeId) {
throw new MissingRequestParameterException('id', '/id');
}
/** @var StoreEntity $store */
$store = $this->storeDetailLoader->load($storeId, $context);
$page->setStore($store);
$config = $this->getConfig($context);
$page->setConfig($config);
$translated = $store->getTranslated();
$metaInfoInformation = $page->getMetaInformation();
if ($metaInfoInformation instanceof MetaInformation) {
$metaInfoInformation->setMetaTitle((string) ($translated['seoTitle'] ?? $store->getLabel()));
if (!\is_string($translated['seoDescription'])) {
$translated['seoDescription'] = '';
}
$metaInfoInformation->setMetaDescription($translated['seoDescription']);
$metaInfoInformation->assign(['canonical' => $this->seoUrlReplacer->generate('frontend.store_locator.detail', ['id' => $storeId])]);
}
$contactFormFields = $this->contactForm->getFields($context);
$page->setContactFormFields($contactFormFields);
$contactSubjectOptions = $this->getContactSubjectOptions($config);
$page->setContactSubjectOptions($contactSubjectOptions);
$page->setStoreBusinessHours($this->businessHoursService->getStoreBusinessHours($storeId, $context->getContext()));
$page->setWeekDays($this->businessHoursService->getBusinessWeekdays($context->getContext()));
$timeZone = $store->getTimezone() ?: $request->cookies->get('timezone');
if (\is_string($timeZone)) {
$time = new \DateTime(
'now',
new \DateTimeZone($timeZone)
);
$page->setIsStoreOpen($this->businessHoursService->isStoreOpen($time, $storeId, $context->getContext()));
}
if (!\is_string($translated['detailDescription'])) {
$translated['detailDescription'] = '';
}
switch ($store->getDetailContentType()) {
case StoreEntity::CONTENT_TYPE_HTML:
$page->setHtmlContent(
$translated['detailDescription']
);
break;
case StoreEntity::CONTENT_TYPE_CMS:
$page->setHtmlContent(
$this->cmsPageRenderer->build(
$request,
$context,
$store->getCmsPage()
)
);
break;
}
$this->eventDispatcher->dispatch(new StoreDetailPageLoadedEvent($page, $context, $request));
return $page;
}
private function getConfig(SalesChannelContext $context): array
{
$config = (array)$this->systemConfig->get(PluginConfigFactory::CONFIG_DOMAIN, $context->getSalesChannel()->getId());
foreach ($config as $key => $value) {
unset ($config[$key]);
switch ($key) {
case 'googleMapIcon':
$mediaId = (string) $value;
if (!empty($mediaId)) {
/**
* @psalm-suppress MixedArgumentTypeCoercion
*
* This is the correct way to search for a specific ID
*/
$criteria = new Criteria([ $mediaId ]);
$result = $this->mediaRepository->search($criteria, $context->getContext());
if ($result->count() > 0) {
$value = $result->first()->getUrl();
} else {
throw new \Exception('The given mediaId does not exist.');
}
}
break;
case 'googleMapIconSize':
if (!empty($value)) {
if (!preg_match('/^([0-9]+)x([0-9]+)$/', $value)) {
throw new \Exception('The given icon size "' . $value . '" is invalid.');
}
[ $width, $height ] = array_map('intval', explode('x', $value));
$value = compact('width', 'height');
}
break;
}
$config[$key] = $value;
}
$config['_cookieConsentEnabled'] = version_compare($this->shopwareVersion, '6.4.12.0', '<')
?: $this->systemConfig->get('core.basicInformation.useDefaultCookieConsent');
return $config;
}
private function getContactSubjectOptions(array $config): array
{
$options = $config['contactSubjectOptions'] ?? '';
$options = trim($options);
if (empty($options)) {
return [];
}
return explode(PHP_EOL, $options);
}
}