-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathPageRendererHook.php
More file actions
117 lines (105 loc) · 4.35 KB
/
Copy pathPageRendererHook.php
File metadata and controls
117 lines (105 loc) · 4.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
<?php
declare(strict_types=1);
namespace B13\Http2;
/*
* This file is part of TYPO3 CMS-based extension "http2" by b13.
*
* 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.
*/
use Psr\Http\Message\ServerRequestInterface;
use Symfony\Component\DependencyInjection\Attribute\Autoconfigure;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use TYPO3\CMS\Core\Cache\CacheDataCollector;
use TYPO3\CMS\Core\Cache\CacheTag;
use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
use TYPO3\CMS\Core\Http\ApplicationType;
use TYPO3\CMS\Core\Page\PageRenderer;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Hooks into PageRenderer before the rendering is taken care of, and remember the files
* that can be sent as resources.
*
* This considers that everything is required, thus is marked as "preload", not via "prefetch".
*/
#[Autoconfigure(public: true)]
class PageRendererHook
{
public function __construct(
#[Autowire(service: 'cache.tx_http2')]
private readonly FrontendInterface $cache,
protected ResourceMatcher $matcher
) {}
/**
* @param array $params
* @param PageRenderer $pageRenderer
* @internal this is just a hook implementation.
*/
public function accumulateResources(array $params, PageRenderer $pageRenderer)
{
$request = $this->getRequest();
if ($request === null) {
return;
}
// If this is a second run (non-cached cObjects adding more data), then the existing cached data is fetched
if (ApplicationType::fromRequest($request)->isFrontend()) {
$allResources = $this->getFromCached($request);
} else {
$allResources = [];
}
foreach ($params['headerData'] as $headerData) {
$allResources = array_merge_recursive($allResources, $this->matcher->match($headerData));
}
foreach ($params['footerData'] as $footerData) {
$allResources = array_merge_recursive($allResources, $this->matcher->match($footerData));
}
foreach (['jsLibs', 'jsFiles', 'jsFooterLibs', 'jsFooterFiles', 'cssLibs', 'cssFiles'] as $part) {
if (empty($params[$part])) {
continue;
}
$allResources = array_merge_recursive($allResources, $this->matcher->match($params[$part]));
}
$allResources['scripts'] = array_unique($allResources['scripts'] ?? []);
$allResources['styles'] = array_unique($allResources['styles'] ?? []);
$this->process($allResources, $request);
}
/**
* In FE the data is stored in TSFE->config.
* In BE it is sent directly to the HTTP response.
*
* @param array $allResources
*/
protected function process(array $allResources, ServerRequestInterface $request): void
{
if (ApplicationType::fromRequest($request)->isFrontend()) {
$this->addToCached($request, $allResources);
} elseif (GeneralUtility::getIndpEnv('TYPO3_SSL')) {
// Push directly into the TYPO3 Backend, but only if TYPO3 is running in SSL
GeneralUtility::makeInstance(ResourcePusher::class)->pushAll($allResources);
}
}
protected function getFromCached(ServerRequestInterface $request): array
{
/** @var CacheDataCollector $cacheDataCollector */
$cacheDataCollector = $request->getAttribute('frontend.cache.collector');
$identifier = $cacheDataCollector->getPageCacheIdentifier();
if ($this->cache->has($identifier)) {
return $this->cache->get($identifier);
}
return [];
}
protected function addToCached(ServerRequestInterface $request, array $data): void
{
/** @var CacheDataCollector $cacheDataCollector */
$cacheDataCollector = $request->getAttribute('frontend.cache.collector');
$identifier = $cacheDataCollector->getPageCacheIdentifier();
$cacheTags = array_map(fn(CacheTag $cacheTag) => $cacheTag->name, $cacheDataCollector->getCacheTags());
$cacheTimeout = $cacheDataCollector->resolveLifetime();
$this->cache->set($identifier, $data, $cacheTags, $cacheTimeout);
}
protected function getRequest(): ?ServerRequestInterface
{
return $GLOBALS['TYPO3_REQUEST'] ?? null;
}
}