1
|
|
|
<?php |
2
|
|
|
namespace Aoe\UpdateRefindex\Typo3; |
3
|
|
|
|
4
|
|
|
/*************************************************************** |
5
|
|
|
* Copyright notice |
6
|
|
|
* |
7
|
|
|
* (c) 2021 AOE GmbH <[email protected]> |
8
|
|
|
* |
9
|
|
|
* All rights reserved |
10
|
|
|
* |
11
|
|
|
* This script is part of the TYPO3 project. The TYPO3 project is |
12
|
|
|
* free software; you can redistribute it and/or modify |
13
|
|
|
* it under the terms of the GNU General Public License as published by |
14
|
|
|
* the Free Software Foundation; either version 2 of the License, or |
15
|
|
|
* (at your option) any later version. |
16
|
|
|
* |
17
|
|
|
* The GNU General Public License can be found at |
18
|
|
|
* http://www.gnu.org/copyleft/gpl.html. |
19
|
|
|
* |
20
|
|
|
* This script is distributed in the hope that it will be useful, |
21
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
22
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
23
|
|
|
* GNU General Public License for more details. |
24
|
|
|
* |
25
|
|
|
* This copyright notice MUST APPEAR in all copies of the script! |
26
|
|
|
***************************************************************/ |
27
|
|
|
|
28
|
|
|
use Doctrine\DBAL\FetchMode; |
29
|
|
|
use PDO; |
30
|
|
|
use TYPO3\CMS\Core\Database\Connection; |
31
|
|
|
use TYPO3\CMS\Core\Database\ConnectionPool; |
32
|
|
|
use TYPO3\CMS\Core\Database\Query\QueryBuilder; |
33
|
|
|
use TYPO3\CMS\Core\Database\ReferenceIndex; |
34
|
|
|
use TYPO3\CMS\Core\Utility\GeneralUtility; |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* scheduler-task to update refindex of TYPO3 |
38
|
|
|
* |
39
|
|
|
* @package update_refindex |
40
|
|
|
* @subpackage Typo3 |
41
|
|
|
*/ |
42
|
|
|
class RefIndex |
43
|
|
|
{ |
44
|
|
|
const ARRAY_CHUNK_SIZE = 100; |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* @var ConnectionPool |
48
|
|
|
*/ |
49
|
|
|
private $connectionPool; |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* @var array |
53
|
|
|
*/ |
54
|
|
|
private $existingTables; |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* @var array |
58
|
|
|
*/ |
59
|
|
|
private $selectedTables = []; |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* @var ReferenceIndex |
63
|
|
|
*/ |
64
|
|
|
private $referenceIndex; |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* @param array $selectedTables |
68
|
|
|
* @return RefIndex |
69
|
|
|
*/ |
70
|
2 |
|
public function setSelectedTables(array $selectedTables) |
71
|
|
|
{ |
72
|
2 |
|
$this->selectedTables = $selectedTables; |
73
|
|
|
|
74
|
2 |
|
return $this; |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* @return array |
79
|
|
|
*/ |
80
|
2 |
|
public function getSelectedTables() |
81
|
|
|
{ |
82
|
2 |
|
return $this->selectedTables; |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
/** |
86
|
|
|
* @return array |
87
|
|
|
*/ |
88
|
1 |
|
public function getExistingTables() |
89
|
|
|
{ |
90
|
1 |
|
if ($this->existingTables === null) { |
91
|
1 |
|
$this->existingTables = array_keys($GLOBALS['TCA']); |
92
|
1 |
|
sort($this->existingTables); |
93
|
|
|
} |
94
|
|
|
|
95
|
1 |
|
return $this->existingTables; |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* update refIndex of selected tables |
100
|
|
|
*/ |
101
|
2 |
|
public function update() |
102
|
|
|
{ |
103
|
|
|
// update index of selected tables |
104
|
2 |
|
foreach ($this->getSelectedTables() as $selectedTable) { |
105
|
2 |
|
if (in_array($selectedTable, $this->getExistingTables(), true)) { |
106
|
1 |
|
$this->updateTable($selectedTable); |
107
|
|
|
} |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
// delete lost indexes ONLY if index of ALL tables where updated |
111
|
2 |
|
if (count($this->getExistingTables()) === count($this->getSelectedTables())) { |
112
|
1 |
|
$this->deleteLostIndexes(); |
113
|
|
|
} |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
/** |
117
|
|
|
* Searching lost indexes for non-existing tables |
118
|
|
|
* this code is inspired by the code of method 'updateIndex' in class '\TYPO3\CMS\Core\Database\ReferenceIndex' |
119
|
|
|
*/ |
120
|
1 |
|
protected function deleteLostIndexes() |
121
|
|
|
{ |
122
|
1 |
|
$queryBuilder = $this->getQueryBuilderForTable('sys_refindex'); |
123
|
|
|
$queryBuilder |
124
|
1 |
|
->delete('sys_refindex') |
125
|
1 |
|
->where( |
126
|
1 |
|
$queryBuilder->expr()->notIn( |
127
|
|
|
'tablename', |
128
|
1 |
|
$queryBuilder->createNamedParameter($this->getExistingTables(), Connection::PARAM_STR_ARRAY) |
129
|
|
|
) |
130
|
|
|
); |
131
|
1 |
|
$queryBuilder->execute(); |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
/** |
135
|
|
|
* update table |
136
|
|
|
* this code is inspired by the code of method 'updateIndex' in class '\TYPO3\CMS\Core\Database\ReferenceIndex' |
137
|
|
|
* |
138
|
|
|
* @param string $tableName |
139
|
|
|
*/ |
140
|
1 |
|
protected function updateTable($tableName) |
141
|
|
|
{ |
142
|
|
|
// Select all records from table, including deleted records |
143
|
1 |
|
$queryBuilder = $this->getQueryBuilderForTable($tableName); |
144
|
|
|
$allRecs = $queryBuilder |
|
|
|
|
145
|
1 |
|
->select('uid') |
146
|
1 |
|
->from($tableName) |
147
|
1 |
|
->execute() |
148
|
1 |
|
->fetchAll(FetchMode::ASSOCIATIVE); |
149
|
|
|
|
150
|
|
|
// Update refindex table for all records in table |
151
|
1 |
|
foreach ($allRecs as $recdat) { |
152
|
1 |
|
$this->getReferenceIndex()->updateRefIndexTable($tableName, $recdat['uid']); |
153
|
|
|
} |
154
|
|
|
|
155
|
1 |
|
$recUidList = $this->getDeletableRecUidListFromTable($tableName); |
156
|
|
|
|
157
|
1 |
|
if (!empty($recUidList)) { |
158
|
|
|
// Searching lost indexes for this table: |
159
|
1 |
|
$queryBuilder = $this->getQueryBuilderForTable('sys_refindex'); |
160
|
1 |
|
foreach (array_chunk($recUidList, self::ARRAY_CHUNK_SIZE) as $recUidChunk) { |
161
|
|
|
$queryBuilder |
162
|
1 |
|
->delete('sys_refindex') |
163
|
1 |
|
->where( |
164
|
1 |
|
$queryBuilder->expr()->eq( |
165
|
|
|
'tablename', |
166
|
1 |
|
$queryBuilder->createNamedParameter($tableName, PDO::PARAM_STR) |
167
|
|
|
) |
168
|
|
|
) |
169
|
1 |
|
->andWhere( |
170
|
1 |
|
$queryBuilder->expr()->in( |
171
|
|
|
'recuid', |
172
|
1 |
|
$queryBuilder->createNamedParameter($recUidChunk, Connection::PARAM_INT_ARRAY) |
173
|
|
|
) |
174
|
|
|
); |
175
|
1 |
|
$queryBuilder->execute(); |
176
|
|
|
} |
177
|
|
|
} |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
/** |
181
|
|
|
* @param string $tableName |
182
|
|
|
* |
183
|
|
|
* @return int[] |
184
|
|
|
*/ |
185
|
1 |
|
protected function getDeletableRecUidListFromTable($tableName): array |
186
|
|
|
{ |
187
|
|
|
// Select all records from table, including deleted records |
188
|
1 |
|
$subQueryBuilder = $this->getQueryBuilderForTable($tableName); |
189
|
|
|
$subQueryBuilder |
190
|
1 |
|
->select('uid') |
191
|
1 |
|
->from($tableName); |
192
|
|
|
|
193
|
|
|
// Select all records from sys_refindex which are not in $tableName, including deleted records |
194
|
1 |
|
$queryBuilder = $this->getQueryBuilderForTable('sys_refindex'); |
195
|
|
|
$queryBuilder |
196
|
1 |
|
->select('recuid') |
197
|
1 |
|
->from('sys_refindex') |
198
|
1 |
|
->where( |
199
|
1 |
|
$queryBuilder->expr()->eq('tablename', $queryBuilder->createNamedParameter($tableName, PDO::PARAM_STR)) |
200
|
|
|
) |
201
|
1 |
|
->andWhere($queryBuilder->expr()->notIn('recuid', $subQueryBuilder->getSQL())) |
202
|
1 |
|
->groupBy('recuid'); |
203
|
|
|
|
204
|
|
|
$allRecs = $queryBuilder |
|
|
|
|
205
|
1 |
|
->execute() |
206
|
1 |
|
->fetchAll(FetchMode::ASSOCIATIVE); |
207
|
|
|
|
208
|
1 |
|
$recUidList = [0]; |
209
|
1 |
|
foreach ($allRecs as $recdat) { |
210
|
|
|
$recUidList[] = (int)$recdat['recuid']; |
211
|
|
|
} |
212
|
|
|
|
213
|
1 |
|
return $recUidList; |
214
|
|
|
} |
215
|
|
|
|
216
|
|
|
/** |
217
|
|
|
* @return ReferenceIndex |
218
|
|
|
*/ |
219
|
1 |
|
protected function getReferenceIndex(): ReferenceIndex |
220
|
|
|
{ |
221
|
1 |
|
if (null === $this->referenceIndex) { |
222
|
1 |
|
$this->referenceIndex = GeneralUtility::makeInstance(ReferenceIndex::class); |
223
|
|
|
} |
224
|
|
|
|
225
|
1 |
|
return $this->referenceIndex; |
226
|
|
|
} |
227
|
|
|
|
228
|
|
|
/** |
229
|
|
|
* @param string $table |
230
|
|
|
* @param bool $useEnableFields |
231
|
|
|
* @return QueryBuilder |
232
|
|
|
*/ |
233
|
3 |
|
private function getQueryBuilderForTable(string $table, bool $useEnableFields = false): QueryBuilder |
234
|
|
|
{ |
235
|
3 |
|
$connectionPool = $this->getConnectionPool(); |
236
|
3 |
|
$queryBuilder = $connectionPool->getQueryBuilderForTable($table); |
237
|
|
|
|
238
|
3 |
|
if (false === $useEnableFields) { |
239
|
3 |
|
$queryBuilder->getRestrictions()->removeAll(); |
240
|
|
|
} |
241
|
|
|
|
242
|
3 |
|
return $queryBuilder; |
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
/** |
246
|
|
|
* @return ConnectionPool |
247
|
|
|
*/ |
248
|
3 |
|
private function getConnectionPool(): ConnectionPool |
249
|
|
|
{ |
250
|
3 |
|
if (null === $this->connectionPool) { |
251
|
3 |
|
$this->connectionPool = GeneralUtility::makeInstance(ConnectionPool::class); |
252
|
|
|
} |
253
|
|
|
|
254
|
3 |
|
return $this->connectionPool; |
255
|
|
|
} |
256
|
|
|
} |
257
|
|
|
|
This function has been deprecated. The supplier of the function has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.