<?php
namespace App\Document\Areabrick\Abstracts;
use App\Controller\DefaultFrontendController;
use App\Document\Areabrick\BrickTraits\BackgroundColorTrait;
use Pimcore\Extension\Document\Areabrick\AbstractTemplateAreabrick;
use Pimcore\Extension\Document\Areabrick\EditableDialogBoxConfiguration;
use Pimcore\Model\Document\Editable\Area\Info;
use Pimcore\Model\Document;
use Pimcore\Model\Document\Page;
use Pimcore\Model\Document\Snippet;
use Pimcore\Targeting\VisitorInfoStorageInterface;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Contracts\Translation\TranslatorInterface;
abstract class AbstractAreabrick extends AbstractTemplateAreabrick
{
// Allows all blocks to use the Background config and Background Panel.
use BackgroundColorTrait;
public Info $info;
protected ?\Pimcore\Model\User $user = null;
protected ?string $userLocale = null;
public function __construct(
private VisitorInfoStorageInterface $visitorInfoStorage,
protected TranslatorInterface $translator
) {
/** @var \Pimcore\Model\User $user */
$this->user = \Pimcore\Tool\Session::getReadonly()->get('user');
$this->userLocale = $this->user?->getLanguage();
}
public function action(Info $info)
{
$this->info = $info;
/** @var Request $request */
$request = $info->getRequest();
/** Also @see DefaultFrontendController::data() */
$info->setParam('data', [
'request' => [
'locale' => $request->getLocale(),
'url' => rawurldecode($request->getUri()),
],
'visitorId' => $this->getVisitorId(),
'gclid' => $this->getParameterOrCookieValue($request, 'gclid'),
'msclkid' => $this->getParameterOrCookieValue($request, 'msclkid'),
'li_fat_id' => $this->getParameterOrCookieValue($request, 'li_fat_id'),
'page' => [
'lang' => $this->getLang($info),
'country' => $this->getCountry($info),
'title' => $this->getTitle($info),
],
]);
}
/**
* Also @see DefaultFrontendController::getLang()
* @param Info $info
* @return string
*/
private function getLang(Info $info): string
{
preg_match('/^\/([a-z]{2}\-[a-z]{2})(\/|$)/i', $info->getDocument()->getRealFullPath(), $matches);
// The en-gb language is the default language and does not have /en-gb/ in the path.
return $matches[1] ?? 'en-gb';
}
/**
* Also @see DefaultFrontendController::getCountry()
* @param Info $info
* @return string
*/
private function getCountry(Info $info): string
{
$lang = $this->getLang($info);
$split = explode('-', $lang);
return $split[1] ?? $split[0];
}
/**
* Also @see DefaultFrontendController::getTitle()
* @param Info $info
* @return string|null
*/
private function getTitle(Info $info): ?string
{
$document = $info->getDocument();
return match (true) {
$document instanceof Page => $document->getTitle() ?: $document->getKey(),
/** @see DefaultController::snippetAction() */
$document instanceof Snippet => $document->getKey(),
default => null,
};
}
/**
* @inheritDoc
*/
public function getTemplateLocation(): string
{
return static::TEMPLATE_LOCATION_GLOBAL;
}
/**
* @inheritDoc
*/
public function getTemplateSuffix(): string
{
return static::TEMPLATE_SUFFIX_TWIG;
}
public function editableWidth(): int
{
return 800;
}
public function editableHeight(): int
{
return 650;
}
public function editableReloadOnClose(): bool
{
return true;
}
/**
* Overwrite this to add fields to the Inhoud panel.
*
* @param Info|null $info
* @return array|null
*/
public function editableContentFields(?Info $info): ?array
{
return null;
}
public function areaBrickEditableFieldItems(?Info $info): ?array
{
$items = [
'type' => 'tabpanel',
'items' => [],
];
if ($contentFields = $this->editableContentFields($info)) {
$items['items'][] = [
'type' => 'panel',
'title' => $this->translator->trans('Inhoud', locale: $this->userLocale),
'items' => $contentFields,
];
}
if ($bgPanel = $this->getBackgroundColorPanel($info)) {
$items['items'][] = $bgPanel;
}
return $items['items'] ? $items : [];
}
/**
* @param Document\Editable $area
* @param Info|null $info
* @return EditableDialogBoxConfiguration
*/
public function getEditableDialogBoxConfiguration(Document\Editable $area, ?Info $info): EditableDialogBoxConfiguration
{
$config = new EditableDialogBoxConfiguration();
$config->setWidth($this->editableWidth());
$config->setHeight($this->editableHeight());
$config->setReloadOnClose($this->editableReloadOnClose());
$config->setItems($this->areaBrickEditableFieldItems($info));
return $config;
}
/**
* {@inheritdoc}
*/
public function getHtmlTagOpen(Info $info): string
{
return "";
}
/**
* {@inheritdoc}
*/
public function getHtmlTagClose(Info $info): string
{
return "";
}
private function getVisitorId(): ?string
{
// always check if there is a visitor info before trying to fetch it
if (!$this->visitorInfoStorage->hasVisitorInfo() ) {
return $this->generateVisitorId();
}
$visitorInfo = $this->visitorInfoStorage->getVisitorInfo();
/*
when using cookie blockers, the visitor ID is sometimes not available and will return null.
So make sure you properly handle null in the template.
*/
return $visitorInfo->getVisitorId() ?? $this->generateVisitorId();
}
private function generateVisitorId(): string {
$result = '';
$chars = '0123456789abcdef';
for ($i = 16; $i > 0; --$i) {
try {
$result .= $chars[random_int(0, strlen($chars) - 1)];
} catch (\Exception $e) {
$result .= 'a';
}
}
return $result;
}
private function getParameterOrCookieValue(Request $request, string $parameterName): ?string
{
$cookieValue = $request->cookies->get($parameterName);
if ($cookieValue !== null && $cookieValue !== '') {
return $cookieValue;
}
return $request->query->get($parameterName);
}
}