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

eliashaeussler / typo3-sitemap-locator / 12427961353

20 Dec 2024 04:25AM CUT coverage: 78.261%. Remained the same
12427961353

push

github

web-flow
[TASK] Update ssch/typo3-rector to v2.12.2

| datasource | package           | from   | to     |
| ---------- | ----------------- | ------ | ------ |
| packagist  | ssch/typo3-rector | 2.12.1 | 2.12.2 |

504 of 644 relevant lines covered (78.26%)

4.52 hits per line

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

0.0
/Classes/Form/Element/XmlSitemapLocationElement.php
1
<?php
2

3
declare(strict_types=1);
4

5
/*
6
 * This file is part of the TYPO3 CMS extension "sitemap_locator".
7
 *
8
 * Copyright (C) 2023-2024 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\Typo3SitemapLocator\Form\Element;
25

26
use EliasHaeussler\Typo3SitemapLocator\Domain;
27
use EliasHaeussler\Typo3SitemapLocator\Exception;
28
use EliasHaeussler\Typo3SitemapLocator\Sitemap;
29
use TYPO3\CMS\Backend;
30
use TYPO3\CMS\Core;
31

32
/**
33
 * XmlSitemapLocationElement
34
 *
35
 * @author Elias Häußler <elias@haeussler.dev>
36
 * @license GPL-2.0-or-later
37
 */
38
final class XmlSitemapLocationElement extends Backend\Form\Element\AbstractFormElement
39
{
40
    /**
41
     * @var array<string, mixed>
42
     */
43
    protected $defaultFieldInformation = [
44
        'tcaDescription' => [
45
            'renderType' => 'tcaDescription',
46
        ],
47
    ];
48

49
    /**
50
     * @todo Make private readonly Core\Imaging\IconFactory once support for TYPO3 v12 is dropped
51
     */
52
    protected $iconFactory;
53
    private readonly Core\Site\SiteFinder $siteFinder;
54
    private readonly Sitemap\SitemapLocator $sitemapLocator;
55

56
    /**
57
     * @todo Use DI once support for TYPO3 v12 is dropped
58
     */
59
    public function __construct(?Backend\Form\NodeFactory $nodeFactory = null, array $data = [])
×
60
    {
61
        if ((new Core\Information\Typo3Version())->getMajorVersion() < 13) {
×
62
            parent::__construct($nodeFactory, $data);
×
63
        } else {
64
            $this->iconFactory = Core\Utility\GeneralUtility::makeInstance(Core\Imaging\IconFactory::class);
×
65
        }
66

67
        $this->siteFinder = Core\Utility\GeneralUtility::makeInstance(Core\Site\SiteFinder::class);
×
68
        $this->sitemapLocator = Core\Utility\GeneralUtility::makeInstance(Sitemap\SitemapLocator::class);
×
69
    }
70

71
    /**
72
     * @return array<string, mixed>
73
     */
74
    public function render(): array
×
75
    {
76
        $fieldInformationResult = $this->renderFieldInformation();
×
77
        $resultArray = $this->mergeChildReturnIntoExistingResult($this->initializeResultArray(), $fieldInformationResult);
×
78

79
        $html = [];
×
80
        $html[] = '<div class="formengine-field-item t3js-formengine-field-item">';
×
81
        $html[] =     '<div class="form-wizards-wrap">';
×
82
        $html[] =         '<div class="form-wizards-element">';
×
83
        $html[] =             $this->renderSitemapStatus();
×
84
        $html[] =         '</div>';
×
85
        $html[] =     '</div>';
×
86
        $html[] = '</div>';
×
87

88
        $resultArray['html'] .= PHP_EOL . implode(PHP_EOL, $html);
×
89

90
        return $resultArray;
×
91
    }
92

93
    private function renderSitemapStatus(): string
×
94
    {
95
        $command = $this->data['command'];
×
96

97
        // Early return on new data
98
        if ($command !== 'edit') {
×
99
            return $this->renderCallout(
×
100
                'info',
×
101
                'actions-info',
×
102
                $this->translate('xml_sitemap_location.alert.new_site'),
×
103
                false,
×
104
            );
×
105
        }
106

107
        try {
108
            [$site, $siteLanguage] = $this->resolveCurrentSiteAndLanguage();
×
109
            $sitemaps = $this->sitemapLocator->locateBySite($site, $siteLanguage);
×
110
        } catch (\Exception $exception) {
×
111
            return $this->renderCallout(
×
112
                'danger',
×
113
                'actions-exclamation',
×
114
                $exception->getMessage(),
×
115
                false,
×
116
            );
×
117
        }
118

119
        // Early return if no sitemaps were found
120
        if ($sitemaps === []) {
×
121
            return $this->renderCallout(
×
122
                'info',
×
123
                'actions-info',
×
124
                $this->translate('xml_sitemap_location.alert.no_sitemaps'),
×
125
                false,
×
126
            );
×
127
        }
128

129
        $html = [];
×
130

131
        foreach ($sitemaps as $sitemap) {
×
132
            $html[] = $this->renderSitemap($sitemap);
×
133
        }
134

135
        return implode(PHP_EOL, $html);
×
136
    }
137

138
    /**
139
     * @return array{Core\Site\Entity\Site, Core\Site\Entity\SiteLanguage}
140
     * @throws Core\Exception\SiteNotFoundException
141
     * @throws Exception\TableIsNotSupported
142
     */
143
    private function resolveCurrentSiteAndLanguage(): array
×
144
    {
145
        $row = $this->data['databaseRow'];
×
146
        $tableName = $this->data['tableName'];
×
147

148
        $site = $this->siteFinder->getSiteByRootPageId(
×
149
            match ($tableName) {
×
150
                'site' => (int)$row['rootPageId'][0],
×
151
                'site_language' => (int)$this->data['inlineParentUid'],
×
152
                default => throw new Exception\TableIsNotSupported($tableName),
×
153
            },
×
154
        );
×
155

156
        $siteLanguage = match ($tableName) {
×
157
            'site' => $site->getDefaultLanguage(),
×
158
            'site_language' => $site->getLanguageById((int)$row['languageId'][0]),
×
159
            default => throw new Exception\TableIsNotSupported($tableName),
×
160
        };
×
161

162
        return [$site, $siteLanguage];
×
163
    }
164

165
    private function renderSitemap(Domain\Model\Sitemap $sitemap): string
×
166
    {
167
        $url = (string)$sitemap->getUri();
×
168
        $baseUrl = rtrim((string)$sitemap->getSiteLanguage()->getBase(), '/') . '/';
×
169

170
        // Compare site base URL and sitemap URL
171
        if (!str_starts_with($url, $baseUrl)) {
×
172
            $baseUrl = '';
×
173
            $sitemapPath = $url;
×
174
        } else {
175
            $sitemapPath = preg_replace('#^' . preg_quote($baseUrl, '#') . '#', '', $url);
×
176
        }
177

178
        // Render callout body
179
        $body = sprintf(
×
180
            '<a href="%s" target="_blank">%s<strong>%s</strong></a>',
×
181
            $url,
×
182
            $baseUrl,
×
183
            $sitemapPath,
×
184
        );
×
185

186
        if ($this->sitemapLocator->isValidSitemap($sitemap)) {
×
187
            return $this->renderCallout('success', 'actions-check', $body);
×
188
        }
189

190
        return $this->renderCallout('warning', 'actions-exclamation', $body);
×
191
    }
192

193
    private function renderCallout(string $state, string $icon, string $body, bool $small = true): string
×
194
    {
195
        $classes = [
×
196
            'callout',
×
197
            'callout-' . $state,
×
198
        ];
×
199

200
        if ($small) {
×
201
            $classes[] = 'callout-sm';
×
202
        }
203

204
        $html = [];
×
205
        $html[] = '<div class="' . implode(' ', $classes) . '">';
×
206
        $html[] =     '<div class="media">';
×
207
        $html[] =         '<div class="media-left">';
×
208
        $html[] =             '<span class="icon-emphasized">';
×
209
        $html[] =                 $this->renderIcon($icon);
×
210
        $html[] =             '</span>';
×
211
        $html[] =         '</div>';
×
212
        $html[] =         '<div class="media-body">';
×
213
        $html[] =             '<div class="callout-body">';
×
214
        $html[] =                 $body;
×
215
        $html[] =             '</div>';
×
216
        $html[] =         '</div>';
×
217
        $html[] =     '</div>';
×
218
        $html[] = '</div>';
×
219

220
        return implode(PHP_EOL, $html);
×
221
    }
222

223
    private function renderIcon(string $identifier): string
×
224
    {
225
        if (enum_exists(Core\Imaging\IconSize::class)) {
×
226
            $iconSize = Core\Imaging\IconSize::SMALL;
×
227
        } else {
228
            $iconSize = Core\Imaging\Icon::SIZE_SMALL;
×
229
        }
230

231
        return $this->iconFactory->getIcon($identifier, $iconSize)->render();
×
232
    }
233

234
    private function translate(string $key): string
×
235
    {
236
        return $this->getLanguageService()->sL('LLL:EXT:sitemap_locator/Resources/Private/Language/locallang.xlf:' . $key);
×
237
    }
238
}
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