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

eliashaeussler / typo3-warming / 18445843960

12 Oct 2025 03:21PM UTC coverage: 92.263% (-0.5%) from 92.803%
18445843960

Pull #993

github

eliashaeussler
[FEATURE] Extract context menu actions into separate classes
Pull Request #993: [FEATURE] Extract context menu actions into separate classes

124 of 141 new or added lines in 6 files covered. (87.94%)

1 existing line in 1 file now uncovered.

1753 of 1900 relevant lines covered (92.26%)

12.24 hits per line

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

87.76
/Classes/Backend/Action/WarmupActionsProvider.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\Backend\Action;
25

26
use EliasHaeussler\Typo3SitemapLocator;
27
use EliasHaeussler\Typo3Warming\Configuration;
28
use EliasHaeussler\Typo3Warming\Domain;
29
use EliasHaeussler\Typo3Warming\Security;
30
use Symfony\Component\DependencyInjection;
31
use TYPO3\CMS\Backend;
32
use TYPO3\CMS\Core;
33

34
/**
35
 * WarmupActionsProvider
36
 *
37
 * @author Elias Häußler <elias@haeussler.dev>
38
 * @license GPL-2.0-or-later
39
 */
40
final readonly class WarmupActionsProvider
41
{
42
    public function __construct(
15✔
43
        private Configuration\Configuration $configuration,
44
        private Security\WarmupPermissionGuard $permissionGuard,
45
        private Domain\Repository\SiteLanguageRepository $siteLanguageRepository,
46
        private Domain\Repository\SiteRepository $siteRepository,
47
        private Typo3SitemapLocator\Sitemap\SitemapLocator $sitemapLocator,
48
        #[DependencyInjection\Attribute\Autowire('@cache.runtime')]
49
        private Core\Cache\Frontend\FrontendInterface $runtimeCache,
50
    ) {}
15✔
51

52
    /**
53
     * @return ($context is WarmupActionContext::Page ? PageWarmupActions|null : SiteWarmupActions|null)
54
     */
55
    public function provideActions(WarmupActionContext $context, int $pageId): PageWarmupActions|SiteWarmupActions|null
11✔
56
    {
57
        return match ($context) {
58
            WarmupActionContext::Page => $this->providePageActions($pageId),
11✔
59
            WarmupActionContext::Site => $this->provideSiteActions($pageId),
11✔
60
        };
61
    }
62

63
    public function provideSiteActions(int $pageId): ?SiteWarmupActions
11✔
64
    {
65
        if (!$this->isValidPage($pageId)) {
11✔
NEW
66
            return null;
×
67
        }
68

69
        $site = $this->siteRepository->findOneByRootPageId($pageId);
11✔
70

71
        // Early return if no associated site could be found
72
        if ($site === null) {
11✔
73
            return null;
1✔
74
        }
75

76
        // Get all languages of current site that are available for the current backend user
77
        $siteLanguages = array_filter(
10✔
78
            $this->siteLanguageRepository->findAll($site),
10✔
79
            fn(Core\Site\Entity\SiteLanguage $siteLanguage): bool => $this->canWarmupCachesOfSite($site, $siteLanguage),
10✔
80
        );
10✔
81

82
        return new SiteWarmupActions($site, $siteLanguages);
10✔
83
    }
84

85
    public function providePageActions(int $pageId): ?PageWarmupActions
11✔
86
    {
87
        if (!$this->isValidPage($pageId)) {
11✔
NEW
88
            return null;
×
89
        }
90

91
        $site = $this->siteRepository->findOneByPageId($pageId);
11✔
92

93
        // Early return if no associated site could be found
94
        if ($site === null) {
11✔
NEW
95
            return null;
×
96
        }
97

98
        // Get all languages of current site that are available for the current backend user
99
        $siteLanguages = array_filter(
11✔
100
            $this->siteLanguageRepository->findAll($site),
11✔
101
            fn(Core\Site\Entity\SiteLanguage $siteLanguage): bool => $this->permissionGuard->canWarmupCacheOfPage(
11✔
102
                $pageId,
11✔
103
                new Security\Context\PermissionContext($siteLanguage->getLanguageId()),
11✔
104
            ),
11✔
105
        );
11✔
106

107
        return new PageWarmupActions($pageId, $siteLanguages);
11✔
108
    }
109

110
    /**
111
     * @phpstan-assert-if-true non-negative-int $pageId
112
     */
113
    private function isValidPage(int $pageId): bool
11✔
114
    {
115
        $cacheIdentifier = 'warming_warmupActionsProvider_isValidPage_' . $pageId;
11✔
116

117
        // Return validation result from cache, if available
118
        if ($this->runtimeCache->has($cacheIdentifier)) {
11✔
119
            return $this->runtimeCache->get($cacheIdentifier);
11✔
120
        }
121

122
        // Root page cannot be used for cache warmup since it is not accessible in Frontend
123
        if ($pageId === 0) {
11✔
NEW
124
            return false;
×
125
        }
126

127
        $record = Backend\Utility\BackendUtility::getRecordWSOL('pages', $pageId);
11✔
128

129
        // Early return if page does not exist
130
        if ($record === null) {
11✔
NEW
131
            return false;
×
132
        }
133

134
        $doktype = (int)($record['doktype'] ?? 0);
11✔
135
        $isValidPage = $doktype > 0 && \in_array($doktype, $this->configuration->supportedDoktypes, true);
11✔
136

137
        // Store page validation in cache to avoid further lookups
138
        $this->runtimeCache->set($cacheIdentifier, $isValidPage);
11✔
139

140
        return $isValidPage;
11✔
141
    }
142

143
    private function canWarmupCachesOfSite(Core\Site\Entity\Site $site, Core\Site\Entity\SiteLanguage $siteLanguage): bool
9✔
144
    {
145
        try {
146
            // Check if any sitemap exists
147
            foreach ($this->sitemapLocator->locateBySite($site, $siteLanguage) as $sitemap) {
9✔
148
                if ($this->sitemapLocator->isValidSitemap($sitemap)) {
9✔
149
                    return true;
8✔
150
                }
151
            }
NEW
152
        } catch (\Exception) {
×
153
            // Unable to locate any sitemaps
154
        }
155

156
        return false;
1✔
157
    }
158
}
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