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 (#506)
by Sebastian
02:52
created

Calendar   F

Complexity

Total Complexity 77

Size/Duplication

Total Lines 419
Duplicated Lines 0 %

Importance

Changes 6
Bugs 0 Features 0
Metric Value
wmc 77
eloc 255
c 6
b 0
f 0
dl 0
loc 419
rs 2.24

4 Methods

Rating   Name   Duplication   Size   Complexity  
B main() 0 36 9
F calendar() 0 136 24
D getCalendarYear() 0 109 31
C years() 0 78 13

How to fix   Complexity   

Complex Class

Complex classes like Calendar 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 Calendar, and based on these observations, apply Extract Interface, too.

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\Plugin;
14
15
use Kitodo\Dlf\Common\Helper;
16
use TYPO3\CMS\Core\Database\ConnectionPool;
17
use TYPO3\CMS\Core\Utility\GeneralUtility;
18
19
/**
20
 * Plugin 'Calendar' for the 'dlf' extension
21
 *
22
 * @author Alexander Bigga <[email protected]>
23
 * @author Sebastian Meyer <[email protected]>
24
 * @package TYPO3
25
 * @subpackage dlf
26
 * @access public
27
 */
28
class Calendar extends \Kitodo\Dlf\Common\AbstractPlugin
29
{
30
    public $scriptRelPath = 'Classes/Plugin/Calendar.php';
31
32
    /**
33
     * This holds all issues for the list view.
34
     *
35
     * @var array
36
     * @access protected
37
     */
38
    protected $allIssues = [];
39
40
    /**
41
     * The main method of the PlugIn
42
     *
43
     * @access public
44
     *
45
     * @param string $content: The PlugIn content
46
     * @param array $conf: The PlugIn configuration
47
     *
48
     * @return string The content that is displayed on the website
49
     */
50
    public function main($content, $conf)
51
    {
52
        $this->init($conf);
53
54
        // Set initial document (anchor or year file) if configured.
55
        if (empty($this->piVars['id']) && !empty($this->conf['initialDocument'])) {
56
            $this->piVars['id'] = $this->conf['initialDocument'];
0 ignored issues
show
Bug Best Practice introduced by
The property piVars does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
57
        }
58
59
        // Load current document.
60
        $this->loadDocument();
61
        if ($this->doc === null) {
62
            // Quit without doing anything if required variables are not set.
63
            return $content;
64
        }
65
66
        $metadata = $this->doc->getTitledata();
67
        if (!empty($metadata['type'][0])) {
68
            $type = $metadata['type'][0];
69
        } else {
70
            return $content;
71
        }
72
73
        switch ($type) {
74
            case 'newspaper':
75
            case 'ephemera':
76
                return $this->years($content, $conf);
77
            case 'year':
78
                return $this->calendar($content, $conf);
79
            case 'issue':
80
            default:
81
                break;
82
        }
83
84
        // Nothing to do here.
85
        return $content;
86
    }
87
88
    /**
89
     * The Calendar Method
90
     *
91
     * @access public
92
     *
93
     * @param string $content: The PlugIn content
94
     * @param array $conf: The PlugIn configuration
95
     *
96
     * @return string The content that is displayed on the website
97
     */
98
    public function calendar($content, $conf)
99
    {
100
        $this->init($conf);
101
        // Load current document.
102
        $this->loadDocument();
103
        if ($this->doc === null) {
104
            // Quit without doing anything if required variables are not set.
105
            return $content;
106
        }
107
        // Load template file.
108
        $this->getTemplate('###TEMPLATECALENDAR###');
109
110
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
111
            ->getQueryBuilderForTable('tx_dlf_documents');
112
113
        // Get all children of year anchor.
114
        $result = $queryBuilder
115
            ->select(
116
                'tx_dlf_documents.uid AS uid',
117
                'tx_dlf_documents.title AS title',
118
                'tx_dlf_documents.year AS year',
119
                'tx_dlf_documents.mets_label AS label',
120
                'tx_dlf_documents.mets_orderlabel AS orderlabel'
121
            )
122
            ->from('tx_dlf_documents')
123
            ->where(
124
                $queryBuilder->expr()->eq('tx_dlf_documents.structure', Helper::getUidFromIndexName('issue', 'tx_dlf_structures', $this->doc->cPid)),
0 ignored issues
show
introduced by
The property cPid is declared write-only in Kitodo\Dlf\Common\Document.
Loading history...
125
                $queryBuilder->expr()->eq('tx_dlf_documents.partof', intval($this->doc->uid)),
126
                Helper::whereExpression('tx_dlf_documents')
127
            )
128
            ->orderBy('tx_dlf_documents.mets_orderlabel')
129
            ->execute();
130
131
        $issues = [];
132
133
        // Process results.
134
        while ($resArray = $result->fetch()) {
135
            // Set title for display in calendar view.
136
            if (!empty($resArray['title'])) {
137
                $title = $resArray['title'];
138
            } else {
139
                $title = !empty($resArray['label']) ? $resArray['label'] : $resArray['orderlabel'];
140
                if (strtotime($title) !== false) {
141
                    $title = strftime('%x', strtotime($title));
142
                }
143
            }
144
            $issues[] = [
145
                'uid' => $resArray['uid'],
146
                'title' => $title,
147
                'year' => $resArray['year']
148
            ];
149
        }
150
        //  We need an array of issues with year => month => day number as key.
151
        $calendarIssuesByYear = [];
152
        foreach ($issues as $issue) {
153
            $dateTimestamp = strtotime($issue['year']);
154
            if ($dateTimestamp !== false) {
155
                $_year = date('Y', $dateTimestamp);
156
                $_month = date('n', $dateTimestamp);
157
                $_day = date('j', $dateTimestamp);
158
                $calendarIssuesByYear[$_year][$_month][$_day][] = $issue;
159
            } else {
160
                Helper::devLog('Document with UID ' . $issue['uid'] . 'has no valid date of publication', DEVLOG_SEVERITY_WARNING);
161
            }
162
        }
163
        // Sort by years.
164
        ksort($calendarIssuesByYear);
165
        // Build calendar for year (default) or season.
166
        $subPartContent = '';
167
        $iteration = 1;
168
        foreach ($calendarIssuesByYear as $year => $calendarIssuesByMonth) {
169
            // Sort by months.
170
            ksort($calendarIssuesByMonth);
171
            // Default: First month is January, last month is December.
172
            $firstMonth = 1;
173
            $lastMonth = 12;
174
            // Show calendar from first issue up to end of season if applicable.
175
            if (
176
                empty($this->conf['showEmptyMonths'])
177
                && count($calendarIssuesByYear) > 1
178
            ) {
179
                if ($iteration == 1) {
180
                    $firstMonth = (int) key($calendarIssuesByMonth);
181
                } elseif ($iteration == count($calendarIssuesByYear)) {
182
                    end($calendarIssuesByMonth);
183
                    $lastMonth = (int) key($calendarIssuesByMonth);
184
                }
185
            }
186
            $subPartContent .= $this->getCalendarYear($calendarIssuesByMonth, $year, $firstMonth, $lastMonth);
187
            $iteration++;
188
        }
189
        // Prepare list as alternative view.
190
        $subPartContentList = '';
191
        // Get subpart templates.
192
        $subParts['list'] = $this->templateService->getSubpart($this->template, '###ISSUELIST###');
193
        $subParts['singleday'] = $this->templateService->getSubpart($subParts['list'], '###SINGLEDAY###');
194
        foreach ($this->allIssues as $dayTimestamp => $issues) {
195
            $markerArrayDay['###DATE_STRING###'] = strftime('%A, %x', $dayTimestamp);
196
            $markerArrayDay['###ITEMS###'] = '';
197
            foreach ($issues as $issue) {
198
                $markerArrayDay['###ITEMS###'] .= $issue;
199
            }
200
            $subPartContentList .= $this->templateService->substituteMarkerArray($subParts['singleday'], $markerArrayDay);
201
        }
202
        $this->template = $this->templateService->substituteSubpart($this->template, '###SINGLEDAY###', $subPartContentList);
203
        // Link to current year.
204
        $linkConf = [
205
            'useCacheHash' => 1,
206
            'parameter' => $GLOBALS['TSFE']->id,
207
            'forceAbsoluteUrl' => !empty($this->conf['forceAbsoluteUrl']) ? 1 : 0,
208
            'forceAbsoluteUrl.' => ['scheme' => !empty($this->conf['forceAbsoluteUrl']) && !empty($this->conf['forceAbsoluteUrlHttps']) ? 'https' : 'http'],
209
            'additionalParams' => '&' . $this->prefixId . '[id]=' . urlencode($this->doc->uid),
210
        ];
211
        $linkTitleData = $this->doc->getTitledata();
212
        $linkTitle = !empty($linkTitleData['mets_orderlabel'][0]) ? $linkTitleData['mets_orderlabel'][0] : $linkTitleData['mets_label'][0];
213
        $yearLink = $this->cObj->typoLink($linkTitle, $linkConf);
214
        // Link to years overview.
215
        $linkConf = [
216
            'useCacheHash' => 1,
217
            'parameter' => $GLOBALS['TSFE']->id,
218
            'forceAbsoluteUrl' => !empty($this->conf['forceAbsoluteUrl']) ? 1 : 0,
219
            'forceAbsoluteUrl.' => ['scheme' => !empty($this->conf['forceAbsoluteUrl']) && !empty($this->conf['forceAbsoluteUrlHttps']) ? 'https' : 'http'],
220
            'additionalParams' => '&' . $this->prefixId . '[id]=' . urlencode($this->doc->parentId),
221
        ];
222
        $allYearsLink = $this->cObj->typoLink($this->pi_getLL('allYears', '', true) . ' ' . $this->doc->getTitle($this->doc->parentId), $linkConf);
223
        // Fill marker array.
224
        $markerArray = [
225
            '###CALENDARVIEWACTIVE###' => count($this->allIssues) > 5 ? 'active' : '',
226
            '###LISTVIEWACTIVE###' => count($this->allIssues) < 6 ? 'active' : '',
227
            '###CALYEAR###' => $yearLink,
228
            '###CALALLYEARS###' => $allYearsLink,
229
            '###LABEL_CALENDAR###' => $this->pi_getLL('label.view_calendar'),
230
            '###LABEL_LIST_VIEW###' => $this->pi_getLL('label.view_list'),
231
        ];
232
        $this->template = $this->templateService->substituteMarkerArray($this->template, $markerArray);
233
        return $this->templateService->substituteSubpart($this->template, '###CALMONTH###', $subPartContent);
234
    }
235
236
    /**
237
     * Build calendar for a certain year
238
     *
239
     * @access protected
240
     *
241
     * @param array $calendarIssuesByMonth All issues sorted by month => day
242
     * @param int $year Gregorian year
243
     * @param int $firstMonth 1 for January, 2 for February, ... 12 for December
244
     * @param int $lastMonth 1 for January, 2 for February, ... 12 for December
245
     *
246
     * @return string Content for template subpart
247
     */
248
    protected function getCalendarYear($calendarIssuesByMonth, $year, $firstMonth = 1, $lastMonth = 12)
249
    {
250
        // Get subpart templates.
251
        $subPartContent = '';
252
        $subParts['month'] = $this->templateService->getSubpart($this->template, '###CALMONTH###');
253
        $subParts['week'] = $this->templateService->getSubpart($subParts['month'], '###CALWEEK###');
254
        for ($i = $firstMonth; $i <= $lastMonth; $i++) {
255
            $markerArray = [
256
                '###DAYMON_NAME###' => strftime('%a', strtotime('last Monday')),
257
                '###DAYTUE_NAME###' => strftime('%a', strtotime('last Tuesday')),
258
                '###DAYWED_NAME###' => strftime('%a', strtotime('last Wednesday')),
259
                '###DAYTHU_NAME###' => strftime('%a', strtotime('last Thursday')),
260
                '###DAYFRI_NAME###' => strftime('%a', strtotime('last Friday')),
261
                '###DAYSAT_NAME###' => strftime('%a', strtotime('last Saturday')),
262
                '###DAYSUN_NAME###' => strftime('%a', strtotime('last Sunday')),
263
                '###MONTHNAME###'  => strftime('%B', strtotime($year . '-' . $i . '-1')) . ' ' . $year,
264
                '###CALYEAR###' => ($i == $firstMonth) ? '<div class="year">' . $year . '</div>' : ''
265
            ];
266
            // Fill the month markers.
267
            $subPartContentMonth = $this->templateService->substituteMarkerArray($subParts['month'], $markerArray);
268
            // Reset week content of new month.
269
            $subPartContentWeek = '';
270
            $firstOfMonth = strtotime($year . '-' . $i . '-1');
271
            $lastOfMonth = strtotime('last day of', ($firstOfMonth));
272
            $firstOfMonthStart = strtotime('last Monday', $firstOfMonth);
273
            // There are never more than 6 weeks in a month.
274
            for ($j = 0; $j <= 5; $j++) {
275
                $firstDayOfWeek = strtotime('+ ' . $j . ' Week', $firstOfMonthStart);
276
                $weekArray = [
277
                    '###DAYMON###' => '&nbsp;',
278
                    '###DAYTUE###' => '&nbsp;',
279
                    '###DAYWED###' => '&nbsp;',
280
                    '###DAYTHU###' => '&nbsp;',
281
                    '###DAYFRI###' => '&nbsp;',
282
                    '###DAYSAT###' => '&nbsp;',
283
                    '###DAYSUN###' => '&nbsp;',
284
                ];
285
                // Every week has seven days. ;-)
286
                for ($k = 0; $k <= 6; $k++) {
287
                    $currentDayTime = strtotime('+ ' . $k . ' Day', $firstDayOfWeek);
288
                    if (
289
                        $currentDayTime >= $firstOfMonth
290
                        && $currentDayTime <= $lastOfMonth
291
                    ) {
292
                        $dayLinks = '';
293
                        $dayLinksText = [];
294
                        $dayLinksList = '';
295
                        $currentMonth = date('n', $currentDayTime);
296
                        if (is_array($calendarIssuesByMonth[$currentMonth])) {
297
                            foreach ($calendarIssuesByMonth[$currentMonth] as $id => $day) {
298
                                if ($id == date('j', $currentDayTime)) {
299
                                    $dayLinks = $id;
300
                                    foreach ($day as $issue) {
301
                                        $dayLinkLabel = empty($issue['title']) ? strftime('%x', $currentDayTime) : $issue['title'];
302
                                        $linkConf = [
303
                                            'useCacheHash' => 1,
304
                                            'parameter' => $this->conf['targetPid'],
305
                                            'forceAbsoluteUrl' => !empty($this->conf['forceAbsoluteUrl']) ? 1 : 0,
306
                                            'forceAbsoluteUrl.' => ['scheme' => !empty($this->conf['forceAbsoluteUrl']) && !empty($this->conf['forceAbsoluteUrlHttps']) ? 'https' : 'http'],
307
                                            'additionalParams' => '&' . $this->prefixId . '[id]=' . urlencode($issue['uid']),
308
                                            'ATagParams' => ' class="title"',
309
                                        ];
310
                                        $dayLinksText[] = $this->cObj->typoLink($dayLinkLabel, $linkConf);
311
                                        // Save issue for list view.
312
                                        $this->allIssues[$currentDayTime][] = $this->cObj->typoLink($dayLinkLabel, $linkConf);
313
                                    }
314
                                }
315
                            }
316
                            if (!empty($dayLinksText)) {
317
                                $dayLinksList = '<ul>';
318
                                foreach ($dayLinksText as $link) {
319
                                    $dayLinksList .= '<li>' . $link . '</li>';
320
                                }
321
                                $dayLinksList .= '</ul>';
322
                            }
323
                            $dayLinkDiv = '<div class="issues"><h4>' . strftime('%d', $currentDayTime) . '</h4><div>' . $dayLinksList . '</div></div>';
324
                        }
325
                        switch (strftime('%w', strtotime('+ ' . $k . ' Day', $firstDayOfWeek))) {
326
                            case '0':
327
                                $weekArray['###DAYSUN###'] = ((int) $dayLinks === (int) date('j', $currentDayTime)) ? $dayLinkDiv : strftime('%d', $currentDayTime);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dayLinkDiv does not seem to be defined for all execution paths leading up to this point.
Loading history...
328
                                break;
329
                            case '1':
330
                                $weekArray['###DAYMON###'] = ((int) $dayLinks === (int) date('j', $currentDayTime)) ? $dayLinkDiv : strftime('%d', $currentDayTime);
331
                                break;
332
                            case '2':
333
                                $weekArray['###DAYTUE###'] = ((int) $dayLinks === (int) date('j', $currentDayTime)) ? $dayLinkDiv : strftime('%d', $currentDayTime);
334
                                break;
335
                            case '3':
336
                                $weekArray['###DAYWED###'] = ((int) $dayLinks === (int) date('j', $currentDayTime)) ? $dayLinkDiv : strftime('%d', $currentDayTime);
337
                                break;
338
                            case '4':
339
                                $weekArray['###DAYTHU###'] = ((int) $dayLinks === (int) date('j', $currentDayTime)) ? $dayLinkDiv : strftime('%d', $currentDayTime);
340
                                break;
341
                            case '5':
342
                                $weekArray['###DAYFRI###'] = ((int) $dayLinks === (int) date('j', $currentDayTime)) ? $dayLinkDiv : strftime('%d', $currentDayTime);
343
                                break;
344
                            case '6':
345
                                $weekArray['###DAYSAT###'] = ((int) $dayLinks === (int) date('j', $currentDayTime)) ? $dayLinkDiv : strftime('%d', $currentDayTime);
346
                                break;
347
                        }
348
                    }
349
                }
350
                // Fill the weeks.
351
                $subPartContentWeek .= $this->templateService->substituteMarkerArray($subParts['week'], $weekArray);
352
            }
353
            // Fill the week markers with the week entries.
354
            $subPartContent .= $this->templateService->substituteSubpart($subPartContentMonth, '###CALWEEK###', $subPartContentWeek);
355
        }
356
        return $subPartContent;
357
    }
358
359
    /**
360
     * The Years Method
361
     *
362
     * @access public
363
     *
364
     * @param string $content: The PlugIn content
365
     * @param array $conf: The PlugIn configuration
366
     *
367
     * @return string The content that is displayed on the website
368
     */
369
    public function years($content, $conf)
370
    {
371
        $this->init($conf);
372
        // Load current document.
373
        $this->loadDocument();
374
        if ($this->doc === null) {
375
            // Quit without doing anything if required variables are not set.
376
            return $content;
377
        }
378
        // Load template file.
379
        $this->getTemplate('###TEMPLATEYEAR###');
380
        // Get subpart templates
381
        $subparts['year'] = $this->templateService->getSubpart($this->template, '###LISTYEAR###');
382
        // Get the title of the anchor file
383
        $titleAnchor = $this->doc->getTitle($this->doc->uid);
384
385
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
386
            ->getQueryBuilderForTable('tx_dlf_documents');
387
388
        // Get all children of anchor. This should be the year anchor documents
389
        $result = $queryBuilder
390
            ->select(
391
                'tx_dlf_documents.uid AS uid',
392
                'tx_dlf_documents.title AS title',
393
                'tx_dlf_documents.mets_label AS label',
394
                'tx_dlf_documents.mets_orderlabel AS orderlabel'
395
            )
396
            ->from('tx_dlf_documents')
397
            ->where(
398
                $queryBuilder->expr()->eq('tx_dlf_documents.structure', Helper::getUidFromIndexName('year', 'tx_dlf_structures', $this->doc->cPid)),
0 ignored issues
show
introduced by
The property cPid is declared write-only in Kitodo\Dlf\Common\Document.
Loading history...
399
                $queryBuilder->expr()->eq('tx_dlf_documents.partof', intval($this->doc->uid)),
400
                Helper::whereExpression('tx_dlf_documents')
401
            )
402
            ->orderBy('tx_dlf_documents.mets_orderlabel')
403
            ->execute();
404
405
        $years = [];
406
        // Process results.
407
        while ($resArray = $result->fetch()) {
408
            $years[] = [
409
                'title' => !empty($resArray['label']) ? $resArray['label'] : (!empty($resArray['orderlabel']) ? $resArray['orderlabel'] : $resArray['title']),
410
                'uid' => $resArray['uid']
411
            ];
412
        }
413
        $subYearPartContent = '';
414
        if (count($years) > 0) {
415
            foreach ($years as $year) {
416
                $linkConf = [
417
                    'useCacheHash' => 1,
418
                    'parameter' => $GLOBALS['TSFE']->id,
419
                    'forceAbsoluteUrl' => !empty($this->conf['forceAbsoluteUrl']) ? 1 : 0,
420
                    'forceAbsoluteUrl.' => ['scheme' => !empty($this->conf['forceAbsoluteUrl']) && !empty($this->conf['forceAbsoluteUrlHttps']) ? 'https' : 'http'],
421
                    'additionalParams' => '&' . $this->prefixId . '[id]=' . urlencode($year['uid']),
422
                    'title' => $titleAnchor . ': ' . $year['title']
423
                ];
424
                $yearArray = [
425
                    '###YEARNAME###' => $this->cObj->typoLink($year['title'], $linkConf),
426
                ];
427
                $subYearPartContent .= $this->templateService->substituteMarkerArray($subparts['year'], $yearArray);
428
            }
429
        }
430
        // Link to years overview (should be itself here)
431
        $linkConf = [
432
            'useCacheHash' => 1,
433
            'parameter' => $GLOBALS['TSFE']->id,
434
            'forceAbsoluteUrl' => !empty($this->conf['forceAbsoluteUrl']) ? 1 : 0,
435
            'forceAbsoluteUrl.' => ['scheme' => !empty($this->conf['forceAbsoluteUrl']) && !empty($this->conf['forceAbsoluteUrlHttps']) ? 'https' : 'http'],
436
            'additionalParams' => '&' . $this->prefixId . '[id]=' . $this->doc->uid,
437
        ];
438
        $allYearsLink = $this->cObj->typoLink($this->pi_getLL('allYears', '', true) . ' ' . $this->doc->getTitle($this->doc->uid), $linkConf);
439
        // Fill markers.
440
        $markerArray = [
441
            '###LABEL_CHOOSE_YEAR###' => $this->pi_getLL('label.please_choose_year'),
442
            '###CALALLYEARS###' => $allYearsLink
443
        ];
444
        $this->template = $this->templateService->substituteMarkerArray($this->template, $markerArray);
445
        // Fill the week markers
446
        return $this->templateService->substituteSubpart($this->template, '###LISTYEAR###', $subYearPartContent);
447
    }
448
}
449