Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Issues (210)

Classes/Hooks/DataHandler.php (2 issues)

1
<?php
2
3
/**
4
 * (c) Kitodo. Key to digital objects e.V. <[email protected]>
5
 *
6
 * This file is part of the Kitodo and TYPO3 projects.
7
 *
8
 * @license GNU General Public License version 3 or later.
9
 * For the full copyright and license information, please read the
10
 * LICENSE.txt file that was distributed with this source code.
11
 */
12
13
namespace Kitodo\Dlf\Hooks;
14
15
use Kitodo\Dlf\Common\AbstractDocument;
16
use Kitodo\Dlf\Common\Helper;
17
use Kitodo\Dlf\Common\Indexer;
18
use Kitodo\Dlf\Common\Solr\Solr;
19
use Kitodo\Dlf\Domain\Repository\DocumentRepository;
20
use Psr\Log\LoggerAwareInterface;
21
use Psr\Log\LoggerAwareTrait;
22
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
23
use TYPO3\CMS\Core\Database\ConnectionPool;
24
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
25
use TYPO3\CMS\Core\Utility\GeneralUtility;
26
27
/**
28
 * Hooks and helper for \TYPO3\CMS\Core\DataHandling\DataHandler
29
 *
30
 * @package TYPO3
31
 * @subpackage dlf
32
 *
33
 * @access public
34
 */
35
class DataHandler implements LoggerAwareInterface
36
{
37
    use LoggerAwareTrait;
38
39
    /**
40
     * Field post-processing hook for the process_datamap() method.
41
     *
42
     * @access public
43
     *
44
     * @param string $status 'new' or 'update'
45
     * @param string $table The destination table
46
     * @param int|string $id The uid of the record
47
     * @param array &$fieldArray Array of field values
48
     *
49
     * @return void
50
     */
51
    public function processDatamap_postProcessFieldArray(string $status, string $table, $id, array &$fieldArray): void // TODO: Add type-hinting for $id when dropping support for PHP 7.
52
    {
53
        if ($status == 'new') {
54
            switch ($table) {
55
                    // Field post-processing for table "tx_dlf_documents".
56
                case 'tx_dlf_documents':
57
                    // Set sorting field if empty.
58
                    if (
59
                        empty($fieldArray['title_sorting'])
60
                        && !empty($fieldArray['title'])
61
                    ) {
62
                        $fieldArray['title_sorting'] = $fieldArray['title'];
63
                    }
64
                    break;
65
                    // Field post-processing for table "tx_dlf_metadata".
66
                    // TODO: Include also subentries if available.
67
                case 'tx_dlf_metadata':
68
                    // Store field in index if it should appear in lists.
69
                    if (!empty($fieldArray['is_listed'])) {
70
                        $fieldArray['index_stored'] = 1;
71
                    }
72
                    // Index field in index if it should be used for auto-completion.
73
                    if (!empty($fieldArray['index_autocomplete'])) {
74
                        $fieldArray['index_indexed'] = 1;
75
                    }
76
                    // Field post-processing for tables "tx_dlf_metadata", "tx_dlf_collections", "tx_dlf_libraries" and "tx_dlf_structures".
77
                case 'tx_dlf_collections':
78
                case 'tx_dlf_libraries':
79
                case 'tx_dlf_structures':
80
                    // Set label as index name if empty.
81
                    if (
82
                        empty($fieldArray['index_name'])
83
                        && !empty($fieldArray['label'])
84
                    ) {
85
                        $fieldArray['index_name'] = $fieldArray['label'];
86
                    }
87
                    // Set index name as label if empty.
88
                    if (
89
                        empty($fieldArray['label'])
90
                        && !empty($fieldArray['index_name'])
91
                    ) {
92
                        $fieldArray['label'] = $fieldArray['index_name'];
93
                    }
94
                    // Ensure that index names don't get mixed up with sorting values.
95
                    if (substr($fieldArray['index_name'], -8) == '_sorting') {
96
                        $fieldArray['index_name'] .= '0';
97
                    }
98
                    break;
99
                    // Field post-processing for table "tx_dlf_solrcores".
100
                case 'tx_dlf_solrcores':
101
                    // Create new Solr core.
102
                    $fieldArray['index_name'] = Solr::createCore($fieldArray['index_name']);
103
                    if (empty($fieldArray['index_name'])) {
104
                        $this->logger->error('Could not create new Apache Solr core');
105
                        // Unset all fields to prevent new database record if Solr core creation failed.
106
                        unset($fieldArray);
107
                    }
108
                    break;
109
            }
110
        } elseif ($status == 'update') {
111
            switch ($table) {
112
                    // Field post-processing for table "tx_dlf_metadata".
113
                case 'tx_dlf_metadata':
114
                    $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
115
                        ->getQueryBuilderForTable($table);
116
117
                    // Store field in index if it should appear in lists.
118
                    if (!empty($fieldArray['is_listed'])) {
119
                        $fieldArray['index_stored'] = 1;
120
                    }
121
                    if (
122
                        isset($fieldArray['index_stored'])
123
                        && $fieldArray['index_stored'] == 0
124
                        && !isset($fieldArray['is_listed'])
125
                    ) {
126
                        // Get current configuration.
127
                        $result = $queryBuilder
128
                            ->select($table . '.is_listed AS is_listed')
129
                            ->from($table)
130
                            ->where(
131
                                $queryBuilder->expr()->eq($table . '.uid', (int) $id),
132
                                Helper::whereExpression($table)
133
                            )
134
                            ->setMaxResults(1)
135
                            ->execute();
136
137
                        $resArray = $result->fetchAssociative();
138
                        if (is_array($resArray)) {
139
                            // Reset storing to current.
140
                            $fieldArray['index_stored'] = $resArray['is_listed'];
141
                        }
142
                    }
143
                    // Index field in index if it should be used for auto-completion.
144
                    if (!empty($fieldArray['index_autocomplete'])) {
145
                        $fieldArray['index_indexed'] = 1;
146
                    }
147
                    if (
148
                        isset($fieldArray['index_indexed'])
149
                        && $fieldArray['index_indexed'] == 0
150
                        && !isset($fieldArray['index_autocomplete'])
151
                    ) {
152
                        // Get current configuration.
153
                        $result = $queryBuilder
154
                            ->select($table . '.index_autocomplete AS index_autocomplete')
155
                            ->from($table)
156
                            ->where(
157
                                $queryBuilder->expr()->eq($table . '.uid', (int) $id),
158
                                Helper::whereExpression($table)
159
                            )
160
                            ->setMaxResults(1)
161
                            ->execute();
162
163
                        if ($resArray = $result->fetchAssociative()) {
164
                            // Reset indexing to current.
165
                            $fieldArray['index_indexed'] = $resArray['index_autocomplete'];
166
                        }
167
                    }
168
                    break;
169
            }
170
        }
171
    }
172
173
    /**
174
     * After database operations hook for the process_datamap() method.
175
     *
176
     * @access public
177
     *
178
     * @param string $status 'new' or 'update'
179
     * @param string $table The destination table
180
     * @param int|string $id The uid of the record
181
     * @param array &$fieldArray Array of field values
182
     *
183
     * @return void
184
     */
185
    public function processDatamap_afterDatabaseOperations(string $status, string $table, $id, array &$fieldArray): void // TODO: Add type-hinting for $id when dropping support for PHP 7.
186
    {
187
        if ($status == 'update') {
188
            switch ($table) {
189
                    // After database operations for table "tx_dlf_documents".
190
                case 'tx_dlf_documents':
191
                    // Delete/reindex document in Solr if "hidden" status or collections have changed.
192
                    if (
193
                        isset($fieldArray['hidden'])
194
                        || isset($fieldArray['collections'])
195
                    ) {
196
                        // Get Solr-Core.
197
                        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
198
                            ->getQueryBuilderForTable('tx_dlf_solrcores');
199
200
                        $result = $queryBuilder
201
                            ->select(
202
                                'tx_dlf_solrcores.uid AS core',
203
                                'tx_dlf_solrcores.index_name',
204
                                'tx_dlf_documents_join.hidden AS hidden'
205
                            )
206
                            ->innerJoin(
207
                                'tx_dlf_solrcores',
208
                                'tx_dlf_documents',
209
                                'tx_dlf_documents_join',
210
                                $queryBuilder->expr()->eq(
211
                                    'tx_dlf_documents_join.solrcore',
212
                                    'tx_dlf_solrcores.uid'
213
                                )
214
                            )
215
                            ->from('tx_dlf_solrcores')
216
                            ->where(
217
                                $queryBuilder->expr()->eq(
218
                                    'tx_dlf_documents_join.uid',
219
                                    (int) $id
220
                                )
221
                            )
222
                            ->setMaxResults(1)
223
                            ->execute();
224
225
                        $resArray = $result->fetchAssociative();
226
                        if (is_array($resArray)) {
227
                            if ($resArray['hidden']) {
228
                                $this->deleteDocument($resArray['core'], $id);
229
                            } else {
230
                                $this->reindexDocument($id);
231
                            }
232
                        }
233
                    }
234
                    break;
235
            }
236
        }
237
    }
238
239
    /**
240
     * Post-processing hook for the process_cmdmap() method.
241
     *
242
     * @access public
243
     *
244
     * @param string $command 'move', 'copy', 'localize', 'inlineLocalizeSynchronize', 'delete' or 'undelete'
245
     * @param string $table The destination table
246
     * @param int|string $id The uid of the record
247
     *
248
     * @return void
249
     */
250
    public function processCmdmap_postProcess(string $command, string $table, $id): void // TODO: Add type-hinting for $id when dropping support for PHP 7.
251
    {
252
        if (
253
            in_array($command, ['move', 'delete', 'undelete'])
254
            && $table == 'tx_dlf_documents'
255
        ) {
256
            // Get Solr core.
257
            $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
258
                ->getQueryBuilderForTable('tx_dlf_solrcores');
259
            // Record in "tx_dlf_documents" is already deleted at this point.
260
            $queryBuilder
261
                ->getRestrictions()
262
                ->removeByType(DeletedRestriction::class);
263
264
            $result = $queryBuilder
265
                ->select(
266
                    'tx_dlf_solrcores.uid AS core'
267
                )
268
                ->innerJoin(
269
                    'tx_dlf_solrcores',
270
                    'tx_dlf_documents',
271
                    'tx_dlf_documents_join',
272
                    $queryBuilder->expr()->eq(
273
                        'tx_dlf_documents_join.solrcore',
274
                        'tx_dlf_solrcores.uid'
275
                    )
276
                )
277
                ->from('tx_dlf_solrcores')
278
                ->where(
279
                    $queryBuilder->expr()->eq(
280
                        'tx_dlf_documents_join.uid',
281
                        (int) $id
282
                    )
283
                )
284
                ->setMaxResults(1)
285
                ->execute();
286
287
            $resArray = $result->fetchAssociative();
288
            if (is_array($resArray)) {
289
                switch ($command) {
290
                    case 'move':
291
                    case 'delete':
292
                        $this->deleteDocument($resArray['core'], $id);
293
                        if ($command == 'delete') {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment if this fall-through is intended.
Loading history...
294
                            break;
295
                        }
296
                    case 'undelete':
297
                        $this->reindexDocument($id);
298
                        break;
299
                }
300
            }
301
        }
302
        if (
303
            $command === 'delete'
304
            && $table == 'tx_dlf_solrcores'
305
        ) {
306
            $this->deleteSolrCore($id);
307
        }
308
    }
309
310
    /**
311
     * Delete document from index.
312
     *
313
     * @access private
314
     *
315
     * @param mixed $core
316
     * @param int|string $id
317
     *
318
     * @return void
319
     */
320
    private function deleteDocument($core, $id): void
321
    {
322
        // Establish Solr connection.
323
        $solr = Solr::getInstance($core);
324
        if ($solr->ready) {
325
            // Delete Solr document.
326
            $updateQuery = $solr->service->createUpdate();
327
            $updateQuery->addDeleteQuery('uid:' . (int) $id);
328
            $updateQuery->addCommit(false);
329
            $solr->service->update($updateQuery);
330
        }
331
    }
332
333
    /**
334
     * Reindex document.
335
     *
336
     * @access private
337
     *
338
     * @param int|string $id
339
     *
340
     * @return void
341
     */
342
    private function reindexDocument($id):void
343
    {
344
        $documentRepository = GeneralUtility::makeInstance(DocumentRepository::class);
345
        $document = $documentRepository->findByUid((int) $id);
346
        $doc = AbstractDocument::getInstance($document->getLocation(), ['storagePid' => $document->getPid()], true);
347
        if ($document !== null && $doc !== null) {
348
            $document->setCurrentDocument($doc);
349
            Indexer::add($document, $documentRepository);
350
        } else {
351
            $this->logger->error('Failed to re-index document with UID ' . (string) $id);
352
        }
353
    }
354
355
    /**
356
     * Delete SOLR core if deletion is allowed.
357
     *
358
     * @access private
359
     *
360
     * @param int|string $id
361
     *
362
     * @return void
363
     */
364
    private function deleteSolrCore($id): void
365
    {
366
        // Is core deletion allowed in extension configuration?
367
        $extConf = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('dlf', 'solr');
368
        if (!empty($extConf['allowCoreDelete'])) {
369
            // Delete core from Apache Solr as well.
370
            $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
371
                ->getQueryBuilderForTable('tx_dlf_solrcores');
372
            // Record in "tx_dlf_solrcores" is already deleted at this point.
373
            $queryBuilder
374
                ->getRestrictions()
375
                ->removeByType(DeletedRestriction::class);
376
377
            $result = $queryBuilder
378
                ->select(
379
                    'tx_dlf_solrcores.index_name AS core'
380
                )
381
                ->from('tx_dlf_solrcores')
382
                ->where($queryBuilder->expr()->eq('tx_dlf_solrcores.uid', (int) $id))
383
                ->setMaxResults(1)
384
                ->execute();
385
386
            $resArray = $result->fetchAssociative();
387
            if (is_array($resArray)) {
388
                // Establish Solr connection.
389
                $solr = Solr::getInstance();
390
                if ($solr->ready) {
391
                    // Delete Solr core.
392
                    $query = $solr->service->createCoreAdmin();
393
                    $action = $query->createUnload();
394
                    $action->setCore($resArray['core']);
395
                    $action->setDeleteDataDir(true);
396
                    $action->setDeleteIndex(true);
397
                    $action->setDeleteInstanceDir(true);
398
                    $query->setAction($action);
399
                    try {
400
                        $response = $solr->service->coreAdmin($query);
401
                        if ($response->getWasSuccessful() == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
402
                            $this->logger->warning('Core ' . $resArray['core'] . ' could not be deleted from Apache Solr');
403
                        }
404
                    } catch (\Exception $e) {
405
                        $this->logger->warning($e->getMessage());
406
                    }
407
                }
408
            }
409
        }
410
    }
411
}
412