Scrutinizer GitHub App not installed

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

Install GitHub App

GitHub Access Token became invalid

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

Issues (188)

Classes/Controller/CalendarController.php (4 issues)

1
<?php
2
3
/**
4
 * (c) Kitodo. Key to digital objects e.V. <[email protected]>
5
 *
6
 * This file is part of the Kitodo and TYPO3 projects.
7
 *
8
 * @license GNU General Public License version 3 or later.
9
 * For the full copyright and license information, please read the
10
 * LICENSE.txt file that was distributed with this source code.
11
 */
12
13
namespace Kitodo\Dlf\Controller;
14
15
use Generator;
16
use Kitodo\Dlf\Domain\Model\Document;
17
use Kitodo\Dlf\Domain\Repository\StructureRepository;
18
use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
19
20
/**
21
 * Controller class for the plugin 'Calendar'.
22
 *
23
 * @package TYPO3
24
 * @subpackage dlf
25
 *
26
 * @access public
27
 */
28
class CalendarController extends AbstractController
29
{
30
    /**
31
     * @access protected
32
     * @var StructureRepository
33
     */
34
    protected StructureRepository $structureRepository;
35
36
    /**
37
     * @access public
38
     *
39
     * @param StructureRepository $structureRepository
40
     *
41
     * @return void
42
     */
43
    public function injectStructureRepository(StructureRepository $structureRepository): void
44
    {
45
        $this->structureRepository = $structureRepository;
46
    }
47
48
    /**
49
     * @access protected
50
     * @var array This holds all issues for the list view.
51
     */
52
    protected array $allIssues = [];
53
54
    /**
55
     * The main method of the plugin
56
     *
57
     * @access public
58
     *
59
     * @return void
60
     */
61
    public function mainAction(): void
62
    {
63
        // Set initial document (anchor or year file) if configured.
64
        if (empty($this->requestData['id']) && !empty($this->settings['initialDocument'])) {
65
            $this->requestData['id'] = $this->settings['initialDocument'];
66
        }
67
68
        // Load current document.
69
        $this->loadDocument();
70
        if ($this->isDocMissing()) {
71
            // Quit without doing anything if required variables are not set.
72
            return;
73
        }
74
75
        $metadata = $this->document->getCurrentDocument()->getToplevelMetadata();
76
        if (!empty($metadata['type'][0])) {
77
            $type = $metadata['type'][0];
78
        } else {
79
            return;
80
        }
81
82
        switch ($type) {
83
            case 'newspaper':
84
            case 'ephemera':
85
                $this->forward('years', null, null, $this->requestData);
0 ignored issues
show
Deprecated Code introduced by
The function TYPO3\CMS\Extbase\Mvc\Co...onController::forward() has been deprecated: since TYPO3 11.0, will be removed in 12.0 ( Ignorable by Annotation )

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

85
                /** @scrutinizer ignore-deprecated */ $this->forward('years', null, null, $this->requestData);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
Coding Style Comprehensibility introduced by
Consider adding a comment if this fall-through is intended.
Loading history...
86
            case 'year':
87
                $this->forward('calendar', null, null, $this->requestData);
0 ignored issues
show
Deprecated Code introduced by
The function TYPO3\CMS\Extbase\Mvc\Co...onController::forward() has been deprecated: since TYPO3 11.0, will be removed in 12.0 ( Ignorable by Annotation )

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

87
                /** @scrutinizer ignore-deprecated */ $this->forward('calendar', null, null, $this->requestData);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
88
            case 'issue':
89
            default:
90
                break;
91
        }
92
93
    }
94
95
    /**
96
     * The Calendar Method
97
     *
98
     * @access public
99
     *
100
     * @return void
101
     */
102
    public function calendarAction(): void
103
    {
104
        // access arguments passed by the mainAction()
105
        $mainRequestData = $this->request->getArguments();
106
107
        // merge both arguments together --> passing id by GET parameter tx_dlf[id] should win
108
        $this->requestData = array_merge($this->requestData, $mainRequestData);
109
110
        // Load current document.
111
        $this->loadDocument();
112
        if ($this->isDocMissing()) {
113
            // Quit without doing anything if required variables are not set.
114
            return;
115
        }
116
117
        $calendarData = $this->buildCalendar();
118
119
        // Prepare list as alternative view.
120
        $issueData = [];
121
        foreach ($this->allIssues as $dayTimestamp => $issues) {
122
            $issueData[$dayTimestamp]['dateString'] = strftime('%A, %x', $dayTimestamp);
123
            $issueData[$dayTimestamp]['items'] = [];
124
            foreach ($issues as $issue) {
125
                $issueData[$dayTimestamp]['items'][] = $issue;
126
            }
127
        }
128
        $this->view->assign('issueData', $issueData);
129
130
        // Link to current year.
131
        $linkTitleData = $this->document->getCurrentDocument()->getToplevelMetadata();
132
        $yearLinkTitle = !empty($linkTitleData['mets_orderlabel'][0]) ? $linkTitleData['mets_orderlabel'][0] : $linkTitleData['mets_label'][0];
133
134
        $this->view->assign('calendarData', $calendarData);
135
        $this->view->assign('documentId', $this->document->getUid());
136
        $this->view->assign('yearLinkTitle', $yearLinkTitle);
137
        $this->view->assign('parentDocumentId', $this->document->getPartof() ?: $this->document->getCurrentDocument()->tableOfContents[0]['points']);
138
        $this->view->assign('allYearDocTitle', $this->document->getCurrentDocument()->getTitle($this->document->getPartof()) ?: $this->document->getCurrentDocument()->tableOfContents[0]['label']);
139
    }
140
141
    /**
142
     * The Years Method
143
     *
144
     * @access public
145
     *
146
     * @return void
147
     */
148
    public function yearsAction(): void
149
    {
150
        // access arguments passed by the mainAction()
151
        $mainRequestData = $this->request->getArguments();
152
153
        // merge both arguments together --> passing id by GET parameter tx_dlf[id] should win
154
        $this->requestData = array_merge($this->requestData, $mainRequestData);
155
156
        // Load current document.
157
        $this->loadDocument();
158
        if ($this->isDocMissing()) {
159
            // Quit without doing anything if required variables are not set.
160
            return;
161
        }
162
163
        // Get all children of anchor. This should be the year anchor documents
164
        $documents = $this->documentRepository->getChildrenOfYearAnchor($this->document->getUid(), $this->structureRepository->findOneByIndexName('year'));
0 ignored issues
show
The method findOneByIndexName() does not exist on Kitodo\Dlf\Domain\Repository\StructureRepository. 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

164
        $documents = $this->documentRepository->getChildrenOfYearAnchor($this->document->getUid(), $this->structureRepository->/** @scrutinizer ignore-call */ findOneByIndexName('year'));
Loading history...
165
166
        $years = [];
167
        // Process results.
168
        if (count($documents) === 0) {
169
            foreach ($this->document->getCurrentDocument()->tableOfContents[0]['children'] as $id => $year) {
170
                $yearLabel = empty($year['label']) ? $year['orderlabel'] : $year['label'];
171
172
                if (empty($yearLabel)) {
173
                    // if neither order nor orderlabel is set, use the id...
174
                    $yearLabel = (string) $id;
175
                }
176
177
                $years[] = [
178
                    'title' => $yearLabel,
179
                    'uid' => $year['points'],
180
                ];
181
            }
182
        } else {
183
            /** @var Document $document */
184
            foreach ($documents as $document) {
185
                $years[] = [
186
                    'title' => !empty($document->getMetsLabel()) ? $document->getMetsLabel() : (!empty($document->getMetsOrderlabel()) ? $document->getMetsOrderlabel() : $document->getTitle()),
187
                    'uid' => $document->getUid()
188
                ];
189
            }
190
        }
191
192
        $yearArray = [];
193
        if (count($years) > 0) {
194
            foreach ($years as $year) {
195
                $yearArray[] = [
196
                    'documentId' => $year['uid'],
197
                    'title' => $year['title']
198
                ];
199
            }
200
            // create an array that includes years without issues
201
            if (!empty($this->settings['showEmptyYears'])) {
202
                $yearFilled = [];
203
                $min = $yearArray[0]['title'];
204
                // round the starting decade down to zero for equal rows
205
                $min = (int) substr_replace($min, "0", -1);
206
                $max = (int) $yearArray[count($yearArray) - 1]['title'];
207
                // if we have an actual documentId it should be used, otherwise leave empty
208
                for ($i = 0; $i < $max - $min + 1; $i++) {
209
                    $key = array_search($min + $i, array_column($yearArray, 'title'));
210
                    if (is_int($key)) {
211
                        $yearFilled[] = $yearArray[$key];
212
                    } else {
213
                        $yearFilled[] = ['title' => $min + $i, 'documentId' => ''];
214
                    }
215
                }
216
                $yearArray = $yearFilled;
217
            }
218
219
            $this->view->assign('yearName', $yearArray);
220
        }
221
222
        $this->view->assign('documentId', $this->document->getUid());
223
        $this->view->assign('allYearDocTitle', $this->document->getCurrentDocument()->getTitle((int) $this->document->getUid()) ?: $this->document->getCurrentDocument()->tableOfContents[0]['label']);
224
    }
225
226
    /**
227
     * Build calendar for a certain year
228
     *
229
     * @access protected
230
     *
231
     * @param array $calendarData Output array containing the result calendar data that is passed to Fluid template
232
     * @param array $calendarIssuesByMonth All issues sorted by month => day
233
     * @param int $year Gregorian year
234
     * @param int $firstMonth 1 for January, 2 for February, ... 12 for December
235
     * @param int $lastMonth 1 for January, 2 for February, ... 12 for December
236
     *
237
     * @return void
238
     */
239
    protected function getCalendarYear(array &$calendarData, array $calendarIssuesByMonth, int $year, int $firstMonth = 1, int $lastMonth = 12): void
240
    {
241
        for ($i = $firstMonth; $i <= $lastMonth; $i++) {
242
            $key = $year . '-' . $i;
243
244
            $calendarData[$key] = [
245
                'DAYMON_NAME' => strftime('%a', strtotime('last Monday')),
246
                'DAYTUE_NAME' => strftime('%a', strtotime('last Tuesday')),
247
                'DAYWED_NAME' => strftime('%a', strtotime('last Wednesday')),
248
                'DAYTHU_NAME' => strftime('%a', strtotime('last Thursday')),
249
                'DAYFRI_NAME' => strftime('%a', strtotime('last Friday')),
250
                'DAYSAT_NAME' => strftime('%a', strtotime('last Saturday')),
251
                'DAYSUN_NAME' => strftime('%a', strtotime('last Sunday')),
252
                'MONTHNAME'  => strftime('%B', strtotime($year . '-' . $i . '-1')) . ' ' . $year,
253
                'CALYEAR' => ($i == $firstMonth) ? $year : ''
254
            ];
255
256
            $firstOfMonth = strtotime($year . '-' . $i . '-1');
257
            $lastOfMonth = strtotime('last day of', ($firstOfMonth));
258
            $firstOfMonthStart = strtotime('last Monday', $firstOfMonth);
259
            // There are never more than 6 weeks in a month.
260
            for ($j = 0; $j <= 5; $j++) {
261
                $firstDayOfWeek = strtotime('+ ' . $j . ' Week', $firstOfMonthStart);
262
263
                $calendarData[$key]['week'][$j] = [
264
                    'DAYMON' => ['dayValue' => '&nbsp;'],
265
                    'DAYTUE' => ['dayValue' => '&nbsp;'],
266
                    'DAYWED' => ['dayValue' => '&nbsp;'],
267
                    'DAYTHU' => ['dayValue' => '&nbsp;'],
268
                    'DAYFRI' => ['dayValue' => '&nbsp;'],
269
                    'DAYSAT' => ['dayValue' => '&nbsp;'],
270
                    'DAYSUN' => ['dayValue' => '&nbsp;'],
271
                ];
272
                // Every week has seven days. ;-)
273
                for ($k = 0; $k <= 6; $k++) {
274
                    $currentDayTime = strtotime('+ ' . $k . ' Day', $firstDayOfWeek);
275
                    if (
276
                        $currentDayTime >= $firstOfMonth
277
                        && $currentDayTime <= $lastOfMonth
278
                    ) {
279
                        $dayLinks = '';
280
                        $dayLinksText = [];
281
                        $dayLinkDiv = [];
282
                        $currentMonth = date('n', $currentDayTime);
283
                        if (is_array($calendarIssuesByMonth[$currentMonth])) {
284
                            foreach ($calendarIssuesByMonth[$currentMonth] as $id => $day) {
285
                                if ($id == date('j', $currentDayTime)) {
286
                                    $dayLinks = $id;
287
                                    $dayLinksText = array_merge($dayLinksText, $this->getDayLinksText($day, $currentDayTime));
288
                                }
289
                            }
290
                            $dayLinkDiv = $dayLinksText;
291
                        }
292
                        $this->fillCalendar($calendarData[$key]['week'][$j], $currentDayTime, $dayLinks, $dayLinkDiv, $firstDayOfWeek, $k);
293
                    }
294
                }
295
            }
296
        }
297
    }
298
299
    /**
300
     * Get text links for given day.
301
     *
302
     * @access private
303
     *
304
     * @param array $day all issues for given day
305
     * @param int $currentDayTime
306
     *
307
     * @return array all issues for given day as text links
308
     */
309
    private function getDayLinksText(array $day, int $currentDayTime): array
310
    {
311
        $dayLinksText = [];
312
        foreach ($day as $issue) {
313
            $dayLinkLabel = empty($issue['title']) ? strftime('%x', $currentDayTime) : $issue['title'];
314
315
            $dayLinksText[] = [
316
                'documentId' => $issue['uid'],
317
                'text' => $dayLinkLabel
318
            ];
319
320
            // Save issue for list view.
321
            $this->allIssues[$currentDayTime][] = [
322
                'documentId' => $issue['uid'],
323
                'text' => $dayLinkLabel
324
            ];
325
        }
326
        return $dayLinksText;
327
    }
328
329
    /**
330
     * Fill calendar.
331
     *
332
     * @access private
333
     *
334
     * @param array &$calendarData calendar passed by reference
335
     * @param int $currentDayTime
336
     * @param string $dayLinks
337
     * @param array $dayLinkDiv
338
     * @param int $firstDayOfWeek
339
     * @param int $k
340
     *
341
     * @return void
342
     */
343
    private function fillCalendar(array &$calendarData, int $currentDayTime, string $dayLinks, array $dayLinkDiv, int $firstDayOfWeek, int $k): void
344
    {
345
        switch (strftime('%w', strtotime('+ ' . $k . ' Day', $firstDayOfWeek))) {
346
            case '0':
347
                $this->fillDay($calendarData, $currentDayTime, 'DAYSUN', $dayLinks, $dayLinkDiv);
348
                break;
349
            case '1':
350
                $this->fillDay($calendarData, $currentDayTime, 'DAYMON', $dayLinks, $dayLinkDiv);
351
                break;
352
            case '2':
353
                $this->fillDay($calendarData, $currentDayTime, 'DAYTUE', $dayLinks, $dayLinkDiv);
354
                break;
355
            case '3':
356
                $this->fillDay($calendarData, $currentDayTime, 'DAYWED', $dayLinks, $dayLinkDiv);
357
                break;
358
            case '4':
359
                $this->fillDay($calendarData, $currentDayTime, 'DAYTHU', $dayLinks, $dayLinkDiv);
360
                break;
361
            case '5':
362
                $this->fillDay($calendarData, $currentDayTime, 'DAYFRI', $dayLinks, $dayLinkDiv);
363
                break;
364
            case '6':
365
                $this->fillDay($calendarData, $currentDayTime, 'DAYSAT', $dayLinks, $dayLinkDiv);
366
                break;
367
        }
368
    }
369
370
    /**
371
     * Fill day.
372
     *
373
     * @access private
374
     *
375
     * @param array &$calendarData calendar passed by reference
376
     * @param int $currentDayTime
377
     * @param string $day
378
     * @param string $dayLinks
379
     * @param array $dayLinkDiv
380
     *
381
     * @return void
382
     */
383
    private function fillDay(array &$calendarData, int $currentDayTime, string $day, string $dayLinks, array $dayLinkDiv): void
384
    {
385
        $calendarData[$day]['dayValue'] = strftime('%d', $currentDayTime);
386
        if ((int) $dayLinks === (int) date('j', $currentDayTime)) {
387
            $calendarData[$day]['issues'] = $dayLinkDiv;
388
        }
389
    }
390
391
    /**
392
     * Build calendar for year (default) or season.
393
     *
394
     * @access private
395
     *
396
     * @return array
397
     */
398
    private function buildCalendar(): array
399
    {
400
        $issuesByYear = $this->getIssuesByYear();
401
402
        $calendarData = [];
403
        $iteration = 1;
404
        foreach ($issuesByYear as $year => $issuesByMonth) {
405
            // Sort by months.
406
            ksort($issuesByMonth);
407
            // Default: First month is January, last month is December.
408
            $firstMonth = 1;
409
            $lastMonth = 12;
410
            // Show calendar from first issue up to end of season if applicable.
411
            if (
412
                empty($this->settings['showEmptyMonths'])
413
                && count($issuesByYear) > 1
414
            ) {
415
                if ($iteration == 1) {
416
                    $firstMonth = (int) key($issuesByMonth);
417
                } elseif ($iteration == count($issuesByYear)) {
418
                    end($issuesByMonth);
419
                    $lastMonth = (int) key($issuesByMonth);
420
                }
421
            }
422
            $this->getCalendarYear($calendarData, $issuesByMonth, $year, $firstMonth, $lastMonth);
423
            $iteration++;
424
        }
425
426
        return $calendarData;
427
    }
428
429
    /**
430
     * Get issues by year
431
     *
432
     * @access private
433
     *
434
     * @return array
435
     */
436
    private function getIssuesByYear(): array
437
    {
438
        //  We need an array of issues with year => month => day number as key.
439
        $issuesByYear = [];
440
441
        foreach ($this->getIssues() as $issue) {
442
            $dateTimestamp = strtotime($issue['year']);
443
            if ($dateTimestamp !== false) {
444
                $_year = date('Y', $dateTimestamp);
445
                $_month = date('n', $dateTimestamp);
446
                $_day = date('j', $dateTimestamp);
447
                $issuesByYear[$_year][$_month][$_day][] = $issue;
448
            } else {
449
                $this->logger->warning('Document with UID ' . $issue['uid'] . 'has no valid date of publication');
450
            }
451
        }
452
        // Sort by years.
453
        ksort($issuesByYear);
454
455
        return $issuesByYear;
456
    }
457
458
    /**
459
     * Gets issues from table of contents or documents.
460
     *
461
     * @access private
462
     *
463
     * @return Generator
464
     */
465
    private function getIssues(): Generator
466
    {
467
        $documents = $this->documentRepository->getChildrenOfYearAnchor($this->document->getUid(), $this->structureRepository->findOneByIndexName('issue'));
468
469
        // Process results.
470
        if ($documents->count() === 0) {
471
            return $this->getIssuesFromTableOfContents();
472
        }
473
474
        return $this->getIssuesFromDocuments($documents);
475
    }
476
477
    /**
478
     * Gets issues from table of contents.
479
     *
480
     * @access private
481
     *
482
     * @return Generator
483
     */
484
    private function getIssuesFromTableOfContents(): Generator
485
    {
486
        $toc = $this->document->getCurrentDocument()->tableOfContents;
487
488
        foreach ($toc[0]['children'] as $year) {
489
            foreach ($year['children'] as $month) {
490
                foreach ($month['children'] as $day) {
491
                    foreach ($day['children'] as $issue) {
492
                        $title = $issue['label'] ?: $issue['orderlabel'];
493
                        if (strtotime($title) !== false) {
494
                            $title = strftime('%x', strtotime($title));
495
                        }
496
497
                        yield [
498
                            'uid' => $issue['points'],
499
                            'title' => $title,
500
                            'year' => $day['orderlabel'],
501
                        ];
502
                    }
503
                }
504
            }
505
        }
506
    }
507
508
    /**
509
     * Gets issues from documents.
510
     *
511
     * @access private
512
     *
513
     * @param array|QueryResultInterface $documents to create issues
514
     *
515
     * @return Generator
516
     */
517
    private function getIssuesFromDocuments($documents): Generator
518
    {
519
        /** @var Document $document */
520
        foreach ($documents as $document) {
521
            // Set title for display in calendar view.
522
            if (!empty($document->getTitle())) {
523
                $title = $document->getTitle();
524
            } else {
525
                $title = !empty($document->getMetsLabel()) ? $document->getMetsLabel() : $document->getMetsOrderlabel();
526
                if (strtotime($title) !== false) {
527
                    $title = strftime('%x', strtotime($title));
528
                }
529
            }
530
            yield [
531
                'uid' => $document->getUid(),
532
                'title' => $title,
533
                'year' => $document->getYear()
534
            ];
535
        }
536
    }
537
}
538