164 lines
5.1 KiB
PHP
164 lines
5.1 KiB
PHP
<?php
|
|
/**
|
|
* @package Plumrocket_GlobalPrivacyControl
|
|
* @copyright Copyright (c) 2025 Plumrocket Inc.
|
|
* @license https://plumrocket.com/license End-user License Agreement
|
|
*/
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Plumrocket\GlobalPrivacyControl\Block;
|
|
|
|
use Magento\Framework\Code\Minifier\Adapter\Js\JShrink;
|
|
use Magento\Framework\ObjectManagerInterface;
|
|
use Magento\Framework\Serialize\SerializerInterface;
|
|
use Magento\Framework\View\Element\Template;
|
|
use Magento\Framework\View\Element\Template\Context;
|
|
use Magento\Framework\View\Helper\SecureHtmlRenderer;
|
|
use Plumrocket\GlobalPrivacyControl\Helper\Config;
|
|
use Plumrocket\GlobalPrivacyControl\ViewModel\Geotargeting as GeotargetingViewModel;
|
|
|
|
class ComponentInit extends Template
|
|
{
|
|
public const SCRIPT_TAG_REPLACEMENT = 'pr-global-privacy-control-head-script';
|
|
|
|
/**
|
|
* @var \Magento\Framework\Code\Minifier\Adapter\Js\JShrink
|
|
*/
|
|
private $jsMinifier;
|
|
|
|
/**
|
|
* @var \Magento\Framework\Serialize\SerializerInterface
|
|
*/
|
|
private $serializer;
|
|
|
|
/**
|
|
* @var \Plumrocket\GlobalPrivacyControl\Helper\Config
|
|
*/
|
|
private $config;
|
|
|
|
/**
|
|
* @var \Plumrocket\GlobalPrivacyControl\ViewModel\Geotargeting
|
|
*/
|
|
private $geotargetingViewModel;
|
|
|
|
/**
|
|
* @var \Magento\Framework\View\Helper\SecureHtmlRenderer|mixed|null
|
|
*/
|
|
private $secureHtmlRenderer;
|
|
|
|
|
|
/**
|
|
* @param \Magento\Framework\View\Element\Template\Context $context
|
|
* @param \Magento\Framework\Code\Minifier\Adapter\Js\JShrink $jsMinifier
|
|
* @param \Magento\Framework\Serialize\SerializerInterface $serializer
|
|
* @param \Magento\Framework\ObjectManagerInterface $objectManager
|
|
* @param \Plumrocket\GlobalPrivacyControl\Helper\Config $config
|
|
* @param \Plumrocket\GlobalPrivacyControl\ViewModel\Geotargeting $geotargetingViewModel
|
|
* @param array $data
|
|
*/
|
|
public function __construct(
|
|
Context $context,
|
|
JShrink $jsMinifier,
|
|
SerializerInterface $serializer,
|
|
ObjectManagerInterface $objectManager,
|
|
Config $config,
|
|
GeotargetingViewModel $geotargetingViewModel,
|
|
array $data = []
|
|
) {
|
|
parent::__construct($context, $data);
|
|
$this->jsMinifier = $jsMinifier;
|
|
$this->serializer = $serializer;
|
|
$this->config = $config;
|
|
$this->geotargetingViewModel = $geotargetingViewModel;
|
|
|
|
/**
|
|
* @TODO Refactor when leave support of Magento 2.3.7 and less
|
|
*/
|
|
$this->secureHtmlRenderer = class_exists(SecureHtmlRenderer::class)
|
|
? $objectManager->get(SecureHtmlRenderer::class)
|
|
: null;
|
|
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function getConfig(): array
|
|
{
|
|
return [
|
|
'canProcessSignal' => $this->config->isModuleEnabled(),
|
|
'isGeotargetingEnabled' => $this->geotargetingViewModel->isEnabled(),
|
|
'geotargetingApiEndpoint' => $this->geotargetingViewModel->getApplicabilityUrl()
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
public function getSerializedConfig(): string
|
|
{
|
|
return $this->serializer->serialize($this->getConfig());
|
|
}
|
|
|
|
/**
|
|
* @return array|string|string[]
|
|
*/
|
|
protected function _toHtml()
|
|
{
|
|
$html = parent::_toHtml();
|
|
|
|
preg_match_all('/<script[\s\S]*?\/script>/', $html, $scriptTags);
|
|
$scriptTags = array_shift($scriptTags);
|
|
foreach ($scriptTags as $scriptTag) {
|
|
try {
|
|
$modifiedScriptTag = $this->modifyScriptTag($scriptTag);
|
|
} catch (\Exception $e) {
|
|
continue;
|
|
}
|
|
|
|
$html = str_replace($scriptTag, $modifiedScriptTag, $html);
|
|
}
|
|
|
|
return $html;
|
|
}
|
|
|
|
/**
|
|
* Modify script tag to prevent from being moved to footer
|
|
*
|
|
* @param string $scriptTag
|
|
* @return string
|
|
* @throws \Exception
|
|
*/
|
|
private function modifyScriptTag(string $scriptTag): string
|
|
{
|
|
/**
|
|
* @TODO Refactor when leave support of Magento 2.3.7 and less
|
|
*/
|
|
if (! $this->secureHtmlRenderer) {
|
|
preg_match('#<script[\s\S]*?>([^`]*?)<\/script>#', $scriptTag, $matches);
|
|
|
|
if(isset($matches[1])) {
|
|
$originalTagContent = $matches[1];
|
|
$minifiedContent = $this->jsMinifier->minify($originalTagContent);
|
|
$scriptTag = str_replace($originalTagContent, $minifiedContent, $scriptTag);
|
|
}
|
|
|
|
return str_replace(
|
|
['<script', '/script>'],
|
|
['<' . self::SCRIPT_TAG_REPLACEMENT, '/'.self::SCRIPT_TAG_REPLACEMENT.'>'],
|
|
$scriptTag
|
|
);
|
|
}
|
|
|
|
$doc = new \DOMDocument();
|
|
$doc->loadHTML($scriptTag);
|
|
$scriptNode = $doc->getElementsByTagName('script')->item(0);
|
|
|
|
$tagAttributes = array_column(iterator_to_array($scriptNode->attributes), 'nodeValue', 'name');
|
|
$tagContent = $this->jsMinifier->minify($scriptNode->textContent);
|
|
|
|
return $this->secureHtmlRenderer->renderTag(self::SCRIPT_TAG_REPLACEMENT, $tagAttributes, $tagContent, false);
|
|
}
|
|
}
|