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.
Passed
Pull Request — master (#655)
by
unknown
02:34
created

CollectionController::mainAction()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 22
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 10
c 1
b 0
f 0
dl 0
loc 22
rs 9.9332
cc 3
nc 4
nop 0
1
<?php
2
/**
3
 * (c) Kitodo. Key to digital objects e.V. <[email protected]>
4
 *
5
 * This file is part of the Kitodo and TYPO3 projects.
6
 *
7
 * @license GNU General Public License version 3 or later.
8
 * For the full copyright and license information, please read the
9
 * LICENSE.txt file that was distributed with this source code.
10
 */
11
12
namespace Kitodo\Dlf\Controller;
13
14
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
15
use \TYPO3\CMS\Extbase\Configuration\ConfigurationManager;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Extbase\Config...on\ConfigurationManager was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
16
use TYPO3\CMS\Core\Utility\GeneralUtility;
17
use Kitodo\Dlf\Common\DocumentList;
18
use Kitodo\Dlf\Common\Helper;
19
use Kitodo\Dlf\Common\Solr;
20
use TYPO3\CMS\Core\Database\ConnectionPool;
21
use TYPO3\CMS\Core\Utility\MathUtility;
22
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Extbase\Mvc\Controller\ActionController was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
23
use TYPO3\CMS\Extbase\Utility\DebuggerUtility;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Extbase\Utility\DebuggerUtility was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
24
use TYPO3\CMS\Frontend\Page\PageRepository;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Frontend\Page\PageRepository was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
25
26
class CollectionController extends ActionController
27
{
28
    const PARAMETER_PREFIX = 'tx_dlf';
29
30
    /**
31
     * This holds the hook objects
32
     *
33
     * @var array
34
     * @access protected
35
     */
36
    protected $hookObjects = [];
37
38
    /**
39
     * @var ConfigurationManager
40
     */
41
    protected $configurationManager;
42
43
    /**
44
     * @var \TYPO3\CMS\Core\Log\LogManager
45
     */
46
    protected $logger;
47
48
    /**
49
     * SearchController constructor.
50
     * @param $configurationManager
51
     */
52
    public function __construct(ConfigurationManager $configurationManager)
53
    {
54
        $this->configurationManager = $configurationManager;
55
        $this->logger = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Core\Log\LogManager')->getLogger(__CLASS__);
56
    }
57
58
    /**
59
     * The plugin main method
60
     */
61
    public function mainAction()
62
    {
63
        $collection = GeneralUtility::_GP(self::PARAMETER_PREFIX)['collection'];
64
65
        // Quit without doing anything if required configuration variables are not set.
66
        if (empty($this->settings['pages'])) {
67
            $this->logger->warning('Incomplete plugin configuration');
1 ignored issue
show
Bug introduced by
The method warning() does not exist on TYPO3\CMS\Core\Log\LogManager. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

67
            $this->logger->/** @scrutinizer ignore-call */ 
68
                           warning('Incomplete plugin configuration');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
68
        }
69
70
        // Get hook objects.
71
        // TODO: $this->hookObjects = Helper::getHookObjects($this->scriptRelPath);
72
73
        if ($collection) {
74
            $this->showSingleCollection($collection);
75
        } else {
76
            $this->showCollectionList();
77
        }
78
79
        $extensionConfiguration = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('dlf');
80
81
        $this->view->assign('forceAbsoluteUrl', $extensionConfiguration['forceAbsoluteUrl']);
82
        $this->view->assign('currentPageUid', $GLOBALS['TSFE']->id);
83
    }
84
85
    /**
86
     * Builds a collection list
87
     * @return void
88
     */
89
    protected function showCollectionList()
90
    {
91
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
92
            ->getQueryBuilderForTable('tx_dlf_collections');
93
94
        $selectedCollections = $queryBuilder->expr()->neq('tx_dlf_collections.uid', 0);
95
        $orderBy = 'tx_dlf_collections.label';
96
        $showUserDefinedColls = '';
97
        // Handle collections set by configuration.
98
        if ($this->settings['collections']) {
99
            if (
100
                count(explode(',', $this->settings['collections'])) == 1
101
                && empty($this->settings['dont_show_single'])
102
            ) {
103
                $this->showSingleCollection(intval(trim($this->settings['collections'], ' ,')));
104
            }
105
            $selectedCollections = $queryBuilder->expr()->in('tx_dlf_collections.uid', implode(',', GeneralUtility::intExplode(',', $this->settings['collections'])));
106
        }
107
108
        // Should user-defined collections be shown?
109
        if (empty($this->settings['show_userdefined'])) {
110
            $showUserDefinedColls = $queryBuilder->expr()->eq('tx_dlf_collections.fe_cruser_id', 0);
111
        } elseif ($this->settings['show_userdefined'] > 0) {
112
            if (!empty($GLOBALS['TSFE']->fe_user->user['uid'])) {
113
                $showUserDefinedColls = $queryBuilder->expr()->eq('tx_dlf_collections.fe_cruser_id', intval($GLOBALS['TSFE']->fe_user->user['uid']));
114
            } else {
115
                $showUserDefinedColls = $queryBuilder->expr()->neq('tx_dlf_collections.fe_cruser_id', 0);
116
            }
117
        }
118
119
        // Get collections.
120
        $queryBuilder
121
            ->select(
122
                'tx_dlf_collections.uid AS uid', // required by getRecordOverlay()
123
                'tx_dlf_collections.pid AS pid', // required by getRecordOverlay()
124
                'tx_dlf_collections.sys_language_uid AS sys_language_uid', // required by getRecordOverlay()
125
                'tx_dlf_collections.index_name AS index_name',
126
                'tx_dlf_collections.index_search as index_query',
127
                'tx_dlf_collections.label AS label',
128
                'tx_dlf_collections.thumbnail AS thumbnail',
129
                'tx_dlf_collections.description AS description',
130
                'tx_dlf_collections.priority AS priority'
131
            )
132
            ->from('tx_dlf_collections')
133
            ->where(
134
                $selectedCollections,
135
                $showUserDefinedColls,
136
                $queryBuilder->expr()->eq('tx_dlf_collections.pid', intval($this->settings['pages'])),
137
                $queryBuilder->expr()->andX(
138
                    $queryBuilder->expr()->orX(
139
                        $queryBuilder->expr()->in('tx_dlf_collections.sys_language_uid', [-1, 0]),
140
                        $queryBuilder->expr()->eq('tx_dlf_collections.sys_language_uid', $GLOBALS['TSFE']->sys_language_uid)
141
                    ),
142
                    $queryBuilder->expr()->eq('tx_dlf_collections.l18n_parent', 0)
143
                )
144
            )
145
            ->orderBy($orderBy);
146
147
        $result = $queryBuilder->execute();
148
        $count = $queryBuilder->count('uid')->execute()->fetchColumn(0);
149
150
        if ($count == 1 && empty($this->settings['dont_show_single'])) {
151
            $resArray = $result->fetch();
152
            $this->showSingleCollection(intval($resArray['uid']));
153
        }
154
        $solr = Solr::getInstance($this->settings['solrcore']);
155
        if (!$solr->ready) {
156
            $this->logger->error('Apache Solr not available');
1 ignored issue
show
Bug introduced by
The method error() does not exist on TYPO3\CMS\Core\Log\LogManager. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

156
            $this->logger->/** @scrutinizer ignore-call */ 
157
                           error('Apache Solr not available');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
157
            //return $content;
158
        }
159
        // We only care about the UID and partOf in the results and want them sorted
160
        $params['fields'] = 'uid,partof';
161
        $params['sort'] = ['uid' => 'asc'];
162
        $collections = [];
163
164
        // Get language overlay if on alterative website language.
165
        $pageRepository = GeneralUtility::makeInstance(PageRepository::class);
166
        while ($collectionData = $result->fetch()) {
167
            if ($collectionData['sys_language_uid'] != $GLOBALS['TSFE']->sys_language_content) {
168
                $collections[$collectionData['uid']] = $pageRepository->getRecordOverlay('tx_dlf_collections', $collectionData, $GLOBALS['TSFE']->sys_language_content, $GLOBALS['TSFE']->sys_language_contentOL);
169
                // keep the index_name of the default language
170
                $collections[$collectionData['uid']]['index_name'] = $collectionData['index_name'];
171
            } else {
172
                $collections[$collectionData['uid']] = $collectionData;
173
            }
174
        }
175
        // Sort collections according to flexform configuration
176
        if ($this->settings['collections']) {
177
            $sortedCollections = [];
178
            foreach (GeneralUtility::intExplode(',', $this->settings['collections']) as $uid) {
179
                $sortedCollections[$uid] = $collections[$uid];
180
            }
181
            $collections = $sortedCollections;
182
        }
183
184
        $processedCollections = [];
185
186
        // Process results.
187
        foreach ($collections as $collection) {
188
            $solr_query = '';
189
            if ($collection['index_query'] != '') {
190
                $solr_query .= '(' . $collection['index_query'] . ')';
191
            } else {
192
                $solr_query .= 'collection:("' . $collection['index_name'] . '")';
193
            }
194
            $partOfNothing = $solr->search_raw($solr_query . ' AND partof:0 AND toplevel:true', $params);
195
            $partOfSomething = $solr->search_raw($solr_query . ' AND NOT partof:0 AND toplevel:true', $params);
196
            // Titles are all documents that are "root" elements i.e. partof == 0
197
            $collection['titles'] = [];
198
            foreach ($partOfNothing as $doc) {
199
                $collection['titles'][$doc->uid] = $doc->uid;
200
            }
201
            // Volumes are documents that are both
202
            // a) "leaf" elements i.e. partof != 0
203
            // b) "root" elements that are not referenced by other documents ("root" elements that have no descendants)
204
            $collection['volumes'] = $collection['titles'];
205
            foreach ($partOfSomething as $doc) {
206
                $collection['volumes'][$doc->uid] = $doc->uid;
207
                // If a document is referenced via partof, it’s not a volume anymore.
208
                unset($collection['volumes'][$doc->partof]);
209
            }
210
211
            // Generate random but unique array key taking priority into account.
212
            do {
213
                $_key = ($collection['priority'] * 1000) + mt_rand(0, 1000);
214
            } while (!empty($processedCollections[$_key]));
215
216
            $collection['countTitles'] = count($collection['titles']);
217
            $collection['countVolumes'] = count($collection['volumes']);
218
219
            $processedCollections[$_key] = $collection;
220
        }
221
222
        // Randomize sorting?
223
        if (!empty($this->settings['randomize'])) {
224
            ksort($processedCollections, SORT_NUMERIC);
225
        }
226
227
        // TODO: Hook for getting custom collection hierarchies/subentries (requested by SBB).
228
        /*    foreach ($this->hookObjects as $hookObj) {
229
                if (method_exists($hookObj, 'showCollectionList_getCustomCollectionList')) {
230
                    $hookObj->showCollectionList_getCustomCollectionList($this, $this->settings['templateFile'], $content, $markerArray);
231
                }
232
            }
233
        */
234
235
        $this->view->assign('collections', $processedCollections);
236
    }
237
238
    /**
239
     * Builds a collection's list
240
     *
241
     * @access protected
242
     *
243
     * @param int $id: The collection's UID
244
     *
245
     * @return void
246
     */
247
    protected function showSingleCollection($id)
248
    {
249
        $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
250
        $queryBuilder = $connectionPool->getQueryBuilderForTable('tx_dlf_collections');
251
252
        $additionalWhere = '';
253
        // Should user-defined collections be shown?
254
        if (empty($this->settings['show_userdefined'])) {
255
            $additionalWhere = $queryBuilder->expr()->eq('tx_dlf_collections.fe_cruser_id', 0);
256
        } elseif ($this->settings['show_userdefined'] > 0) {
257
            $additionalWhere = $queryBuilder->expr()->neq('tx_dlf_collections.fe_cruser_id', 0);
258
        }
259
260
        // Get collection information from DB
261
        $collection = $queryBuilder
262
            ->select(
263
                'tx_dlf_collections.uid AS uid', // required by getRecordOverlay()
264
                'tx_dlf_collections.pid AS pid', // required by getRecordOverlay()
265
                'tx_dlf_collections.sys_language_uid AS sys_language_uid', // required by getRecordOverlay()
266
                'tx_dlf_collections.index_name AS index_name',
267
                'tx_dlf_collections.index_search as index_search',
268
                'tx_dlf_collections.label AS label',
269
                'tx_dlf_collections.description AS description',
270
                'tx_dlf_collections.thumbnail AS thumbnail',
271
                'tx_dlf_collections.fe_cruser_id'
272
            )
273
            ->from('tx_dlf_collections')
274
            ->where(
275
                $queryBuilder->expr()->eq('tx_dlf_collections.pid', intval($this->settings['pages'])),
276
                $queryBuilder->expr()->eq('tx_dlf_collections.uid', intval($id)),
277
                $additionalWhere,
278
                $queryBuilder->expr()->andX(
279
                    $queryBuilder->expr()->orX(
280
                        $queryBuilder->expr()->in('tx_dlf_collections.sys_language_uid', [-1, 0]),
281
                        $queryBuilder->expr()->eq('tx_dlf_collections.sys_language_uid', $GLOBALS['TSFE']->sys_language_uid)
282
                    ),
283
                    $queryBuilder->expr()->eq('tx_dlf_collections.l18n_parent', 0)
284
                ),
285
                Helper::whereExpression('tx_dlf_collections')
286
            )
287
            ->setMaxResults(1)
288
            ->execute();
289
290
        // Get language overlay if on alterative website language.
291
        $pageRepository = GeneralUtility::makeInstance(PageRepository::class);
292
        if ($resArray = $collection->fetch()) {
293
            if ($resArray['sys_language_uid'] != $GLOBALS['TSFE']->sys_language_content) {
294
                $collectionData = $pageRepository->getRecordOverlay('tx_dlf_collections', $resArray, $GLOBALS['TSFE']->sys_language_content, $GLOBALS['TSFE']->sys_language_contentOL);
295
                // keep the index_name of the default language
296
                $collectionData['index_name'] = $resArray['index_name'];
297
            } else {
298
                $collectionData = $resArray;
299
            }
300
        } else {
301
            $this->logger->warning('No collection with UID ' . $id . ' found.');
302
            return;
303
        }
304
        // Fetch corresponding document UIDs from Solr.
305
        if ($collectionData['index_search'] != '') {
306
            $solr_query = '(' . $collectionData['index_search'] . ')';
307
        } else {
308
            $solr_query = 'collection:("' . $collectionData['index_name'] . '") AND toplevel:true';
309
        }
310
        $solr = Solr::getInstance($this->settings['solrcore']);
311
        if (!$solr->ready) {
312
            $this->logger->error('Apache Solr not available');
313
            return;
314
        }
315
        $params['fields'] = 'uid';
316
        $params['sort'] = ['uid' => 'asc'];
317
        $solrResult = $solr->search_raw($solr_query, $params);
318
        // Initialize array
319
        $documentSet = [];
320
        foreach ($solrResult as $doc) {
321
            if ($doc->uid) {
322
                $documentSet[] = $doc->uid;
323
            }
324
        }
325
        $documentSet = array_unique($documentSet);
326
        $queryBuilder = $connectionPool->getQueryBuilderForTable('tx_dlf_documents');
327
        // Fetch document info for UIDs in $documentSet from DB
328
        $documents = $queryBuilder
329
            ->select(
330
                'tx_dlf_documents.uid AS uid',
331
                'tx_dlf_documents.metadata_sorting AS metadata_sorting',
332
                'tx_dlf_documents.volume_sorting AS volume_sorting',
333
                'tx_dlf_documents.partof AS partof'
334
            )
335
            ->from('tx_dlf_documents')
336
            ->where(
337
                $queryBuilder->expr()->eq('tx_dlf_documents.pid', intval($this->settings['pages'])),
338
                $queryBuilder->expr()->in('tx_dlf_documents.uid', $documentSet),
339
                Helper::whereExpression('tx_dlf_documents')
340
            )
341
            ->execute();
342
343
        $toplevel = [];
344
        $subparts = [];
345
        $listMetadata = [];
346
        // Process results.
347
        while ($resArray = $documents->fetch()) {
348
            if (empty($listMetadata)) {
349
                $listMetadata = [
350
                    'label' => htmlspecialchars($collectionData['label']),
351
                    'description' => $collectionData['description'],
352
                    'thumbnail' => htmlspecialchars($collectionData['thumbnail']),
353
                    'options' => [
354
                        'source' => 'collection',
355
                        'select' => $id,
356
                        'userid' => $collectionData['userid'],
357
                        'params' => ['filterquery' => [['query' => 'collection_faceting:("' . $collectionData['index_name'] . '")']]],
358
                        'core' => '',
359
                        'pid' => $this->settings['pages'],
360
                        'order' => 'title',
361
                        'order.asc' => true
362
                    ]
363
                ];
364
            }
365
            // Prepare document's metadata for sorting.
366
            $sorting = unserialize($resArray['metadata_sorting']);
367
            if (!empty($sorting['type']) && MathUtility::canBeInterpretedAsInteger($sorting['type'])) {
368
                $sorting['type'] = Helper::getIndexNameFromUid($sorting['type'], 'tx_dlf_structures', $this->settings['pages']);
369
            }
370
            if (!empty($sorting['owner']) && MathUtility::canBeInterpretedAsInteger($sorting['owner'])) {
371
                $sorting['owner'] = Helper::getIndexNameFromUid($sorting['owner'], 'tx_dlf_libraries', $this->settings['pages']);
372
            }
373
            if (!empty($sorting['collection']) && MathUtility::canBeInterpretedAsInteger($sorting['collection'])) {
374
                $sorting['collection'] = Helper::getIndexNameFromUid($sorting['collection'], 'tx_dlf_collections', $this->settings['pages']);
375
            }
376
            // Split toplevel documents from volumes.
377
            if ($resArray['partof'] == 0) {
378
                $toplevel[$resArray['uid']] = [
379
                    'u' => $resArray['uid'],
380
                    'h' => '',
381
                    's' => $sorting,
382
                    'p' => []
383
                ];
384
            } else {
385
                // volume_sorting should be always set - but it's not a required field. We append the uid to the array key to make it always unique.
386
                $subparts[$resArray['partof']][$resArray['volume_sorting'] . str_pad($resArray['uid'], 9, '0', STR_PAD_LEFT)] = [
387
                    'u' => $resArray['uid'],
388
                    'h' => '',
389
                    's' => $sorting,
390
                    'p' => []
391
                ];
392
            }
393
        }
394
        // Add volumes to the corresponding toplevel documents.
395
        foreach ($subparts as $partof => $parts) {
396
            ksort($parts);
397
            foreach ($parts as $part) {
398
                if (!empty($toplevel[$partof])) {
399
                    $toplevel[$partof]['p'][] = ['u' => $part['u']];
400
                } else {
401
                    $toplevel[$part['u']] = $part;
402
                }
403
            }
404
        }
405
        // Save list of documents.
406
        $list = GeneralUtility::makeInstance(DocumentList::class);
407
        $list->reset();
408
        $list->add(array_values($toplevel));
409
        $listMetadata['options']['numberOfToplevelHits'] = count($list);
410
        $list->metadata = $listMetadata;
411
        $list->sort('title');
412
        $list->save();
413
        // Clean output buffer.
414
        ob_end_clean();
415
416
        // Send headers.
417
        $extensionConfiguration = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('dlf');
418
419
        $this->uriBuilder->reset()->setTargetPageUid($this->settings['targetPid'])
420
            ->setCreateAbsoluteUri((!empty($extensionConfiguration['forceAbsoluteUrl']) ? true : false));
421
422
        if (
423
            !empty($extensionConfiguration['forceAbsoluteUrl']) &&
424
            !empty($extensionConfiguration['forceAbsoluteUrlHttps'])
425
        ) {
426
            $this->uriBuilder->setAbsoluteUriScheme('https');
427
        } else {
428
            $this->uriBuilder->setAbsoluteUriScheme('http');
429
        }
430
431
        $uri = $this->uriBuilder->uriFor('main', [], 'ListView', 'dlf', 'ListView');
432
        $this->redirectToURI($uri);
433
    }
434
}
435