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

Yoast / Yoast-SEO-for-TYPO3 / 24723291290

21 Apr 2026 12:50PM UTC coverage: 10.457% (+9.2%) from 1.275%
24723291290

push

github

web-flow
Merge pull request #632 from Yoast/feature/yoast-v12

[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

40 of 806 new or added lines in 69 files covered. (4.96%)

40 existing lines in 23 files now uncovered.

284 of 2716 relevant lines covered (10.46%)

0.29 hits per line

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

0.0
/Classes/Service/ProminentWordsService.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\Service;
13

14
use TYPO3\CMS\Core\Database\Connection;
15
use TYPO3\CMS\Core\Database\ConnectionPool;
16
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
17
use YoastSeoForTypo3\YoastSeo\Constants\TableNames;
18

19
class ProminentWordsService
20
{
21
    protected int $uid;
22
    protected int $pid;
23
    protected string $table;
24
    protected int $languageId;
25

26
    public function __construct(
27
        protected ConnectionPool $connectionPool,
28
        protected SiteService $siteService
UNCOV
29
    ) {}
×
30

31
    /**
32
     * @param array<string, int|string> $prominentWords
33
     */
34
    public function saveProminentWords(
35
        int $uid,
36
        ?int $pid,
37
        string $table,
38
        int $languageId,
39
        array $prominentWords
40
    ): void {
41
        $this->uid = $uid;
×
42
        $this->pid = $pid ?? $this->getPidForRecord($uid, $table);
×
43
        $this->table = $table;
×
44
        $this->languageId = $languageId;
×
45

46
        $wordsToDelete = [];
×
47

48
        $oldWords = $this->getOldWords();
×
49
        foreach ($oldWords as $oldWord) {
×
50
            if (!isset($prominentWords[$oldWord['stem']])) {
×
51
                $wordsToDelete[] = $oldWord['uid'];
×
52
                continue;
×
53
            }
54

55
            $this->updateIfWeightHasChanged($oldWord, (int)$prominentWords[$oldWord['stem']]);
×
56
            unset($prominentWords[$oldWord['stem']]);
×
57
        }
58

59
        $this->deleteProminentWords($wordsToDelete);
×
60
        $this->createNewWords($prominentWords);
×
61
    }
62

63
    /**
64
     * @param array{uid: int, weight: int} $oldWord
65
     */
66
    protected function updateIfWeightHasChanged(array $oldWord, int $weight): void
67
    {
68
        if ((int)$oldWord['weight'] === $weight) {
×
69
            return;
×
70
        }
71
        $queryBuilder = $this->getQueryBuilder();
×
NEW
72
        $queryBuilder->update(TableNames::PROMINENT_WORD)
×
73
            ->set('weight', $weight)
×
74
            ->where(
×
75
                $queryBuilder->expr()->eq('uid', $oldWord['uid'])
×
76
            )
×
77
            ->setMaxResults(1)
×
78
            ->executeStatement();
×
79
    }
80

81
    /**
82
     * @param int[] $wordsToDelete
83
     */
84
    protected function deleteProminentWords(array $wordsToDelete): void
85
    {
86
        if ($wordsToDelete === []) {
×
87
            return;
×
88
        }
89

90
        $queryBuilder = $this->getQueryBuilder();
×
NEW
91
        $queryBuilder->delete(TableNames::PROMINENT_WORD)
×
92
            ->where(
×
93
                $queryBuilder->expr()->in(
×
94
                    'uid',
×
95
                    $queryBuilder->createNamedParameter($wordsToDelete, Connection::PARAM_INT_ARRAY)
×
96
                )
×
97
            )
×
98
            ->executeStatement();
×
99
    }
100

101
    /**
102
     * @param array<string, int|string> $prominentWords
103
     */
104
    protected function createNewWords(array $prominentWords): void
105
    {
NEW
106
        if ($prominentWords === []) {
×
NEW
107
            return;
×
108
        }
109

110
        $site = $this->getSiteRootPageId();
×
NEW
111
        $pid = $this->table === TableNames::PAGES ? $this->uid : $this->pid;
×
112

NEW
113
        $rows = [];
×
114
        foreach ($prominentWords as $word => $weight) {
×
NEW
115
            $rows[] = [
×
NEW
116
                $pid,
×
NEW
117
                $this->languageId,
×
NEW
118
                $this->uid,
×
NEW
119
                $site,
×
NEW
120
                $this->table,
×
NEW
121
                (string)$word,
×
NEW
122
                (int)$weight,
×
123
            ];
×
124
        }
125

NEW
126
        $this->connectionPool->getConnectionForTable(TableNames::PROMINENT_WORD)->bulkInsert(
×
NEW
127
            TableNames::PROMINENT_WORD,
×
NEW
128
            $rows,
×
NEW
129
            ['pid', 'sys_language_uid', 'uid_foreign', 'site', 'tablenames', 'stem', 'weight']
×
NEW
130
        );
×
131
    }
132

133
    /**
134
     * @return array<array{uid: int, stem: string, weight: int}>
135
     */
136
    protected function getOldWords(): array
137
    {
138
        $queryBuilder = $this->getQueryBuilder();
×
139
        $queryBuilder->select('uid', 'stem', 'weight')
×
NEW
140
            ->from(TableNames::PROMINENT_WORD)
×
141
            ->where(
×
142
                $queryBuilder->expr()->eq('uid_foreign', $this->uid),
×
143
                $queryBuilder->expr()->eq('tablenames', $queryBuilder->createNamedParameter($this->table)),
×
144
                $queryBuilder->expr()->eq('sys_language_uid', $this->languageId)
×
145
            );
×
146
        /** @var array<array{uid: int, stem: string, weight: int}> $oldWords */
147
        $oldWords = $queryBuilder->executeQuery()->fetchAllAssociative();
×
148
        return $oldWords;
×
149
    }
150

151
    protected function getPidForRecord(int $uid, string $table): int
152
    {
153
        $connection = $this->connectionPool->getConnectionForTable($table);
×
154
        $record = $connection->select(['pid'], $table, ['uid' => $uid])->fetchAssociative();
×
155
        return (int)($record['pid'] ?? 0);
×
156
    }
157

158
    protected function getSiteRootPageId(): int
159
    {
NEW
160
        return $this->siteService->getSiteRootPageId(
×
NEW
161
            $this->table === TableNames::PAGES ? $this->uid : $this->pid
×
NEW
162
        );
×
163
    }
164

165
    protected function getQueryBuilder(): QueryBuilder
166
    {
NEW
167
        return $this->connectionPool->getQueryBuilderForTable(TableNames::PROMINENT_WORD);
×
168
    }
169
}
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