• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

eliashaeussler / typo3-warming / 17878495693

20 Sep 2025 10:02AM UTC coverage: 93.066% (+0.3%) from 92.759%
17878495693

Pull #959

github

eliashaeussler
[FEATURE] Run cache warmup after DataHandler cache clear
Pull Request #959: [FEATURE] Run cache warmup after DataHandler cache clear

94 of 95 new or added lines in 3 files covered. (98.95%)

1785 of 1918 relevant lines covered (93.07%)

14.22 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.62
/Classes/Hook/DataHandlerClearCacheHook.php
1
<?php
2

3
declare(strict_types=1);
4

5
/*
6
 * This file is part of the TYPO3 CMS extension "warming".
7
 *
8
 * Copyright (C) 2021-2025 Elias Häußler <elias@haeussler.dev>
9
 *
10
 * This program is free software: you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation, either version 2 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22
 */
23

24
namespace EliasHaeussler\Typo3Warming\Hook;
25

26
use EliasHaeussler\Typo3Warming\Configuration;
27
use EliasHaeussler\Typo3Warming\Queue;
28
use EliasHaeussler\Typo3Warming\ValueObject;
29
use Symfony\Component\DependencyInjection;
30
use TYPO3\CMS\Backend;
31
use TYPO3\CMS\Core;
32

33
/**
34
 * DataHandlerClearCacheHook
35
 *
36
 * @author Elias Häußler <elias@haeussler.dev>
37
 * @license GPL-2.0-or-later
38
 * @internal
39
 *
40
 * @phpstan-type HookParams array{table?: non-empty-string, uid?: positive-int, uid_page?: positive-int}
41
 */
42
#[DependencyInjection\Attribute\Autoconfigure(public: true)]
43
final readonly class DataHandlerClearCacheHook
44
{
45
    public function __construct(
13✔
46
        private Configuration\Configuration $configuration,
47
        private Queue\CacheWarmupQueue $queue,
48
    ) {}
13✔
49

50
    /**
51
     * @param HookParams $params
52
     */
53
    public function warmupPageCache(array $params): void
13✔
54
    {
55
        // Early return if hook is disabled
56
        if (!$this->configuration->runAfterCacheClear) {
13✔
57
            return;
2✔
58
        }
59

60
        [$pageUid, $languageIds] = $this->resolveCacheWarmupParameters($params);
11✔
61

62
        if ($pageUid !== null) {
11✔
63
            $this->queue->enqueue(new ValueObject\Request\PageWarmupRequest($pageUid, $languageIds));
7✔
64
        }
65
    }
66

67
    /**
68
     * @param HookParams $params
69
     * @return array{positive-int|null, array{0?: non-negative-int}}
70
     */
71
    private function resolveCacheWarmupParameters(array $params): array
11✔
72
    {
73
        $table = $params['table'] ?? null;
11✔
74
        $recordUid = $params['uid'] ?? null;
11✔
75
        $unsupportedParameters = [null, []];
11✔
76

77
        // Early return if table or record uid is not available
78
        if ($table === null || $recordUid === null) {
11✔
79
            return $unsupportedParameters;
1✔
80
        }
81

82
        if ($table === 'pages') {
10✔
83
            if ($this->isSupportedPage($recordUid)) {
4✔
84
                return [$recordUid, []];
3✔
85
            }
86

87
            return $unsupportedParameters;
1✔
88
        }
89

90
        $pageUid = $params['uid_page'] ?? null;
6✔
91

92
        if (!$this->isSupportedPage($pageUid)) {
6✔
93
            return $unsupportedParameters;
2✔
94
        }
95

96
        $record = Backend\Utility\BackendUtility::getRecord($table, $recordUid);
4✔
97

98
        // Early return if record cannot be resolved
99
        if ($record === null) {
4✔
100
            return [$pageUid, []];
1✔
101
        }
102

103
        if (\class_exists(Core\Schema\TcaSchemaFactory::class)) {
3✔
104
            // @todo Use DI once support for TYPO3 v12 is dropped
105
            $tcaSchemaFactory = Core\Utility\GeneralUtility::makeInstance(Core\Schema\TcaSchemaFactory::class);
3✔
106
            $tcaSchema = $tcaSchemaFactory->has($table) ? $tcaSchemaFactory->get($table) : null;
3✔
107

108
            if ($tcaSchema?->isLanguageAware() === true) {
3✔
109
                $languageField = $tcaSchema->getCapability(Core\Schema\Capability\TcaSchemaCapability::Language)->getLanguageField()->getName();
2✔
110
            } else {
111
                $languageField = null;
1✔
112
            }
113
        } else {
114
            // @todo Remove once support for TYPO3 v12 is dropped
NEW
115
            $languageField = $GLOBALS['TCA'][$table]['ctrl']['languageField'] ?? null;
×
116
        }
117

118
        if ($languageField !== null) {
3✔
119
            $languageIds = [$record[$languageField] ?? 0];
2✔
120
        } else {
121
            $languageIds = [];
1✔
122
        }
123

124
        return [$pageUid, $languageIds];
3✔
125
    }
126

127
    private function isSupportedPage(?int $pageId): bool
10✔
128
    {
129
        if ($pageId === null) {
10✔
130
            return false;
1✔
131
        }
132

133
        $pageRecord = Backend\Utility\BackendUtility::getRecord('pages', $pageId);
9✔
134

135
        return $pageRecord !== null
9✔
136
            && in_array($pageRecord['doktype'] ?? 0, $this->configuration->supportedDoktypes, true)
9✔
137
        ;
9✔
138
    }
139
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc