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
Push — master ( d27b89...31a6e8 )
by
unknown
04:57 queued 32s
created

AbstractController::setDefaultIntSetting()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
c 0
b 0
f 0
nc 2
nop 2
dl 0
loc 7
rs 10
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\AbstractDocument;
15
use Kitodo\Dlf\Common\Helper;
16
use Kitodo\Dlf\Domain\Model\Document;
17
use Kitodo\Dlf\Domain\Repository\DocumentRepository;
18
use Psr\Log\LoggerAwareInterface;
19
use Psr\Log\LoggerAwareTrait;
20
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
21
use TYPO3\CMS\Core\Localization\LanguageService;
22
use TYPO3\CMS\Core\Pagination\PaginationInterface;
23
use TYPO3\CMS\Core\Utility\GeneralUtility;
24
use TYPO3\CMS\Core\Utility\MathUtility;
25
use TYPO3\CMS\Core\Pagination\PaginatorInterface;
26
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
27
28
/**
29
 * Abstract controller class for most of the plugin controller.
30
 *
31
 * @package TYPO3
32
 * @subpackage dlf
33
 *
34
 * @access public
35
 *
36
 * @abstract
37
 */
38
abstract class AbstractController extends ActionController implements LoggerAwareInterface
39
{
40
    use LoggerAwareTrait;
41
42
    /**
43
     * @access protected
44
     * @var DocumentRepository
45
     */
46
    protected DocumentRepository $documentRepository;
47
48
    /**
49
     * @access public
50
     *
51
     * @param DocumentRepository $documentRepository
52
     *
53
     * @return void
54
     */
55
    public function injectDocumentRepository(DocumentRepository $documentRepository): void
56
    {
57
        $this->documentRepository = $documentRepository;
58
    }
59
60
    /**
61
     * @access protected
62
     * @var Document|null This holds the current document
63
     */
64
    protected ?Document $document = null;
65
66
    /**
67
     * @access protected
68
     * @var array
69
     */
70
    protected $documentArray;
71
72
    /**
73
     * @access protected
74
     * @var array
75
     */
76
    protected array $extConf;
77
78
    /**
79
     * @access protected
80
     * @var array This holds the request parameter
81
     */
82
    protected array $requestData;
83
84
    /**
85
     * @access protected
86
     * @var array This holds some common data for the fluid view
87
     */
88
    protected array $viewData;
89
90
    /**
91
     * @access protected
92
     * @var int
93
     */
94
    protected int $pageUid;
95
96
    /**
97
     * Initialize the plugin controller
98
     *
99
     * @access protected
100
     *
101
     * @return void
102
     */
103
    protected function initialize(): void
104
    {
105
        $this->requestData = GeneralUtility::_GPmerged('tx_dlf');
106
        $this->pageUid = (int) GeneralUtility::_GET('id');
107
108
        // Sanitize user input to prevent XSS attacks.
109
        $this->sanitizeRequestData();
110
111
        // Get extension configuration.
112
        $this->extConf = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('dlf');
113
114
        $this->viewData = [
115
            'pageUid' => $this->pageUid,
116
            'uniqueId' => uniqid(),
117
            'requestData' => $this->requestData
118
        ];
119
    }
120
121
    /**
122
     * Loads the current document into $this->document
123
     *
124
     * @access protected
125
     *
126
     * @param int $documentId The document's UID (fallback: $this->requestData[id])
127
     *
128
     * @return void
129
     */
130
    protected function loadDocument(int $documentId = 0): void
131
    {
132
        // Get document ID from request data if not passed as parameter.
133
        if ($documentId === 0 && !empty($this->requestData['id'])) {
134
            $documentId = $this->requestData['id'];
135
        }
136
137
        // Try to get document format from database
138
        if (!empty($documentId)) {
139
140
            $doc = null;
141
142
            if (MathUtility::canBeInterpretedAsInteger($documentId)) {
143
                $doc = $this->getDocumentByUid($documentId);
144
            } elseif (GeneralUtility::isValidUrl($documentId)) {
145
                $doc = $this->getDocumentByUrl($documentId);
146
            }
147
148
            if ($this->document !== null && $doc !== null) {
149
                $this->document->setCurrentDocument($doc);
150
            }
151
152
        } elseif (!empty($this->requestData['recordId'])) {
153
154
            $this->document = $this->documentRepository->findOneByRecordId($this->requestData['recordId']);
0 ignored issues
show
Bug introduced by
The method findOneByRecordId() does not exist on Kitodo\Dlf\Domain\Repository\DocumentRepository. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

154
            /** @scrutinizer ignore-call */ 
155
            $this->document = $this->documentRepository->findOneByRecordId($this->requestData['recordId']);
Loading history...
155
156
            if ($this->document !== null) {
157
                $doc = AbstractDocument::getInstance($this->document->getLocation(), $this->settings, true);
158
                if ($doc !== null) {
159
                    $this->document->setCurrentDocument($doc);
160
                } else {
161
                    $this->logger->error('Failed to load document with record ID "' . $this->requestData['recordId'] . '"');
162
                }
163
            }
164
        } else {
165
            $this->logger->error('Invalid ID "' . $documentId . '" or PID "' . $this->settings['storagePid'] . '" for document loading');
166
        }
167
    }
168
169
    /**
170
     * Configure URL for proxy.
171
     *
172
     * @access protected
173
     *
174
     * @param string $url URL for proxy configuration
175
     *
176
     * @return void
177
     */
178
    protected function configureProxyUrl(string &$url): void
179
    {
180
        $this->uriBuilder->reset()
181
            ->setTargetPageUid($this->pageUid)
182
            ->setCreateAbsoluteUri(!empty($this->extConf['general']['forceAbsoluteUrl']))
183
            ->setArguments(
184
                [
185
                    'eID' => 'tx_dlf_pageview_proxy',
186
                    'url' => $url,
187
                    'uHash' => GeneralUtility::hmac($url, 'PageViewProxy')
188
                ]
189
            )
190
            ->build();
191
    }
192
193
    /**
194
     * Checks if doc is missing or is empty (no pages)
195
     *
196
     * @access protected
197
     *
198
     * @return bool
199
     */
200
    protected function isDocMissingOrEmpty(): bool
201
    {
202
        $multiViewType = $this->settings['multiViewType'] ?? '';
203
        return $this->isDocMissing() || ($this->document->getCurrentDocument()->numPages < 1 && $this->document->getCurrentDocument()->tableOfContents[0]['type'] !== $multiViewType);
204
    }
205
206
    /**
207
     * Checks if doc is missing
208
     *
209
     * @access protected
210
     *
211
     * @return bool
212
     */
213
    protected function isDocMissing(): bool
214
    {
215
        return $this->document === null || $this->document->getCurrentDocument() === null;
216
    }
217
218
    /**
219
     * Returns the LanguageService
220
     *
221
     * @access protected
222
     *
223
     * @return LanguageService
224
     */
225
    protected function getLanguageService(): LanguageService
226
    {
227
        return $GLOBALS['LANG'];
228
    }
229
230
    /**
231
     * Safely gets Parameters from request if they exist
232
     *
233
     * @access protected
234
     *
235
     * @param string $parameterName
236
     *
237
     * @return null|string|array
238
     */
239
    protected function getParametersSafely(string $parameterName)
240
    {
241
        if ($this->request->hasArgument($parameterName)) {
242
            return $this->request->getArgument($parameterName);
243
        }
244
        return null;
245
    }
246
247
    /**
248
     * Sanitize input variables.
249
     *
250
     * @access protected
251
     *
252
     * @return void
253
     */
254
    protected function sanitizeRequestData(): void
255
    {
256
        // tx_dlf[id] may only be an UID or URI.
257
        if (
258
            !empty($this->requestData['id'])
259
            && !MathUtility::canBeInterpretedAsInteger($this->requestData['id'])
260
            && !GeneralUtility::isValidUrl($this->requestData['id'])
261
        ) {
262
            $this->logger->warning('Invalid ID or URI "' . $this->requestData['id'] . '" for document loading');
263
            unset($this->requestData['id']);
264
        }
265
266
        // tx_dlf[page] may only be a positive integer or valid XML ID.
267
        if (
268
            !empty($this->requestData['page'])
269
            && !MathUtility::canBeInterpretedAsInteger($this->requestData['page'])
270
            && !Helper::isValidXmlId($this->requestData['page'])
271
        ) {
272
            $this->requestData['page'] = 1;
273
        }
274
275
        // tx_dlf[double] may only be 0 or 1.
276
        $this->requestData['double'] = MathUtility::forceIntegerInRange($this->requestData['double'] ?? 0, 0, 1);
277
    }
278
279
    /**
280
     * Sanitize settings from FlexForm.
281
     *
282
     * @access protected
283
     *
284
     * @return void
285
     */
286
    protected function sanitizeSettings(): void
287
    {
288
        $this->setDefaultIntSetting('storagePid', 0);
289
290
        if ($this instanceof MetadataController) {
291
            $this->setDefaultIntSetting('rootline', 0);
292
            $this->setDefaultIntSetting('originalIiifMetadata', 0);
293
            $this->setDefaultIntSetting('displayIiifDescription', 1);
294
            $this->setDefaultIntSetting('displayIiifRights', 1);
295
            $this->setDefaultIntSetting('displayIiifLinks', 1);
296
        }
297
298
        if ($this instanceof OaiPmhController) {
299
            $this->setDefaultIntSetting('limit', 5);
300
            $this->setDefaultIntSetting('solr_limit', 50000);
301
        }
302
303
        if ($this instanceof PageViewController) {
304
            $this->setDefaultIntSetting('useInternalProxy', 0);
305
        }
306
    }
307
308
    /**
309
     * Sets default value for setting if not yet set.
310
     *
311
     * @access protected
312
     *
313
     * @param string $setting name of setting
314
     * @param int $value for being set if empty
315
     *
316
     * @return void
317
     */
318
    protected function setDefaultIntSetting(string $setting, int $value): void
319
    {
320
        if (empty($this->settings[$setting])) {
321
            $this->settings[$setting] = $value;
322
            $this->logger->warning('Setting "' . $setting . '" not set, using default value "' . $value . '". Probably FlexForm for controller "' . get_class($this) . '" is not read.');
323
        } else {
324
            $this->settings[$setting] = (int) $this->settings[$setting];
325
        }
326
    }
327
328
    /**
329
     * Sets page value.
330
     *
331
     * @access protected
332
     *
333
     * @return void
334
     */
335
    protected function setPage(): void
336
    {
337
        if (!empty($this->requestData['logicalPage'])) {
338
            $this->requestData['page'] = $this->document->getCurrentDocument()->getPhysicalPage($this->requestData['logicalPage']);
0 ignored issues
show
Bug introduced by
The method getCurrentDocument() 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

338
            $this->requestData['page'] = $this->document->/** @scrutinizer ignore-call */ getCurrentDocument()->getPhysicalPage($this->requestData['logicalPage']);

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...
339
            // The logical page parameter should not appear again
340
            unset($this->requestData['logicalPage']);
341
        }
342
343
        $this->setDefaultPage();
344
    }
345
346
    /**
347
     * Sets default page value.
348
     *
349
     * @access protected
350
     *
351
     * @return void
352
     */
353
    protected function setDefaultPage(): void
354
    {
355
        // Set default values if not set.
356
        // $this->requestData['page'] may be integer or string (physical structure @ID)
357
        if (
358
            (int) $this->requestData['page'] > 0
359
            || empty($this->requestData['page'])
360
            || is_array($this->requestData['docPage'])
361
        ) {
362
            if (isset($this->settings['multiViewType']) && $this->document->getCurrentDocument()->tableOfContents[0]['type'] === $this->settings['multiViewType']) {
363
                $i = 0;
364
                foreach ($this->documentArray as $document) {
365
                    if ($document !== null) {
366
                        $this->requestData['docPage'][$i] = MathUtility::forceIntegerInRange((int) $this->requestData['docPage'][$i], 1, $document->numPages, 1);
367
                        $i++;
368
                    }
369
                }
370
            } else {
371
                $this->requestData['page'] = MathUtility::forceIntegerInRange((int) $this->requestData['page'], 1, $this->document->getCurrentDocument()->numPages, 1);
372
            }
373
        }
374
        // reassign viewData to get correct page
375
        $this->viewData['requestData'] = $this->requestData;
376
    }
377
378
    /**
379
     * This is the constructor
380
     *
381
     * @access public
382
     *
383
     * @return void
384
     */
385
    public function __construct()
386
    {
387
        $this->initialize();
388
    }
389
390
    /**
391
     * build simple pagination
392
     *
393
     * @param PaginationInterface $pagination
394
     * @param PaginatorInterface $paginator
395
     * @return array
396
     */
397
    //TODO: clean this function
398
    protected function buildSimplePagination(PaginationInterface $pagination, PaginatorInterface $paginator): array
399
    {
400
        $firstPage = $pagination->getFirstPageNumber();
401
        $lastPage = $pagination->getLastPageNumber();
402
        $currentPageNumber = $paginator->getCurrentPageNumber();
403
404
        $pages = [];
405
        $pagesSect = [];
406
        $aRange = [];
407
        $nRange = 5;    // ToDo: should be made configurable
408
409
        // lower limit of the range
410
        $nBottom = $currentPageNumber - $nRange;
411
        // upper limit of the range
412
        $nTop = $currentPageNumber + $nRange;
413
        // page range
414
        for ($i = $nBottom; $i <= $nTop; $i++) {
415
            if ($i > 0 and $i <= $lastPage) {
416
                array_push($aRange, $i);
417
            };
418
        };
419
420
        // check whether the first screen page is > 1, if yes then points must be added
421
        if ($aRange[0] > 1) {
422
            array_push($pagesSect, ['label' => '...','startRecordNumber' => '...']);
423
        };
424
        $lastStartRecordNumberGrid = 0; // due to validity outside the loop
425
        foreach (range($firstPage, $lastPage) as $i) {
426
            // detect which pagination is active: ListView or GridView
427
            if (get_class($pagination) == 'TYPO3\CMS\Core\Pagination\SimplePagination') {  // ListView
428
                $lastStartRecordNumberGrid = $i; // save last $startRecordNumber for LastPage button
429
430
                $pages[$i] = [
431
                    'label' => $i,
432
                    'startRecordNumber' => $i
433
                ];
434
435
                // Check if screen page is in range
436
                // <f:for each="{pagination.pagesR}" as="page">
437
                if (in_array($i, $aRange)) {
438
                    array_push($pagesSect, ['label' => $i, 'startRecordNumber' => $i]);
439
                };
440
            } else { // GridView
441
                // to calculate the values for generation the links for the pagination pages
442
                /** @var \Kitodo\Dlf\Pagination\PageGridPaginator $paginator */
443
                $itemsPerPage = $paginator->getPublicItemsPerPage();
444
445
                $startRecordNumber = $itemsPerPage * $i;
446
                $startRecordNumber = $startRecordNumber + 1;
447
                $startRecordNumber = $startRecordNumber - $itemsPerPage;
448
449
                $lastStartRecordNumberGrid = $startRecordNumber; // save last $startRecordNumber for LastPage button
450
451
                // array with label as screen/pagination page number
452
                // and startRecordNumer for correct structure of the link
453
                //<f:link.action action="{action}"
454
                //      addQueryString="true"
455
                //      argumentsToBeExcludedFromQueryString="{0: 'tx_dlf[page]'}"
456
                //      additionalParams="{'tx_dlf[page]': page.startRecordNumber}"
457
                //      arguments="{searchParameter: lastSearch}">{page.label}</f:link.action>
458
                $pages[$i] = [
459
                    'label' => $i,
460
                    'startRecordNumber' => $startRecordNumber
461
                ];
462
463
                // Check if screen page is in range
464
                if (in_array($i, $aRange)) {
465
                    array_push($pagesSect, ['label' => $i,'startRecordNumber' => $startRecordNumber]);
466
                };
467
            };
468
        };
469
470
        // check whether the last element from $aRange <= last screen page, if yes then points must be added
471
        if ($aRange[array_key_last($aRange)] < $lastPage) {
472
            array_push($pagesSect, ['label' => '...', 'startRecordNumber' => '...']);
473
        };
474
475
        // Safely get the next and previous page numbers
476
        $nextPageNumber = isset($pages[$currentPageNumber + 1]) ? $pages[$currentPageNumber + 1]['startRecordNumber'] : null;
477
        $previousPageNumber = isset($pages[$currentPageNumber - 1]) ? $pages[$currentPageNumber - 1]['startRecordNumber'] : null;
478
479
        // 'startRecordNumber' is not required in GridView, only the variant for each loop is required
480
        // 'endRecordNumber' is not required in both views
481
        //
482
        // lastPageNumber       =>  last screen page
483
        // lastPageNumber       =>  Document page to build the last screen page. This is the first document
484
        //                          of the last block of 10 (or less) documents on the last screen page
485
        // firstPageNumber      =>  always 1
486
        // nextPageNumber       =>  Document page to build the next screen page
487
        // nextPageNumberG      =>  Number of the screen page for the next screen page
488
        // previousPageNumber   =>  Document page to build up the previous screen page
489
        // previousPageNumberG  =>  Number of the screen page for the previous screen page
490
        // currentPageNumber    =>  Number of the current screen page
491
        // pagesG               =>  Array with two keys
492
        //    label             =>  Number of the screen page
493
        //    startRecordNumber =>  First document of this block of 10 documents on the same screen page
494
        return [
495
            'lastPageNumber' => $lastPage,
496
            'lastPageNumberG' => $lastStartRecordNumberGrid,
497
            'firstPageNumber' => $firstPage,
498
            'nextPageNumber' => $nextPageNumber,
499
            'nextPageNumberG' => $currentPageNumber + 1,
500
            'previousPageNumber' => $previousPageNumber,
501
            'previousPageNumberG' => $currentPageNumber - 1,
502
            'startRecordNumber' => $pagination->getStartRecordNumber(),
503
            'endRecordNumber' => $pagination->getEndRecordNumber(),
504
            'currentPageNumber' => $currentPageNumber,
505
            'pages' => range($firstPage, $lastPage),
506
            'pagesG' => $pages,
507
            'pagesR' => $pagesSect
508
        ];
509
    }
510
511
    /**
512
     * Get document from repository by uid.
513
     *
514
     * @access private
515
     *
516
     * @param int $documentId The document's UID
517
     *
518
     * @return AbstractDocument
519
     */
520
    private function getDocumentByUid(int $documentId)
521
    {
522
        $doc = null;
523
        $this->document = $this->documentRepository->findOneByIdAndSettings($documentId);
524
525
        if ($this->document) {
526
            $doc = AbstractDocument::getInstance($this->document->getLocation(), $this->settings, true);
527
        } else {
528
            $this->logger->error('Invalid UID "' . $documentId . '" or PID "' . $this->settings['storagePid'] . '" for document loading');
529
        }
530
531
        return $doc;
532
    }
533
534
    /**
535
     * Get document by URL.
536
     *
537
     * @access protected
538
     *
539
     * @param string $documentId The document's URL
540
     *
541
     * @return AbstractDocument
542
     */
543
    protected function getDocumentByUrl(string $documentId)
544
    {
545
        $doc = AbstractDocument::getInstance($documentId, $this->settings, true);
546
547
        if (isset($this->settings['multiViewType']) && $doc->tableOfContents[0]['type'] === $this->settings['multiViewType']) {
548
            $childDocuments = $doc->tableOfContents[0]['children'];
549
            $i = 0;
550
            foreach ($childDocuments as $document) {
551
                $this->documentArray[] = AbstractDocument::getInstance($document['points'], $this->settings, true);
552
                if (!isset($this->requestData['docPage'][$i]) && isset(explode('#', $document['points'])[1])) {
553
                    $initPage = explode('#', $document['points'])[1];
554
                    $this->requestData['docPage'][$i] = $initPage;
555
                }
556
                $i++;
557
            }
558
        } else {
559
            $this->documentArray[] = $doc;
560
        }
561
        if ($this->requestData['multipleSource'] && is_array($this->requestData['multipleSource'])) {
562
            $i = 0;
563
            foreach ($this->requestData['multipleSource'] as $location) {
564
                $document = AbstractDocument::getInstance($location, $this->settings, true);
565
                if ($document !== null) {
566
                    $this->documentArray['extra_' . $i] = $document;
567
                }
568
                $i++;
569
            }
570
        }
571
572
        if ($doc !== null) {
573
            $this->document = GeneralUtility::makeInstance(Document::class);
574
575
            if ($doc->recordId) {
576
                // find document from repository by recordId
577
                $docFromRepository = $this->documentRepository->findOneByRecordId($doc->recordId);
578
                if ($docFromRepository !== null) {
579
                    $this->document = $docFromRepository;
580
                }
581
            }
582
583
            // Make sure configuration PID is set when applicable
584
            if ($doc->cPid == 0) {
585
                $doc->cPid = max($this->settings['storagePid'], 0);
586
            }
587
588
            $this->document->setLocation($documentId);
589
        } else {
590
            $this->logger->error('Invalid location given "' . $documentId . '" for document loading');
591
        }
592
593
        return $doc;
594
    }
595
}
596