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

Yoast / Yoast-SEO-for-TYPO3 / 21521134747

30 Jan 2026 03:30PM UTC coverage: 0.866% (-0.4%) from 1.275%
21521134747

push

github

RinyVT
[FEATURE] Version 12.0.0, added v14 support, removed v11 support including php8.0 and php8.1, rewrote backend javascript functionality to typescript and webcomponents

0 of 550 new or added lines in 53 files covered. (0.0%)

33 existing lines in 21 files now uncovered.

23 of 2657 relevant lines covered (0.87%)

0.03 hits per line

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

0.0
/Classes/StructuredData/StructuredDataProviderManager.php
1
<?php
2

3
/**
4
 * This file is part of the "yoast_seo" extension for TYPO3 CMS.
5
 *
6
 * For the full copyright and license information, please read the
7
 * LICENSE.txt file that was distributed with this source code.
8
 */
9

10
declare(strict_types=1);
11

12
namespace YoastSeoForTypo3\YoastSeo\StructuredData;
13

14
use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
15
use TYPO3\CMS\Core\Service\DependencyOrderingService;
16
use TYPO3\CMS\Core\SingletonInterface;
17
use TYPO3\CMS\Core\TypoScript\TypoScriptService;
18
use TYPO3\CMS\Core\Utility\GeneralUtility;
19
use YoastSeoForTypo3\YoastSeo\Service\Frontend\FrontendServiceInterface;
20

21
class StructuredDataProviderManager implements SingletonInterface
22
{
23
    public function __construct(
24
        protected FrontendInterface $pageCache,
25
        protected FrontendServiceInterface $frontendService,
26
        protected DependencyOrderingService $dependencyOrderingService,
27
        protected TypoScriptService $typoScriptService,
UNCOV
28
    ) {}
×
29

30
    /**
31
     * @param array<string, mixed> $params
32
     */
33
    public function render(array &$params, object $pObj): void
34
    {
NEW
35
        if (!$this->frontendService->isFrontendRequest()) {
×
36
            return;
×
37
        }
38

39
        $data = $this->getStructuredData();
×
40

41
        $params['headerData']['StructuredDataManager']
×
42
            = $this->getSourceComment() . PHP_EOL . $this->buildJsonLdBlob($data);
×
43
    }
44

45
    /**
46
     * @param array<string, array<string, mixed>> $src
47
     */
48
    protected function buildJsonLdBlob(array $src): string
49
    {
NEW
50
        $data = $src ? array_merge(...array_values($src)) : [];
×
51

NEW
52
        return $data
×
NEW
53
            ? '<script type="application/ld+json">' . json_encode($data) . '</script>'
×
NEW
54
            : '';
×
55
    }
56

57
    /**
58
     * @return array<string, array<string, mixed>>
59
     */
60
    public function getStructuredData(): array
61
    {
62
        $structuredData = [];
×
63
        foreach ($this->getOrderedStructuredDataProviders() as $provider => $configuration) {
×
NEW
64
            $cacheIdentifier = $this->frontendService->getCacheIdentifier('-structured-data-' . $provider);
×
65
            if ($this->pageCache instanceof FrontendInterface) {
×
66
                $data = $this->pageCache->get($cacheIdentifier);
×
67
                if ($data !== false) {
×
68
                    $structuredData[$provider] = $data;
×
69
                    continue;
×
70
                }
71
            }
72
            $structuredDataProviderObject = $this->getStructuredDataProviderObject($configuration);
×
73
            if ($structuredDataProviderObject === null) {
×
74
                continue;
×
75
            }
76

77
            if ($data = $structuredDataProviderObject->getData()) {
×
78
                $this->pageCache->set(
×
79
                    $cacheIdentifier,
×
80
                    $data,
×
NEW
81
                    ['pageId_' . $this->frontendService->getPageUid()],
×
NEW
82
                    $this->frontendService->getCacheTimeout(),
×
UNCOV
83
                );
×
84
            }
85

86
            if (!empty($data)) {
×
87
                $structuredData[$provider] = $data;
×
88
            }
89
        }
90

91
        return $structuredData;
×
92
    }
93

94
    /**
95
     * @param array<string, mixed> $configuration
96
     */
97
    protected function getStructuredDataProviderObject(array $configuration): StructuredDataProviderInterface|null
98
    {
99
        if (!class_exists($configuration['provider']) || !is_subclass_of($configuration['provider'], StructuredDataProviderInterface::class)) {
×
100
            return null;
×
101
        }
102

103
        $providerObject = GeneralUtility::makeInstance($configuration['provider']);
×
104
        if (method_exists($providerObject, 'setConfiguration')) {
×
105
            $providerObject->setConfiguration($configuration);
×
106
        }
107
        return $providerObject;
×
108
    }
109

110
    /**
111
     * @return array<string, array<string, mixed>>
112
     */
113
    private function getOrderedStructuredDataProviders(): array
114
    {
115
        $structuredDataProviders = $this->getStructuredDataProviderConfiguration();
×
116
        $structuredDataProviders = $this->setProviderOrder($structuredDataProviders);
×
117

NEW
118
        return $this->dependencyOrderingService->orderByDependencies($structuredDataProviders);
×
119
    }
120

121
    /**
122
     * @return array<string, array<string, mixed>>
123
     */
124
    private function getStructuredDataProviderConfiguration(): array
125
    {
NEW
126
        $config = $this->typoScriptService->convertTypoScriptArrayToPlainArray(
×
NEW
127
            $this->frontendService->getTyposcriptConfiguration()
×
UNCOV
128
        );
×
129

130
        return $config['structuredData']['providers'] ?? [];
×
131
    }
132

133
    /**
134
     * @param array<string, array<string, mixed>> $orderInformation
135
     * @return array<string, array<string, mixed>>
136
     */
137
    protected function setProviderOrder(array $orderInformation): array
138
    {
139
        foreach ($orderInformation as $provider => &$configuration) {
×
140
            if (isset($configuration['before'])) {
×
141
                $configuration['before'] = $this->getOrderConfiguration($provider, $configuration, 'before');
×
142
            }
143
            if (isset($configuration['after'])) {
×
144
                $configuration['after'] = $this->getOrderConfiguration($provider, $configuration, 'after');
×
145
            }
146
        }
147
        return $orderInformation;
×
148
    }
149

150
    /**
151
     * @param array<string, mixed> $configuration
152
     * @return string[]
153
     */
154
    private function getOrderConfiguration(string $provider, array $configuration, string $key): array
155
    {
156
        if (is_string($configuration[$key])) {
×
157
            return GeneralUtility::trimExplode(',', $configuration[$key], true);
×
158
        }
159
        if (!is_array($configuration[$key])) {
×
160
            throw new \UnexpectedValueException(
×
161
                'The specified "' . $key . '" order configuration for provider "' . $provider . '" is invalid.',
×
162
                1551014599
×
163
            );
×
164
        }
165
        return $configuration[$key];
×
166
    }
167

168
    protected function getSourceComment(): string
169
    {
170
        return '<!-- This site is optimized with the Yoast SEO for TYPO3 plugin - https://yoast.com/typo3-extensions-seo/ -->';
×
171
    }
172
}
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

© 2026 Coveralls, Inc