Completed
Push — master ( 2700b4...4ccb05 )
by Torben
04:03 queued 02:37
created

PopulateSfEventMgtSlugUpdater::populateSlugs()   B

Complexity

Conditions 7
Paths 10

Size

Total Lines 47

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 47
rs 8.223
c 0
b 0
f 0
cc 7
nc 10
nop 1
1
<?php
2
namespace DERHANSEN\SfEventMgt\Updates;
3
4
/*
5
 * This file is part of the Extension "sf_event_mgt" for TYPO3 CMS.
6
 *
7
 * For the full copyright and license information, please read the
8
 * LICENSE.txt file that was distributed with this source code.
9
 */
10
11
use TYPO3\CMS\Core\Database\ConnectionPool;
12
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
13
use TYPO3\CMS\Core\DataHandling\Model\RecordStateFactory;
14
use TYPO3\CMS\Core\DataHandling\SlugHelper;
15
use TYPO3\CMS\Core\Utility\GeneralUtility;
16
use TYPO3\CMS\Install\Updates\DatabaseUpdatedPrerequisite;
17
use TYPO3\CMS\Install\Updates\UpgradeWizardInterface;
18
19
/**
20
 * Class PopulateSfEventMgtSlugUpdater
21
 */
22
class PopulateSfEventMgtSlugUpdater implements UpgradeWizardInterface
23
{
24
    protected $tables = [
25
        'tx_sfeventmgt_domain_model_event',
26
        'tx_sfeventmgt_domain_model_location',
27
        'tx_sfeventmgt_domain_model_organisator',
28
        'tx_sfeventmgt_domain_model_speaker',
29
    ];
30
31
    /**
32
     * @return string Unique identifier of this updater
33
     */
34
    public function getIdentifier(): string
35
    {
36
        return 'populateSfEventMgtSlugUpdater';
37
    }
38
39
    /**
40
     * Get title
41
     *
42
     * @return string
43
     */
44
    public function getTitle(): string
45
    {
46
        return 'Introduce URL parts ("slugs") to all records of EXT:sf_event_mgt';
47
    }
48
49
    /**
50
     * Get description
51
     *
52
     * @return string Longer description of this updater
53
     */
54
    public function getDescription(): string
55
    {
56
        return 'This wizard will fill URL parts ("slugs") for events, locations, organisators and speakers.';
57
    }
58
59
    /**
60
     * Checks whether updates are required.
61
     *
62
     * @return bool Whether an update is required (true) or not (false)
63
     */
64
    public function updateNecessary(): bool
65
    {
66
        return $this->checkIfWizardIsRequired();
67
    }
68
69
    /**
70
     * @return string[] All new fields and tables must exist
71
     */
72
    public function getPrerequisites(): array
73
    {
74
        return [
75
            DatabaseUpdatedPrerequisite::class
76
        ];
77
    }
78
79
    /**
80
     * Performs the updates.
81
     *
82
     * @return bool Whether everything went smoothly or not
83
     */
84
    public function executeUpdate(): bool
85
    {
86
        foreach ($this->tables as $table) {
87
            $this->populateSlugs($table);
88
        }
89
90
        return true;
91
    }
92
93
    /**
94
     * Returns, if the wizard must be executed
95
     *
96
     * @return bool
97
     */
98
    public function checkIfWizardIsRequired(): bool
99
    {
100
        $numberOfEntries = 0;
101
        $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
102
103
        foreach ($this->tables as $table) {
104
            $queryBuilder = $connectionPool->getQueryBuilderForTable($table);
105
            $queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(DeletedRestriction::class));
106
107
            $numberOfEntries += $queryBuilder
108
                ->count('uid')
109
                ->from($table)
110
                ->where(
111
                    $queryBuilder->expr()->orX(
112
                        $queryBuilder->expr()->eq('slug', $queryBuilder->createNamedParameter('')),
113
                        $queryBuilder->expr()->isNull('slug')
114
                    )
115
                )
116
                ->execute()
117
                ->fetchColumn();
118
        }
119
120
        return $numberOfEntries > 0;
121
    }
122
123
    /**
124
     * Fills the given database table with slugs based on the configuration of the field.
125
     *
126
     * @param string $table
127
     * @return void
128
     */
129
    public function populateSlugs(string $table)
130
    {
131
        $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);
132
        $queryBuilder = $connection->createQueryBuilder();
133
        $queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(DeletedRestriction::class));
134
        $statement = $queryBuilder
135
            ->select('*')
136
            ->from($table)
137
            ->where(
138
                $queryBuilder->expr()->orX(
139
                    $queryBuilder->expr()->eq('slug', $queryBuilder->createNamedParameter('')),
140
                    $queryBuilder->expr()->isNull('slug')
141
                )
142
            )
143
            // Ensure that live workspace records are handled first
144
            ->addOrderBy('t3ver_wsid', 'asc')
145
            // Ensure that all pages are run through "per parent page" field, and in the correct sorting values
146
            ->addOrderBy('pid', 'asc')
147
            ->addOrderBy('sorting', 'asc')
148
            ->execute();
149
150
        $fieldConfig = $GLOBALS['TCA'][$table]['columns']['slug']['config'];
151
        $evalInfo = !empty($fieldConfig['eval']) ? GeneralUtility::trimExplode(',', $fieldConfig['eval'], true) : [];
152
        $hasToBeUniqueInSite = in_array('uniqueInSite', $evalInfo, true);
153
        $hasToBeUniqueInPid = in_array('uniqueInPid', $evalInfo, true);
154
        $slugHelper = GeneralUtility::makeInstance(SlugHelper::class, $table, 'slug', $fieldConfig);
155
        while ($record = $statement->fetch()) {
156
            $recordId = (int)$record['uid'];
157
            $pid = (int)$record['pid'];
158
            $slug = $slugHelper->generate($record, $pid);
159
160
            $state = RecordStateFactory::forName($table)
161
                ->fromArray($record, $pid, $recordId);
162
            if ($hasToBeUniqueInSite && !$slugHelper->isUniqueInSite($slug, $state)) {
163
                $slug = $slugHelper->buildSlugForUniqueInSite($slug, $state);
164
            }
165
            if ($hasToBeUniqueInPid && !$slugHelper->isUniqueInPid($slug, $state)) {
166
                $slug = $slugHelper->buildSlugForUniqueInPid($slug, $state);
167
            }
168
169
            $connection->update(
170
                $table,
171
                ['slug' => $slug],
172
                ['uid' => $recordId]
173
            );
174
        }
175
    }
176
}
177