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 (#836)
by Beatrycze
03:35
created

TableOfContentsController   F

Complexity

Total Complexity 83

Size/Duplication

Total Lines 415
Duplicated Lines 0 %

Importance

Changes 9
Bugs 0 Features 0
Metric Value
eloc 195
c 9
b 0
f 0
dl 0
loc 415
rs 2
wmc 83

11 Methods

Rating   Name   Duplication   Size   Complexity  
C makeMenuArray() 0 65 14
B mainAction() 0 29 6
A makeMenuFor3DObjects() 0 22 5
D getMenuEntry() 0 81 19
B getMenuEntryWithImage() 0 53 11
A getType() 0 6 2
A isTitleFound() 0 4 1
A isAuthorFound() 0 4 1
A getTypes() 0 15 5
D isFound() 0 18 18
A isTypeFound() 0 2 1

How to fix   Complexity   

Complex Class

Complex classes like TableOfContentsController 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 TableOfContentsController, 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\Helper;
15
use TYPO3\CMS\Core\Utility\MathUtility;
16
use TYPO3\CMS\Core\Utility\GeneralUtility;
17
18
/**
19
 * Controller class for plugin 'Table Of Contents'.
20
 *
21
 * @author Sebastian Meyer <[email protected]>
22
 * @package TYPO3
23
 * @subpackage dlf
24
 * @access public
25
 */
26
class TableOfContentsController extends AbstractController
27
{
28
    /**
29
     * This holds the active entries according to the currently selected page
30
     *
31
     * @var array
32
     * @access protected
33
     */
34
    protected $activeEntries = [];
35
36
    /**
37
     * The main method of the plugin
38
     *
39
     * @return void
40
     */
41
    public function mainAction()
42
    {
43
        // Load current document.
44
        $this->loadDocument($this->requestData);
45
        if (
46
            $this->document === null
47
            || $this->document->getDoc() === null
48
        ) {
49
            // Quit without doing anything if required variables are not set.
50
            return;
51
        } else {
52
            if (!empty($this->requestData['logicalPage'])) {
53
                $this->requestData['page'] = $this->document->getDoc()->getPhysicalPage($this->requestData['logicalPage']);
54
                // The logical page parameter should not appear again
55
                unset($this->requestData['logicalPage']);
56
            }
57
            if ($this->document->getDoc()->tableOfContents[0]['type'] == 'collection') {
58
                $this->view->assign('currentList', $this->requestData['id']);
59
                if (isset($this->requestData['transform'])) {
60
                    $this->view->assign('transform', $this->requestData['transform']);
61
                } else {
62
                    $this->view->assign('transform', 'something');
63
                }
64
                $this->view->assign('type', 'collection');
65
                $this->view->assign('types', $this->getTypes($this->document->getDoc()->tableOfContents));
66
                $this->view->assign('toc', $this->makeMenuFor3DObjects());
67
            } else {
68
                $this->view->assign('type', 'other');
69
                $this->view->assign('toc', $this->makeMenuArray());
70
            }
71
        }
72
    }
73
74
    /**
75
     * This builds a menu array for HMENU
76
     *
77
     * @access protected
78
     * @return array HMENU array
79
     */
80
    protected function makeMenuArray()
81
    {
82
        // Set default values for page if not set.
83
        // $this->requestData['page'] may be integer or string (physical structure @ID)
84
        if (
85
            (int) $this->requestData['page'] > 0
86
            || empty($this->requestData['page'])
87
        ) {
88
            $this->requestData['page'] = MathUtility::forceIntegerInRange((int) $this->requestData['page'], 1, $this->document->getDoc()->numPages, 1);
89
        } else {
90
            $this->requestData['page'] = array_search($this->requestData['page'], $this->document->getDoc()->physicalStructure);
91
        }
92
        $this->requestData['double'] = MathUtility::forceIntegerInRange($this->requestData['double'], 0, 1, 0);
93
        $menuArray = [];
94
        // Does the document have physical elements or is it an external file?
95
        if (
96
            !empty($this->document->getDoc()->physicalStructure)
97
            || !MathUtility::canBeInterpretedAsInteger($this->requestData['id'])
98
        ) {
99
            // Get all logical units the current page or track is a part of.
100
            if (
101
                !empty($this->requestData['page'])
102
                && !empty($this->document->getDoc()->physicalStructure)
103
            ) {
104
                $this->activeEntries = array_merge((array) $this->document->getDoc()->smLinks['p2l'][$this->document->getDoc()->physicalStructure[0]],
105
                    (array) $this->document->getDoc()->smLinks['p2l'][$this->document->getDoc()->physicalStructure[$this->requestData['page']]]);
106
                if (
107
                    !empty($this->requestData['double'])
108
                    && $this->requestData['page'] < $this->document->getDoc()->numPages
109
                ) {
110
                    $this->activeEntries = array_merge($this->activeEntries,
111
                        (array) $this->document->getDoc()->smLinks['p2l'][$this->document->getDoc()->physicalStructure[$this->requestData['page'] + 1]]);
112
                }
113
            }
114
            // Go through table of contents and create all menu entries.
115
            foreach ($this->document->getDoc()->tableOfContents as $entry) {
116
                $menuArray[] = $this->getMenuEntry($entry, true);
117
            }
118
        } else {
119
            // Go through table of contents and create top-level menu entries.
120
            foreach ($this->document->getDoc()->tableOfContents as $entry) {
121
                $menuArray[] = $this->getMenuEntry($entry, false);
122
            }
123
            // Build table of contents from database.
124
            $result = $this->documentRepository->getTableOfContentsFromDb($this->document->getUid(), $this->document->getPid(), $this->settings);
125
126
            $allResults = $result->fetchAll();
0 ignored issues
show
Bug introduced by
The method fetchAll() does not exist on TYPO3\CMS\Extbase\Persistence\QueryResultInterface. ( Ignorable by Annotation )

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

126
            /** @scrutinizer ignore-call */ 
127
            $allResults = $result->fetchAll();

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...
127
128
            if (count($allResults) > 0) {
129
                $menuArray[0]['ITEM_STATE'] = 'CURIFSUB';
130
                $menuArray[0]['_SUB_MENU'] = [];
131
                foreach ($allResults as $resArray) {
132
                    $entry = [
133
                        'label' => !empty($resArray['mets_label']) ? $resArray['mets_label'] : $resArray['title'],
134
                        'type' => $resArray['type'],
135
                        'volume' => $resArray['volume'],
136
                        'orderlabel' => $resArray['mets_orderlabel'],
137
                        'pagination' => '',
138
                        'targetUid' => $resArray['uid']
139
                    ];
140
                    $menuArray[0]['_SUB_MENU'][] = $this->getMenuEntry($entry, false);
141
                }
142
            }
143
        }
144
        return $menuArray;
145
    }
146
147
    /**
148
     * This builds a menu for list of 3D objects
149
     *
150
     * @access protected
151
     *
152
     * @param string $content: The PlugIn content
153
     * @param array $conf: The PlugIn configuration
154
     *
155
     * @return array HMENU array
156
     */
157
    protected function makeMenuFor3DObjects()
158
    {
159
        // Set default values for page if not set.
160
        // $this->requestData['page'] may be integer or string (physical structure @ID)
161
        if (
162
            (int) $this->requestData['page'] > 0
163
            || empty($this->requestData['page'])
164
        ) {
165
            $this->requestData['page'] = MathUtility::forceIntegerInRange((int) $this->requestData['page'], 1, $this->document->getDoc()->numPages, 1);
166
        } else {
167
            $this->requestData['page'] = array_search($this->requestData['page'], $this->document->getDoc()->physicalStructure);
168
        }
169
        $this->requestData['double'] = MathUtility::forceIntegerInRange($this->requestData['double'], 0, 1, 0);
170
        $menuArray = [];
171
        // Is the document an external file?
172
        if (!MathUtility::canBeInterpretedAsInteger($this->requestData['id'])) {
173
            // Go through table of contents and create all menu entries.
174
            foreach ($this->document->getDoc()->tableOfContents as $entry) {
175
                $menuArray[] = $this->getMenuEntryWithImage($entry, true);
176
            }
177
        }
178
        return $menuArray;
179
    }
180
181
    /**
182
     * This builds an array for one menu entry
183
     *
184
     * @access protected
185
     *
186
     * @param array $entry : The entry's array from \Kitodo\Dlf\Common\Doc->getLogicalStructure
187
     * @param bool $recursive : Whether to include the child entries
188
     *
189
     * @return array HMENU array for menu entry
190
     */
191
    protected function getMenuEntry(array $entry, $recursive = false)
192
    {
193
        $entryArray = [];
194
        // Set "title", "volume", "type" and "pagination" from $entry array.
195
        $entryArray['title'] = !empty($entry['label']) ? $entry['label'] : $entry['orderlabel'];
196
        $entryArray['volume'] = $entry['volume'];
197
        $entryArray['orderlabel'] = $entry['orderlabel'];
198
        $entryArray['type'] = Helper::translate($entry['type'], 'tx_dlf_structures', $this->settings['storagePid']);
199
        $entryArray['pagination'] = htmlspecialchars($entry['pagination']);
200
        $entryArray['_OVERRIDE_HREF'] = '';
201
        $entryArray['doNotLinkIt'] = 1;
202
        $entryArray['ITEM_STATE'] = 'NO';
203
        // Build menu links based on the $entry['points'] array.
204
        if (
205
            !empty($entry['points'])
206
            && MathUtility::canBeInterpretedAsInteger($entry['points'])
207
        ) {
208
            $entryArray['page'] = $entry['points'];
209
210
            $entryArray['doNotLinkIt'] = 0;
211
            if ($this->settings['basketButton']) {
212
                $entryArray['basketButton'] = [
213
                    'logId' => $entry['id'],
214
                    'startpage' => $entry['points']
215
                ];
216
            }
217
        } elseif (
218
            !empty($entry['points'])
219
            && is_string($entry['points'])
220
        ) {
221
            $entryArray['id'] = $entry['points'];
222
            $entryArray['page'] = 1;
223
            $entryArray['doNotLinkIt'] = 0;
224
            if ($this->settings['basketButton']) {
225
                $entryArray['basketButton'] = [
226
                    'logId' => $entry['id'],
227
                    'startpage' => $entry['points']
228
                ];
229
            }
230
        } elseif (!empty($entry['targetUid'])) {
231
            $entryArray['id'] = $entry['targetUid'];
232
            $entryArray['page'] = 1;
233
            $entryArray['doNotLinkIt'] = 0;
234
            if ($this->settings['basketButton']) {
235
                $entryArray['basketButton'] = [
236
                    'logId' => $entry['id'],
237
                    'startpage' => $entry['targetUid']
238
                ];
239
            }
240
        }
241
        // Set "ITEM_STATE" to "CUR" if this entry points to current page.
242
        if (in_array($entry['id'], $this->activeEntries)) {
243
            $entryArray['ITEM_STATE'] = 'CUR';
244
        }
245
        // Build sub-menu if available and called recursively.
246
        if (
247
            $recursive === true
248
            && !empty($entry['children'])
249
        ) {
250
            // Build sub-menu only if one of the following conditions apply:
251
            // 1. Current menu node is in rootline
252
            // 2. Current menu node points to another file
253
            // 3. Current menu node has no corresponding images
254
            if (
255
                $entryArray['ITEM_STATE'] == 'CUR'
256
                || is_string($entry['points'])
257
                || empty($this->document->getDoc()->smLinks['l2p'][$entry['id']])
258
            ) {
259
                $entryArray['_SUB_MENU'] = [];
260
                foreach ($entry['children'] as $child) {
261
                    // Set "ITEM_STATE" to "ACT" if this entry points to current page and has sub-entries pointing to the same page.
262
                    if (in_array($child['id'], $this->activeEntries)) {
263
                        $entryArray['ITEM_STATE'] = 'ACT';
264
                    }
265
                    $entryArray['_SUB_MENU'][] = $this->getMenuEntry($child, true);
266
                }
267
            }
268
            // Append "IFSUB" to "ITEM_STATE" if this entry has sub-entries.
269
            $entryArray['ITEM_STATE'] = ($entryArray['ITEM_STATE'] == 'NO' ? 'IFSUB' : $entryArray['ITEM_STATE'] . 'IFSUB');
270
        }
271
        return $entryArray;
272
    }
273
274
    /**
275
     * This builds an array for one 3D menu entry
276
     *
277
     * @access protected
278
     *
279
     * @param array $entry : The entry's array from \Kitodo\Dlf\Common\Doc->getLogicalStructure
280
     * @param bool $recursive : Whether to include the child entries
281
     *
282
     * @return array HMENU array for 3D menu entry
283
     */
284
    protected function getMenuEntryWithImage(array $entry, $recursive = false)
285
    {
286
        $entryArray = [];
287
288
        // don't filter if the entry type is collection
289
        if ($entry['type'] != 'collection') {
290
            if (!$this->isFound($entry)) {
291
                return $entryArray;
292
            }
293
        }
294
295
        // Set "title", "volume", "type" and "pagination" from $entry array.
296
        $entryArray['title'] = !empty($entry['label']) ? $entry['label'] : $entry['orderlabel'];
297
        $entryArray['orderlabel'] = $entry['orderlabel'];
298
        $entryArray['type'] = Helper::translate($entry['type'], 'tx_dlf_structures', $this->settings['storagePid']);
299
        $entryArray['pagination'] = htmlspecialchars($entry['pagination']);
300
        $entryArray['doNotLinkIt'] = 1;
301
        $entryArray['ITEM_STATE'] = 'HEADER';
302
303
        if ($entry['children'] == NULL) {
304
            $entryArray['description'] = $entry['description'];
305
            $entryArray['identifier'] = $entry['identifier'];
306
            $id = str_replace("LOG", "PHYS", $entry['id']);
307
            $entryArray['image'] = $this->document->getDoc()->getFileLocation($this->document->getDoc()->physicalStructureInfo[$id]['files']['THUMBS']);
308
            $entryArray['doNotLinkIt'] = 0;
309
            // index.php?tx_dlf%5Bid%5D=http%3A%2F%2Flink_to_METS_file.xml
310
            $entryArray['urlId'] = GeneralUtility::_GET('id');
311
            $entryArray['urlXml'] = $entry['points'];
312
            $entryArray['ITEM_STATE'] = 'ITEM';
313
        }
314
315
        // Build sub-menu if available and called recursively.
316
        if (
317
            $recursive == true
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...
318
            && !empty($entry['children'])
319
        ) {
320
            // Build sub-menu only if one of the following conditions apply:
321
            // 1. Current menu node points to another file
322
            // 2. Current menu node has no corresponding images
323
            if (
324
                is_string($entry['points'])
325
                || empty($this->document->getDoc()->smLinks['l2p'][$entry['id']])
326
            ) {
327
                $entryArray['_SUB_MENU'] = [];
328
                foreach ($entry['children'] as $child) {
329
                    $menuEntry = $this->getMenuEntryWithImage($child);
330
                    if (!empty($menuEntry)) {
331
                        $entryArray['_SUB_MENU'][] = $menuEntry;
332
                    }
333
                }
334
            }
335
        }
336
        return $entryArray;
337
    }
338
339
    /**
340
     * Check or possible combinations of requested params.
341
     *
342
     * @param array $entry : The entry's array from \Kitodo\Dlf\Common\Doc->getLogicalStructure
343
     *
344
     * @return bool true if found, false otherwise
345
     */
346
    private function isFound($entry) {
347
        if (!empty($this->requestData['title'] && !empty($this->requestData['types']) && !empty($this->requestData['author']))) {
348
            return $this->isTitleFound($entry) && $this->isTypeFound($entry) && $this->isAuthorFound($entry);
349
        } else if (!empty($this->requestData['title']) && !empty($this->requestData['author'])) {
350
            return $this->isTitleFound($entry) && $this->isAuthorFound($entry);
351
        } else if (!empty($this->requestData['title']) && !empty($this->requestData['types'])) {
352
            return $this->isTitleFound($entry) && $this->isTypeFound($entry);
353
        } else if (!empty($this->requestData['author']) && !empty($this->requestData['types'])) {
354
            return $this->isAuthorFound($entry) && $this->isTypeFound($entry);
355
        } else if (!empty($this->requestData['title'])) {
356
            return $this->isTitleFound($entry);
357
        } else if (!empty($this->requestData['types'])) {
358
            return $this->isTypeFound($entry);
359
        } else if (!empty($this->requestData['author'])) {
360
            return $this->isAuthorFound($entry);
361
        } else {
362
            // no parameters so entry is matching
363
            return true;
364
        }
365
    }
366
367
    /**
368
     * Check if author is found.
369
     *
370
     * @param array $entry : The entry's array from \Kitodo\Dlf\Common\Doc->getLogicalStructure
371
     *
372
     * @return bool true if found, false otherwise
373
     */
374
    private function isAuthorFound($entry) {
375
        $value = strtolower($entry['author']);
376
        $author = strtolower($this->requestData['author']);
377
        return str_contains($value, $author);
378
    }
379
380
    /**
381
     * Check if title is found.
382
     *
383
     * @param array $entry : The entry's array from \Kitodo\Dlf\Common\Doc->getLogicalStructure
384
     *
385
     * @return bool true if found, false otherwise
386
     */
387
    private function isTitleFound($entry) {
388
        $value = strtolower($entry['label']);
389
        $title = strtolower($this->requestData['title']);
390
        return str_contains($value, $title);
391
    }
392
393
    /**
394
     * Check if type is found.
395
     *
396
     * @param array $entry : The entry's array from \Kitodo\Dlf\Common\Doc->getLogicalStructure
397
     *
398
     * @return bool true if found, false otherwise
399
     */
400
    private function isTypeFound($entry) {
401
        return str_contains($entry['identifier'], $this->requestData['types']);
402
    }
403
404
    /**
405
     * Get all types.
406
     *
407
     * @param array $entry : The entry's array from \Kitodo\Dlf\Common\Doc->getLogicalStructure
408
     *
409
     * @return array of object types
410
     */
411
    private function getTypes($entry) {
412
        $types = [];
413
        $index = 0;
414
415
        if (!empty($entry[0]['children'])) {
416
            foreach ($entry[0]['children'] as $child) {
417
                $type = $this->getType($child);
418
                if (!(in_array($type, $types)) && $type != NULL) {
419
                    $types[$index] = $type;
420
                    $index++;
421
                }
422
            }
423
        }
424
425
        return $types;
426
    }
427
428
    /**
429
     * Get single type for given entry.
430
     *
431
     * @param array $entry : The entry's array from \Kitodo\Dlf\Common\Doc->getLogicalStructure
432
     *
433
     * @return string type name without number
434
     */
435
    private function getType($entry) {
436
        $type = $entry['identifier'];
437
        if (!empty($type)) {
438
            return strtok($type, ',');
439
        }
440
        return $type;
441
    }
442
}
443