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

Yoast / Yoast-SEO-for-TYPO3 / 21916594510

11 Feb 2026 05:54PM UTC coverage: 10.09% (+8.8%) from 1.275%
21916594510

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

28 of 550 new or added lines in 53 files covered. (5.09%)

33 existing lines in 21 files now uncovered.

268 of 2656 relevant lines covered (10.09%)

0.27 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