-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8b7fefd
commit 3e12792
Showing
6 changed files
with
331 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
<?php | ||
declare(strict_types = 1); | ||
|
||
namespace T3G\AgencyPack\Usercentrics\Hooks; | ||
|
||
|
||
use T3G\AgencyPack\Usercentrics\Page\AssetCollector; | ||
use T3G\AgencyPack\Usercentrics\Page\AssetRenderer; | ||
use TYPO3\CMS\Core\Utility\GeneralUtility; | ||
|
||
class PageRendererPostProcess | ||
{ | ||
|
||
/** | ||
* @var AssetCollector | ||
*/ | ||
private $assetCollector; | ||
|
||
public function __construct(AssetCollector $assetCollector = null) | ||
{ | ||
// hooks: no DI yet :( | ||
$this->assetCollector = $assetCollector ?? GeneralUtility::makeInstance(AssetCollector::class); | ||
} | ||
|
||
public function render($params) | ||
{ | ||
// Use AssetRenderer to inject all JavaScripts and CSS files | ||
$assetRenderer = GeneralUtility::makeInstance(AssetRenderer::class); | ||
$jsFiles = &$params['jsFiles']; | ||
$jsFiles .= $assetRenderer->renderJavaScript(true); | ||
$jsFooterFiles = &$params['jsFooterFiles']; | ||
$jsFooterFiles .= $assetRenderer->renderJavaScript(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,197 @@ | ||
<?php | ||
declare(strict_types = 1); | ||
namespace T3G\AgencyPack\Usercentrics\Page; | ||
|
||
/* | ||
* This file is part of the TYPO3 CMS project. | ||
* | ||
* It is free software; you can redistribute it and/or modify it under | ||
* the terms of the GNU General Public License, either version 2 | ||
* of the License, or any later version. | ||
* | ||
* For the full copyright and license information, please read the | ||
* LICENSE.txt file that was distributed with this source code. | ||
* | ||
* The TYPO3 project - inspiring people to share! | ||
*/ | ||
|
||
use TYPO3\CMS\Core\SingletonInterface; | ||
use TYPO3\CMS\Core\Utility\ArrayUtility; | ||
|
||
/** | ||
* The Asset Collector is responsible for keeping track of | ||
* - everything within <script> tags: javascript files and inline javascript code | ||
* - inline CSS and CSS files | ||
* | ||
* The goal of the asset collector is to: | ||
* - utilize a single "runtime-based" store for adding assets of certain kinds that are added to the output | ||
* - allow to deal with assets from non-cacheable plugins and cacheable content in the Frontend | ||
* - reduce the "power" and flexibility (I'd say it's a burden) of the "god class" PageRenderer. | ||
* - reduce the burden of storing everything in PageRenderer | ||
* | ||
* As a side-effect this allows to: | ||
* - Add a single CSS snippet or CSS file per content block, but assure that the CSS is only added once to the output. | ||
* | ||
* Note on the implementation: | ||
* - We use a Singleton to make use of the AssetCollector throughout Frontend process (similar to PageRenderer). | ||
* - Although this is not optimal, I don't see any other way to do so in the current code. | ||
* | ||
* https://developer.wordpress.org/reference/functions/wp_enqueue_style/ | ||
*/ | ||
class AssetCollector implements SingletonInterface | ||
{ | ||
/** | ||
* @var array | ||
*/ | ||
protected $javaScripts = []; | ||
|
||
/** | ||
* @var array | ||
*/ | ||
protected $inlineJavaScripts = []; | ||
|
||
/** | ||
* @var array | ||
*/ | ||
protected $styleSheets = []; | ||
|
||
/** | ||
* @var array | ||
*/ | ||
protected $inlineStyleSheets = []; | ||
|
||
/** | ||
* @var array | ||
*/ | ||
protected $media = []; | ||
|
||
public function addJavaScript(string $identifier, string $source, array $attributes, array $options = []): self | ||
{ | ||
$existingAttributes = $this->javaScripts[$identifier]['attributes'] ?? []; | ||
ArrayUtility::mergeRecursiveWithOverrule($existingAttributes, $attributes); | ||
$existingOptions = $this->javaScripts[$identifier]['options'] ?? []; | ||
ArrayUtility::mergeRecursiveWithOverrule($existingOptions, $options); | ||
$this->javaScripts[$identifier] = [ | ||
'source' => $source, | ||
'attributes' => $existingAttributes, | ||
'options' => $existingOptions | ||
]; | ||
return $this; | ||
} | ||
|
||
public function addInlineJavaScript(string $identifier, string $source, array $attributes, array $options = []): self | ||
{ | ||
$existingAttributes = $this->inlineJavaScripts[$identifier]['attributes'] ?? []; | ||
ArrayUtility::mergeRecursiveWithOverrule($existingAttributes, $attributes); | ||
$existingOptions = $this->inlineJavaScripts[$identifier]['options'] ?? []; | ||
ArrayUtility::mergeRecursiveWithOverrule($existingOptions, $options); | ||
$this->inlineJavaScripts[$identifier] = [ | ||
'source' => $source, | ||
'attributes' => $existingAttributes, | ||
'options' => $existingOptions | ||
]; | ||
return $this; | ||
} | ||
|
||
public function addStyleSheet(string $identifier, string $source, array $attributes, array $options = []): self | ||
{ | ||
$existingAttributes = $this->styleSheets[$identifier]['attributes'] ?? []; | ||
ArrayUtility::mergeRecursiveWithOverrule($existingAttributes, $attributes); | ||
$existingOptions = $this->styleSheets[$identifier]['options'] ?? []; | ||
ArrayUtility::mergeRecursiveWithOverrule($existingOptions, $options); | ||
$this->styleSheets[$identifier] = [ | ||
'source' => $source, | ||
'attributes' => $existingAttributes, | ||
'options' => $existingOptions | ||
]; | ||
return $this; | ||
} | ||
|
||
public function addInlineStyleSheet(string $identifier, string $source, array $attributes, array $options = []): self | ||
{ | ||
$existingAttributes = $this->inlineStyleSheets[$identifier]['attributes'] ?? []; | ||
ArrayUtility::mergeRecursiveWithOverrule($existingAttributes, $attributes); | ||
$existingOptions = $this->inlineStyleSheets[$identifier]['options'] ?? []; | ||
ArrayUtility::mergeRecursiveWithOverrule($existingOptions, $options); | ||
$this->inlineStyleSheets[$identifier] = [ | ||
'source' => $source, | ||
'attributes' => $existingAttributes, | ||
'options' => $existingOptions | ||
]; | ||
return $this; | ||
} | ||
|
||
/** | ||
* @param string $fileName | ||
* @param array $additionalInformation One dimensional hash map (array with non numerical keys) with scalar values | ||
* @return AssetCollector | ||
*/ | ||
public function addMedia(string $fileName, array $additionalInformation): self | ||
{ | ||
$existingAdditionalInformation = $this->media[$fileName] ?? []; | ||
ArrayUtility::mergeRecursiveWithOverrule($existingAdditionalInformation, $this->ensureAllValuesAreSerializable($additionalInformation)); | ||
$this->media[$fileName] = $existingAdditionalInformation; | ||
return $this; | ||
} | ||
|
||
private function ensureAllValuesAreSerializable(array $additionalInformation): array | ||
{ | ||
// Currently just filtering all non scalar values | ||
return array_filter($additionalInformation, 'is_scalar'); | ||
} | ||
|
||
public function removeJavaScript(string $identifier): self | ||
{ | ||
unset($this->javaScripts[$identifier]); | ||
return $this; | ||
} | ||
|
||
public function removeInlineJavaScript(string $identifier): self | ||
{ | ||
unset($this->inlineJavaScripts[$identifier]); | ||
return $this; | ||
} | ||
|
||
public function removeStyleSheet(string $identifier): self | ||
{ | ||
unset($this->styleSheets[$identifier]); | ||
return $this; | ||
} | ||
|
||
public function removeInlineStyleSheet(string $identifier): self | ||
{ | ||
unset($this->inlineStyleSheets[$identifier]); | ||
return $this; | ||
} | ||
|
||
public function removeMedia(string $identifier): self | ||
{ | ||
unset($this->media[$identifier]); | ||
return $this; | ||
} | ||
|
||
public function getMedia(): array | ||
{ | ||
return $this->media; | ||
} | ||
|
||
public function getJavaScripts(): array | ||
{ | ||
return $this->javaScripts; | ||
} | ||
|
||
public function getInlineJavaScripts(): array | ||
{ | ||
return $this->inlineJavaScripts; | ||
} | ||
|
||
public function getStyleSheets(): array | ||
{ | ||
return $this->styleSheets; | ||
} | ||
|
||
public function getInlineStyleSheets(): array | ||
{ | ||
return $this->inlineStyleSheets; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
<?php | ||
declare(strict_types = 1); | ||
namespace T3G\AgencyPack\Usercentrics\Page; | ||
|
||
/* | ||
* This file is part of the TYPO3 CMS project. | ||
* | ||
* It is free software; you can redistribute it and/or modify it under | ||
* the terms of the GNU General Public License, either version 2 | ||
* of the License, or any later version. | ||
* | ||
* For the full copyright and license information, please read the | ||
* LICENSE.txt file that was distributed with this source code. | ||
* | ||
* The TYPO3 project - inspiring people to share! | ||
*/ | ||
|
||
use TYPO3\CMS\Core\Utility\GeneralUtility; | ||
use TYPO3\CMS\Core\Utility\PathUtility; | ||
|
||
/** | ||
* Class AssetRenderer | ||
* @internal The AssetRenderer is used for the asset rendering and is not public API | ||
*/ | ||
class AssetRenderer | ||
{ | ||
protected $assetCollector; | ||
|
||
public function __construct(AssetCollector $assetCollector = null) | ||
{ | ||
$this->assetCollector = $assetCollector ?? GeneralUtility::makeInstance(AssetCollector::class); | ||
} | ||
|
||
public function renderInlineJavaScript($priority = false): string | ||
{ | ||
$template = '<script%attributes%>%source%</script>'; | ||
$assets = $this->assetCollector->getInlineJavaScripts(); | ||
foreach ($assets as &$assetData) { | ||
$assetData['attributes']['type'] = $assetData['attributes']['type'] ?? 'text/javascript'; | ||
} | ||
return $this->render($assets, $template, $priority); | ||
} | ||
|
||
public function renderJavaScript($priority = false): string | ||
{ | ||
$template = '<script%attributes%></script>'; | ||
$assets = $this->assetCollector->getJavaScripts(); | ||
foreach ($assets as &$assetData) { | ||
$assetData['attributes']['src'] = $this->getAbsoluteWebPath($assetData['source']); | ||
$assetData['attributes']['type'] = $assetData['attributes']['type'] ?? 'text/javascript'; | ||
} | ||
return $this->render($assets, $template, $priority); | ||
} | ||
|
||
public function renderInlineStyleSheets($priority = false): string | ||
{ | ||
$template = '<style%attributes%>%source%</style>'; | ||
$assets = $this->assetCollector->getInlineStyleSheets(); | ||
return $this->render($assets, $template, $priority); | ||
} | ||
|
||
public function renderStyleSheets(bool $priority = false, string $endingSlash = ''): string | ||
{ | ||
$template = '<link%attributes% ' . $endingSlash . '>'; | ||
$assets = $this->assetCollector->getStyleSheets(); | ||
foreach ($assets as &$assetData) { | ||
$assetData['attributes']['href'] = $this->getAbsoluteWebPath($assetData['source']); | ||
$assetData['attributes']['rel'] = $assetData['attributes']['rel'] ?? 'stylesheet'; | ||
$assetData['attributes']['type'] = $assetData['attributes']['type'] ?? 'text/css'; | ||
} | ||
return $this->render($assets, $template, $priority); | ||
} | ||
|
||
protected function render(array $assets, string $template, bool $priority = false): string | ||
{ | ||
$results = []; | ||
foreach ($assets as $assetData) { | ||
if (($assetData['options']['priority'] ?? false) !== $priority) { | ||
continue; | ||
} | ||
$attributes = $assetData['attributes']; | ||
$attributesString = count($attributes) ? ' ' . GeneralUtility::implodeAttributes($attributes, true) : ''; | ||
$results[] = str_replace(['%attributes%', '%source%'], [$attributesString, $assetData['source']], $template); | ||
} | ||
return implode(LF, $results); | ||
} | ||
|
||
private function getAbsoluteWebPath(string $file): string | ||
{ | ||
if (strpos($file, '://') !== false) { | ||
return $file; | ||
} | ||
return PathUtility::getAbsoluteWebPath(GeneralUtility::getFileAbsFileName($file)); | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters