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 — dev-extbase-fluid (#732)
by Alexander
03:15
created

CollectionController   B

Complexity

Total Complexity 44

Size/Duplication

Total Lines 375
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 226
c 2
b 0
f 0
dl 0
loc 375
rs 8.8798
wmc 44

3 Methods

Rating   Name   Duplication   Size   Complexity  
F showCollectionList() 0 147 20
A mainAction() 0 22 3
F showSingleCollection() 0 174 21

How to fix   Complexity   

Complex Class

Complex classes like CollectionController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use CollectionController, and based on these observations, apply Extract Interface, too.

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 Kitodo\Dlf\Common\DocumentList;
15
use Kitodo\Dlf\Common\Helper;
16
use Kitodo\Dlf\Common\Solr;
17
use TYPO3\CMS\Core\Database\ConnectionPool;
18
use TYPO3\CMS\Core\Utility\GeneralUtility;
19
use TYPO3\CMS\Core\Utility\MathUtility;
20
use TYPO3\CMS\Frontend\Page\PageRepository;
21
22
class CollectionController extends AbstractController
23
{
24
    /**
25
     * This holds the hook objects
26
     *
27
     * @var array
28
     * @access protected
29
     */
30
    protected $hookObjects = [];
31
32
    /**
33
     * The main method of the plugin
34
     *
35
     * @return void
36
     */
37
    public function mainAction()
38
    {
39
        // access to GET parameter tx_dlf_collection['collection']
40
        $requestData = $this->request->getArguments();
41
42
        $collection = $requestData['collection'];
43
44
        // Quit without doing anything if required configuration variables are not set.
45
        if (empty($this->settings['pages'])) {
46
            $this->logger->warning('Incomplete plugin configuration');
1 ignored issue
show
Bug introduced by
The method warning() does not exist on null. ( Ignorable by Annotation )

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

46
            $this->logger->/** @scrutinizer ignore-call */ 
47
                           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...
47
        }
48
49
        // Get hook objects.
50
        // TODO: $this->hookObjects = Helper::getHookObjects($this->scriptRelPath);
51
52
        if ($collection) {
53
            $this->showSingleCollection($collection);
54
        } else {
55
            $this->showCollectionList();
56
        }
57
58
        $this->view->assign('currentPageUid', $GLOBALS['TSFE']->id);
59
    }
60
61
    /**
62
     * Builds a collection list
63
     * @return void
64
     */
65
    protected function showCollectionList()
66
    {
67
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
68
            ->getQueryBuilderForTable('tx_dlf_collections');
69
70
        $selectedCollections = $queryBuilder->expr()->neq('tx_dlf_collections.uid', 0);
71
        $orderBy = 'tx_dlf_collections.label';
72
        $showUserDefinedColls = '';
73
        // Handle collections set by configuration.
74
        if ($this->settings['collections']) {
75
            if (
76
                count(explode(',', $this->settings['collections'])) == 1
77
                && empty($this->settings['dont_show_single'])
78
            ) {
79
                $this->showSingleCollection(intval(trim($this->settings['collections'], ' ,')));
80
            }
81
            $selectedCollections = $queryBuilder->expr()->in('tx_dlf_collections.uid', implode(',', GeneralUtility::intExplode(',', $this->settings['collections'])));
82
        }
83
84
        // Should user-defined collections be shown?
85
        if (empty($this->settings['show_userdefined'])) {
86
            $showUserDefinedColls = $queryBuilder->expr()->eq('tx_dlf_collections.fe_cruser_id', 0);
87
        } elseif ($this->settings['show_userdefined'] > 0) {
88
            if (!empty($GLOBALS['TSFE']->fe_user->user['uid'])) {
89
                $showUserDefinedColls = $queryBuilder->expr()->eq('tx_dlf_collections.fe_cruser_id', intval($GLOBALS['TSFE']->fe_user->user['uid']));
90
            } else {
91
                $showUserDefinedColls = $queryBuilder->expr()->neq('tx_dlf_collections.fe_cruser_id', 0);
92
            }
93
        }
94
95
        // Get collections.
96
        $queryBuilder
97
            ->select(
98
                'tx_dlf_collections.uid AS uid', // required by getRecordOverlay()
99
                'tx_dlf_collections.pid AS pid', // required by getRecordOverlay()
100
                'tx_dlf_collections.sys_language_uid AS sys_language_uid', // required by getRecordOverlay()
101
                'tx_dlf_collections.index_name AS index_name',
102
                'tx_dlf_collections.index_search as index_query',
103
                'tx_dlf_collections.label AS label',
104
                'tx_dlf_collections.thumbnail AS thumbnail',
105
                'tx_dlf_collections.description AS description',
106
                'tx_dlf_collections.priority AS priority'
107
            )
108
            ->from('tx_dlf_collections')
109
            ->where(
110
                $selectedCollections,
111
                $showUserDefinedColls,
112
                $queryBuilder->expr()->eq('tx_dlf_collections.pid', intval($this->settings['pages'])),
113
                $queryBuilder->expr()->andX(
114
                    $queryBuilder->expr()->orX(
115
                        $queryBuilder->expr()->in('tx_dlf_collections.sys_language_uid', [-1, 0]),
116
                        $queryBuilder->expr()->eq('tx_dlf_collections.sys_language_uid', $GLOBALS['TSFE']->sys_language_uid)
117
                    ),
118
                    $queryBuilder->expr()->eq('tx_dlf_collections.l18n_parent', 0)
119
                )
120
            )
121
            ->orderBy($orderBy);
122
123
        $result = $queryBuilder->execute();
124
        $count = $queryBuilder->count('uid')->execute()->fetchColumn(0);
125
126
        if ($count == 1 && empty($this->settings['dont_show_single'])) {
127
            $resArray = $result->fetch();
128
            $this->showSingleCollection(intval($resArray['uid']));
129
        }
130
        $solr = Solr::getInstance($this->settings['solrcore']);
131
        if (!$solr->ready) {
132
            $this->logger->error('Apache Solr not available');
133
            //return $content;
134
        }
135
        // We only care about the UID and partOf in the results and want them sorted
136
        $params['fields'] = 'uid,partof';
137
        $params['sort'] = ['uid' => 'asc'];
138
        $collections = [];
139
140
        // Get language overlay if on alterative website language.
141
        $pageRepository = GeneralUtility::makeInstance(PageRepository::class);
142
        while ($collectionData = $result->fetch()) {
143
            if ($collectionData['sys_language_uid'] != $GLOBALS['TSFE']->sys_language_content) {
144
                $collections[$collectionData['uid']] = $pageRepository->getRecordOverlay('tx_dlf_collections', $collectionData, $GLOBALS['TSFE']->sys_language_content, $GLOBALS['TSFE']->sys_language_contentOL);
145
                // keep the index_name of the default language
146
                $collections[$collectionData['uid']]['index_name'] = $collectionData['index_name'];
147
            } else {
148
                $collections[$collectionData['uid']] = $collectionData;
149
            }
150
        }
151
        // Sort collections according to flexform configuration
152
        if ($this->settings['collections']) {
153
            $sortedCollections = [];
154
            foreach (GeneralUtility::intExplode(',', $this->settings['collections']) as $uid) {
155
                $sortedCollections[$uid] = $collections[$uid];
156
            }
157
            $collections = $sortedCollections;
158
        }
159
160
        $processedCollections = [];
161
162
        // Process results.
163
        foreach ($collections as $collection) {
164
            $solr_query = '';
165
            if ($collection['index_query'] != '') {
166
                $solr_query .= '(' . $collection['index_query'] . ')';
167
            } else {
168
                $solr_query .= 'collection:("' . $collection['index_name'] . '")';
169
            }
170
            $partOfNothing = $solr->search_raw($solr_query . ' AND partof:0 AND toplevel:true', $params);
171
            $partOfSomething = $solr->search_raw($solr_query . ' AND NOT partof:0 AND toplevel:true', $params);
172
            // Titles are all documents that are "root" elements i.e. partof == 0
173
            $collection['titles'] = [];
174
            foreach ($partOfNothing as $doc) {
175
                $collection['titles'][$doc->uid] = $doc->uid;
176
            }
177
            // Volumes are documents that are both
178
            // a) "leaf" elements i.e. partof != 0
179
            // b) "root" elements that are not referenced by other documents ("root" elements that have no descendants)
180
            $collection['volumes'] = $collection['titles'];
181
            foreach ($partOfSomething as $doc) {
182
                $collection['volumes'][$doc->uid] = $doc->uid;
183
                // If a document is referenced via partof, it’s not a volume anymore.
184
                unset($collection['volumes'][$doc->partof]);
185
            }
186
187
            // Generate random but unique array key taking priority into account.
188
            do {
189
                $_key = ($collection['priority'] * 1000) + mt_rand(0, 1000);
190
            } while (!empty($processedCollections[$_key]));
191
192
            $collection['countTitles'] = count($collection['titles']);
193
            $collection['countVolumes'] = count($collection['volumes']);
194
195
            $processedCollections[$_key] = $collection;
196
        }
197
198
        // Randomize sorting?
199
        if (!empty($this->settings['randomize'])) {
200
            ksort($processedCollections, SORT_NUMERIC);
201
        }
202
203
        // TODO: Hook for getting custom collection hierarchies/subentries (requested by SBB).
204
        /*    foreach ($this->hookObjects as $hookObj) {
205
                if (method_exists($hookObj, 'showCollectionList_getCustomCollectionList')) {
206
                    $hookObj->showCollectionList_getCustomCollectionList($this, $this->settings['templateFile'], $content, $markerArray);
207
                }
208
            }
209
        */
210
211
        $this->view->assign('collections', $processedCollections);
212
    }
213
214
    /**
215
     * Builds a collection's list
216
     *
217
     * @access protected
218
     *
219
     * @param int $id: The collection's UID
220
     *
221
     * @return void
222
     */
223
    protected function showSingleCollection($id)
224
    {
225
        $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
226
        $queryBuilder = $connectionPool->getQueryBuilderForTable('tx_dlf_collections');
227
228
        $additionalWhere = '';
229
        // Should user-defined collections be shown?
230
        if (empty($this->settings['show_userdefined'])) {
231
            $additionalWhere = $queryBuilder->expr()->eq('tx_dlf_collections.fe_cruser_id', 0);
232
        } elseif ($this->settings['show_userdefined'] > 0) {
233
            $additionalWhere = $queryBuilder->expr()->neq('tx_dlf_collections.fe_cruser_id', 0);
234
        }
235
236
        // Get collection information from DB
237
        $collection = $queryBuilder
238
            ->select(
239
                'tx_dlf_collections.uid AS uid', // required by getRecordOverlay()
240
                'tx_dlf_collections.pid AS pid', // required by getRecordOverlay()
241
                'tx_dlf_collections.sys_language_uid AS sys_language_uid', // required by getRecordOverlay()
242
                'tx_dlf_collections.index_name AS index_name',
243
                'tx_dlf_collections.index_search as index_search',
244
                'tx_dlf_collections.label AS label',
245
                'tx_dlf_collections.description AS description',
246
                'tx_dlf_collections.thumbnail AS thumbnail',
247
                'tx_dlf_collections.fe_cruser_id'
248
            )
249
            ->from('tx_dlf_collections')
250
            ->where(
251
                $queryBuilder->expr()->eq('tx_dlf_collections.pid', intval($this->settings['pages'])),
252
                $queryBuilder->expr()->eq('tx_dlf_collections.uid', intval($id)),
253
                $additionalWhere,
254
                $queryBuilder->expr()->andX(
255
                    $queryBuilder->expr()->orX(
256
                        $queryBuilder->expr()->in('tx_dlf_collections.sys_language_uid', [-1, 0]),
257
                        $queryBuilder->expr()->eq('tx_dlf_collections.sys_language_uid', $GLOBALS['TSFE']->sys_language_uid)
258
                    ),
259
                    $queryBuilder->expr()->eq('tx_dlf_collections.l18n_parent', 0)
260
                ),
261
                Helper::whereExpression('tx_dlf_collections')
262
            )
263
            ->setMaxResults(1)
264
            ->execute();
265
266
        // Get language overlay if on alterative website language.
267
        $pageRepository = GeneralUtility::makeInstance(PageRepository::class);
268
        if ($resArray = $collection->fetch()) {
269
            if ($resArray['sys_language_uid'] != $GLOBALS['TSFE']->sys_language_content) {
270
                $collectionData = $pageRepository->getRecordOverlay('tx_dlf_collections', $resArray, $GLOBALS['TSFE']->sys_language_content, $GLOBALS['TSFE']->sys_language_contentOL);
271
                // keep the index_name of the default language
272
                $collectionData['index_name'] = $resArray['index_name'];
273
            } else {
274
                $collectionData = $resArray;
275
            }
276
        } else {
277
            $this->logger->warning('No collection with UID ' . $id . ' found.');
278
            return;
279
        }
280
        // Fetch corresponding document UIDs from Solr.
281
        if ($collectionData['index_search'] != '') {
282
            $solr_query = '(' . $collectionData['index_search'] . ')';
283
        } else {
284
            $solr_query = 'collection:("' . $collectionData['index_name'] . '") AND toplevel:true';
285
        }
286
        $solr = Solr::getInstance($this->settings['solrcore']);
287
        if (!$solr->ready) {
288
            $this->logger->error('Apache Solr not available');
289
            return;
290
        }
291
        $params['fields'] = 'uid';
292
        $params['sort'] = ['uid' => 'asc'];
293
        $solrResult = $solr->search_raw($solr_query, $params);
294
        // Initialize array
295
        $documentSet = [];
296
        foreach ($solrResult as $doc) {
297
            if ($doc->uid) {
298
                $documentSet[] = $doc->uid;
299
            }
300
        }
301
        $documentSet = array_unique($documentSet);
302
        $queryBuilder = $connectionPool->getQueryBuilderForTable('tx_dlf_documents');
303
        // Fetch document info for UIDs in $documentSet from DB
304
        $documents = $queryBuilder
305
            ->select(
306
                'tx_dlf_documents.uid AS uid',
307
                'tx_dlf_documents.metadata_sorting AS metadata_sorting',
308
                'tx_dlf_documents.volume_sorting AS volume_sorting',
309
                'tx_dlf_documents.partof AS partof'
310
            )
311
            ->from('tx_dlf_documents')
312
            ->where(
313
                $queryBuilder->expr()->eq('tx_dlf_documents.pid', intval($this->settings['pages'])),
314
                $queryBuilder->expr()->in('tx_dlf_documents.uid', $documentSet),
315
                Helper::whereExpression('tx_dlf_documents')
316
            )
317
            ->execute();
318
319
        $toplevel = [];
320
        $subparts = [];
321
        $listMetadata = [];
322
        // Process results.
323
        while ($resArray = $documents->fetch()) {
324
            if (empty($listMetadata)) {
325
                $listMetadata = [
326
                    'label' => htmlspecialchars($collectionData['label']),
327
                    'description' => $collectionData['description'],
328
                    'thumbnail' => htmlspecialchars($collectionData['thumbnail']),
329
                    'options' => [
330
                        'source' => 'collection',
331
                        'select' => $id,
332
                        'userid' => $collectionData['userid'],
333
                        'params' => ['filterquery' => [['query' => 'collection_faceting:("' . $collectionData['index_name'] . '")']]],
334
                        'core' => '',
335
                        'pid' => $this->settings['pages'],
336
                        'order' => 'title',
337
                        'order.asc' => true
338
                    ]
339
                ];
340
            }
341
            // Prepare document's metadata for sorting.
342
            $sorting = unserialize($resArray['metadata_sorting']);
343
            if (!empty($sorting['type']) && MathUtility::canBeInterpretedAsInteger($sorting['type'])) {
344
                $sorting['type'] = Helper::getIndexNameFromUid($sorting['type'], 'tx_dlf_structures', $this->settings['pages']);
345
            }
346
            if (!empty($sorting['owner']) && MathUtility::canBeInterpretedAsInteger($sorting['owner'])) {
347
                $sorting['owner'] = Helper::getIndexNameFromUid($sorting['owner'], 'tx_dlf_libraries', $this->settings['pages']);
348
            }
349
            if (!empty($sorting['collection']) && MathUtility::canBeInterpretedAsInteger($sorting['collection'])) {
350
                $sorting['collection'] = Helper::getIndexNameFromUid($sorting['collection'], 'tx_dlf_collections', $this->settings['pages']);
351
            }
352
            // Split toplevel documents from volumes.
353
            if ($resArray['partof'] == 0) {
354
                $toplevel[$resArray['uid']] = [
355
                    'u' => $resArray['uid'],
356
                    'h' => '',
357
                    's' => $sorting,
358
                    'p' => []
359
                ];
360
            } else {
361
                // 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.
362
                $subparts[$resArray['partof']][$resArray['volume_sorting'] . str_pad($resArray['uid'], 9, '0', STR_PAD_LEFT)] = [
363
                    'u' => $resArray['uid'],
364
                    'h' => '',
365
                    's' => $sorting,
366
                    'p' => []
367
                ];
368
            }
369
        }
370
        // Add volumes to the corresponding toplevel documents.
371
        foreach ($subparts as $partof => $parts) {
372
            ksort($parts);
373
            foreach ($parts as $part) {
374
                if (!empty($toplevel[$partof])) {
375
                    $toplevel[$partof]['p'][] = ['u' => $part['u']];
376
                } else {
377
                    $toplevel[$part['u']] = $part;
378
                }
379
            }
380
        }
381
        // Save list of documents.
382
        $list = GeneralUtility::makeInstance(DocumentList::class);
383
        $list->reset();
384
        $list->add(array_values($toplevel));
385
        $listMetadata['options']['numberOfToplevelHits'] = count($list);
386
        $list->metadata = $listMetadata;
387
        $list->sort('title');
388
        $list->save();
389
        // Clean output buffer.
390
        ob_end_clean();
391
392
        $uri = $this->uriBuilder
393
            ->reset()
394
            ->setTargetPageUid($this->settings['targetPid'])
395
            ->uriFor('main', [], 'ListView', 'dlf', 'ListView');
396
        $this->redirectToURI($uri);
397
    }
398
}
399