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

PageView   B

Complexity

Total Complexity 49

Size/Duplication

Total Lines 361
Duplicated Lines 0 %

Importance

Changes 7
Bugs 0 Features 1
Metric Value
wmc 49
eloc 171
c 7
b 0
f 1
dl 0
loc 361
rs 8.48

7 Methods

Rating   Name   Duplication   Size   Complexity  
A addInteraction() 0 18 4
B addViewerJS() 0 62 6
B addBasketForm() 0 38 8
B main() 0 44 8
A getFulltext() 0 21 6
B getAnnotationContainers() 0 46 10
B getImage() 0 26 7

How to fix   Complexity   

Complex Class

Complex classes like PageView 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 PageView, 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 Kitodo\Dlf\Common\IiifManifest;
17
use Ubl\Iiif\Presentation\Common\Model\Resources\ManifestInterface;
18
use Ubl\Iiif\Presentation\Common\Vocabulary\Motivation;
19
20
/**
21
 * Plugin 'Page View' for the 'dlf' extension
22
 *
23
 * @author Sebastian Meyer <[email protected]>
24
 * @package TYPO3
25
 * @subpackage dlf
26
 * @access public
27
 */
28
class PageView extends \Kitodo\Dlf\Common\AbstractPlugin
29
{
30
    public $scriptRelPath = 'Classes/Plugin/PageView.php';
31
32
    /**
33
     * Holds the controls to add to the map
34
     *
35
     * @var array
36
     * @access protected
37
     */
38
    protected $controls = [];
39
40
    /**
41
     * Holds the current images' URLs and MIME types
42
     *
43
     * @var array
44
     * @access protected
45
     */
46
    protected $images = [];
47
48
    /**
49
     * Holds the current fulltexts' URLs
50
     *
51
     * @var array
52
     * @access protected
53
     */
54
    protected $fulltexts = [];
55
56
    /**
57
     * Holds the current AnnotationLists / AnnotationPages
58
     *
59
     * @var array
60
     * @access protected
61
     */
62
    protected $annotationContainers = [];
63
64
    /**
65
     * Adds Viewer javascript
66
     *
67
     * @access protected
68
     *
69
     * @return string The output string for the ###JAVASCRIPT### template marker
70
     */
71
    protected function addViewerJS()
72
    {
73
        $markerArray = '';
74
        // CSS files.
75
        $cssFiles = [
76
            'Resources/Public/Javascript/OpenLayers/ol3.css'
77
        ];
78
        // Javascript files.
79
        $jsFiles = [
80
            // OpenLayers
81
            'Resources/Public/Javascript/OpenLayers/glif.min.js',
82
            'Resources/Public/Javascript/OpenLayers/ol3-dlf.js',
83
            // Viewer
84
            'Resources/Public/Javascript/PageView/Utility.js',
85
            'Resources/Public/Javascript/PageView/OL3.js',
86
            'Resources/Public/Javascript/PageView/OL3Styles.js',
87
            'Resources/Public/Javascript/PageView/OL3Sources.js',
88
            'Resources/Public/Javascript/PageView/AltoParser.js',
89
            'Resources/Public/Javascript/PageView/AnnotationParser.js',
90
            'Resources/Public/Javascript/PageView/AnnotationControl.js',
91
            'Resources/Public/Javascript/PageView/ImageManipulationControl.js',
92
            'Resources/Public/Javascript/PageView/FulltextControl.js',
93
            'Resources/Public/Javascript/PageView/PageView.js'
94
        ];
95
        // Viewer configuration.
96
        $viewerConfiguration = '
97
            $(document).ready(function() {
98
                if (dlfUtils.exists(dlfViewer)) {
99
                    tx_dlf_viewer = new dlfViewer({
100
                        controls: ["' . implode('", "', $this->controls) . '"],
101
                        div: "' . $this->conf['elementId'] . '",
102
                        images: ' . json_encode($this->images) . ',
103
                        fulltexts: ' . json_encode($this->fulltexts) . ',
104
                        annotationContainers: ' . json_encode($this->annotationContainers) . ',
105
                        useInternalProxy: ' . ($this->conf['useInternalProxy'] ? 1 : 0) . '
106
                    });
107
                }
108
            });
109
        ';
110
        // Add Javascript to page footer if not configured otherwise.
111
        if (empty($this->conf['addJStoBody'])) {
112
            $pageRenderer = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Page\PageRenderer::class);
113
            foreach ($cssFiles as $cssFile) {
114
                $pageRenderer->addCssFile(\TYPO3\CMS\Core\Utility\PathUtility::stripPathSitePrefix(\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath($this->extKey)) . $cssFile);
115
            }
116
            foreach ($jsFiles as $jsFile) {
117
                $pageRenderer->addJsFooterFile(\TYPO3\CMS\Core\Utility\PathUtility::stripPathSitePrefix(\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath($this->extKey)) . $jsFile);
118
            }
119
            $pageRenderer->addJsFooterInlineCode('kitodo-pageview-configuration', $viewerConfiguration);
120
        } else {
121
            foreach ($jsFiles as $jsFile) {
122
                $markerArray .= '<script type="text/javascript" src="' . \TYPO3\CMS\Core\Utility\PathUtility::stripPathSitePrefix(\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath($this->extKey)) . $jsFile . '"></script>' . "\n";
123
            }
124
            $markerArray .= '
125
                <script type="text/javascript">
126
                /*<![CDATA[*/
127
                /*kitodo-pageview-configuration*/
128
                ' . $viewerConfiguration . '
129
                /*]]>*/
130
                </script>';
131
        }
132
        return $markerArray;
133
    }
134
135
    /**
136
     * Adds pageview interaction (crop, magnifier and rotation)
137
     *
138
     * @access protected
139
     *
140
     * @return array Marker array
141
     */
142
    protected function addInteraction()
143
    {
144
        $markerArray = [];
145
        if ($this->piVars['id']) {
146
            if ($this->conf['crop']) {
147
                $markerArray['###EDITBUTTON###'] = '<a href="javascript: tx_dlf_viewer.activateSelection();" title="' . $this->pi_getLL('editMode', '', true) . '">' . $this->pi_getLL('editMode', '', true) . '</a>';
148
                $markerArray['###EDITREMOVE###'] = '<a href="javascript: tx_dlf_viewer.resetCropSelection();" title="' . $this->pi_getLL('editRemove', '', true) . '">' . $this->pi_getLL('editRemove', '', true) . '</a>';
149
            } else {
150
                $markerArray['###EDITBUTTON###'] = '';
151
                $markerArray['###EDITREMOVE###'] = '';
152
            }
153
            if ($this->conf['magnifier']) {
154
                $markerArray['###MAGNIFIER###'] = '<a href="javascript: tx_dlf_viewer.activateMagnifier();" title="' . $this->pi_getLL('magnifier', '', true) . '">' . $this->pi_getLL('magnifier', '', true) . '</a>';
155
            } else {
156
                $markerArray['###MAGNIFIER###'] = '';
157
            }
158
        }
159
        return $markerArray;
160
    }
161
162
    /**
163
     * Adds form to save cropping data to basket
164
     *
165
     * @access protected
166
     *
167
     * @return array Marker array
168
     */
169
    protected function addBasketForm()
170
    {
171
        $markerArray = [];
172
        // Add basket button
173
        if ($this->conf['basketButton'] && $this->conf['targetBasket'] && $this->piVars['id']) {
174
            $label = $this->pi_getLL('addBasket', '', true);
175
            $params = [
176
                'id' => $this->piVars['id'],
177
                'addToBasket' => true
178
            ];
179
            if (empty($this->piVars['page'])) {
180
                $params['page'] = 1;
181
            }
182
            $basketConf = [
183
                'parameter' => $this->conf['targetBasket'],
184
                'forceAbsoluteUrl' => !empty($this->conf['forceAbsoluteUrl']) ? 1 : 0,
185
                'forceAbsoluteUrl.' => ['scheme' => !empty($this->conf['forceAbsoluteUrl']) && !empty($this->conf['forceAbsoluteUrlHttps']) ? 'https' : 'http'],
186
                'additionalParams' => \TYPO3\CMS\Core\Utility\GeneralUtility::implodeArrayForUrl($this->prefixId, $params, '', true, false),
187
                'title' => $label
188
            ];
189
            $output = '<form id="addToBasketForm" action="' . $this->cObj->typoLink_URL($basketConf) . '" method="post">';
190
            $output .= '<input type="hidden" name="tx_dlf[startpage]" id="startpage" value="' . $this->piVars['page'] . '">';
191
            $output .= '<input type="hidden" name="tx_dlf[endpage]" id="endpage" value="' . $this->piVars['page'] . '">';
192
            $output .= '<input type="hidden" name="tx_dlf[startX]" id="startX">';
193
            $output .= '<input type="hidden" name="tx_dlf[startY]" id="startY">';
194
            $output .= '<input type="hidden" name="tx_dlf[endX]" id="endX">';
195
            $output .= '<input type="hidden" name="tx_dlf[endY]" id="endY">';
196
            $output .= '<input type="hidden" name="tx_dlf[rotation]" id="rotation">';
197
            $output .= '<button id="submitBasketForm" onclick="this.form.submit()">' . $label . '</button>';
198
            $output .= '</form>';
199
            $output .= '<script>';
200
            $output .= '$(document).ready(function() { $("#submitBasketForm").click(function() { $("#addToBasketForm").submit(); }); });';
201
            $output .= '</script>';
202
            $markerArray['###BASKETBUTTON###'] = $output;
203
        } else {
204
            $markerArray['###BASKETBUTTON###'] = '';
205
        }
206
        return $markerArray;
207
    }
208
209
    /**
210
     * Get image's URL and MIME type
211
     *
212
     * @access protected
213
     *
214
     * @param int $page: Page number
215
     *
216
     * @return array URL and MIME type of image file
217
     */
218
    protected function getImage($page)
219
    {
220
        $image = [];
221
        // Get @USE value of METS fileGrp.
222
        $fileGrps = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $this->conf['fileGrps']);
223
        while ($fileGrp = @array_pop($fileGrps)) {
224
            // Get image link.
225
            if (!empty($this->doc->physicalStructureInfo[$this->doc->physicalStructure[$page]]['files'][$fileGrp])) {
226
                $image['url'] = $this->doc->getFileLocation($this->doc->physicalStructureInfo[$this->doc->physicalStructure[$page]]['files'][$fileGrp]);
227
                if ($this->conf['useInternalProxy']) {
228
                    // Configure @action URL for form.
229
                    $linkConf = [
230
                        'parameter' => $GLOBALS['TSFE']->id,
231
                        'forceAbsoluteUrl' => !empty($this->conf['forceAbsoluteUrl']) ? 1 : 0,
232
                        'forceAbsoluteUrl.' => ['scheme' => !empty($this->conf['forceAbsoluteUrl']) && !empty($this->conf['forceAbsoluteUrlHttps']) ? 'https' : 'http'],
233
                        'additionalParams' => '&eID=tx_dlf_pageview_proxy&url=' . urlencode($image['url']),
234
                    ];
235
                    $image['url'] = $this->cObj->typoLink_URL($linkConf);
236
                }
237
                $image['mimetype'] = $this->doc->getFileMimeType($this->doc->physicalStructureInfo[$this->doc->physicalStructure[$page]]['files'][$fileGrp]);
238
                break;
239
            } else {
240
                Helper::devLog('File not found in fileGrp "' . $fileGrp . '"', DEVLOG_SEVERITY_WARNING);
241
            }
242
        }
243
        return $image;
244
    }
245
246
    /**
247
     * Get fulltext URL and MIME type
248
     *
249
     * @access protected
250
     *
251
     * @param int $page: Page number
252
     *
253
     * @return array URL and MIME type of fulltext file
254
     */
255
    protected function getFulltext($page)
256
    {
257
        $fulltext = [];
258
        // Get fulltext link.
259
        if (!empty($this->doc->physicalStructureInfo[$this->doc->physicalStructure[$page]]['files'][$this->conf['fileGrpFulltext']])) {
260
            $fulltext['url'] = $this->doc->getFileLocation($this->doc->physicalStructureInfo[$this->doc->physicalStructure[$page]]['files'][$this->conf['fileGrpFulltext']]);
261
            if ($this->conf['useInternalProxy']) {
262
                // Configure @action URL for form.
263
                $linkConf = [
264
                    'parameter' => $GLOBALS['TSFE']->id,
265
                    'forceAbsoluteUrl' => !empty($this->conf['forceAbsoluteUrl']) ? 1 : 0,
266
                    'forceAbsoluteUrl.' => ['scheme' => !empty($this->conf['forceAbsoluteUrl']) && !empty($this->conf['forceAbsoluteUrlHttps']) ? 'https' : 'http'],
267
                    'additionalParams' => '&eID=tx_dlf_pageview_proxy&url=' . urlencode($fulltext['url']),
268
                ];
269
                $fulltext['url'] = $this->cObj->typoLink_URL($linkConf);
270
            }
271
            $fulltext['mimetype'] = $this->doc->getFileMimeType($this->doc->physicalStructureInfo[$this->doc->physicalStructure[$page]]['files'][$this->conf['fileGrpFulltext']]);
272
        } else {
273
            Helper::devLog('File not found in fileGrp "' . $this->conf['fileGrpFulltext'] . '"', DEVLOG_SEVERITY_WARNING);
274
        }
275
        return $fulltext;
276
    }
277
278
    /**
279
     * Get all AnnotationPages / AnnotationLists that contain text Annotations with motivation "painting"
280
     *
281
     * @access protected
282
     *
283
     * @param int $page: Page number
284
     * @return array An array containing the IRIs of the AnnotationLists / AnnotationPages as well as
285
     *               some information about the canvas.
286
     */
287
    protected function getAnnotationContainers($page)
288
    {
289
        if ($this->doc instanceof IiifManifest) {
290
            $canvasId = $this->doc->physicalStructure[$page];
291
            $iiif = $this->doc->getIiif();
292
            if ($iiif instanceof ManifestInterface) {
0 ignored issues
show
introduced by
$iiif is always a sub-type of Ubl\Iiif\Presentation\Co...urces\ManifestInterface.
Loading history...
293
                $canvas = $iiif->getContainedResourceById($canvasId);
294
                /* @var $canvas \Ubl\Iiif\Presentation\Common\Model\Resources\CanvasInterface */
295
                if ($canvas != null && !empty($canvas->getPossibleTextAnnotationContainers(Motivation::PAINTING))) {
296
                    $annotationContainers = [];
297
                    /*
298
                     *  TODO Analyzing the annotations on the server side requires loading the annotation lists / pages
299
                     *  just to determine wether they contain text annotations for painting. This will take time and lead to a bad user experience.
300
                     *  It would be better to link every annotation and analyze the data on the client side.
301
                     *
302
                     *  On the other hand, server connections are potentially better than client connections. Downloading annotation lists
303
                     */
304
                    foreach ($canvas->getPossibleTextAnnotationContainers(Motivation::PAINTING) as $annotationContainer) {
305
                        if (($textAnnotations = $annotationContainer->getTextAnnotations(Motivation::PAINTING)) != null) {
306
                            foreach ($textAnnotations as $annotation) {
307
                                if (
308
                                    $annotation->getBody()->getFormat() == 'text/plain'
309
                                    && $annotation->getBody()->getChars() != null
310
                                ) {
311
                                    $annotationListData = [];
312
                                    $annotationListData['uri'] = $annotationContainer->getId();
313
                                    $annotationListData['label'] = $annotationContainer->getLabelForDisplay();
314
                                    $annotationContainers[] = $annotationListData;
315
                                    break;
316
                                }
317
                            }
318
                        }
319
                    }
320
                    $result = [
321
                        'canvas' => [
322
                            'id' => $canvas->getId(),
323
                            'width' => $canvas->getWidth(),
324
                            'height' => $canvas->getHeight(),
325
                        ],
326
                        'annotationContainers' => $annotationContainers
327
                    ];
328
                    return $result;
329
                }
330
            }
331
        }
332
        return [];
333
    }
334
335
    /**
336
     * The main method of the PlugIn
337
     *
338
     * @access public
339
     *
340
     * @param string $content: The PlugIn content
341
     * @param array $conf: The PlugIn configuration
342
     *
343
     * @return string The content that is displayed on the website
344
     */
345
    public function main($content, $conf)
346
    {
347
        $this->init($conf);
348
        // Load current document.
349
        $this->loadDocument();
350
        if (
351
            $this->doc === null
352
            || $this->doc->numPages < 1
353
        ) {
354
            // Quit without doing anything if required variables are not set.
355
            return $content;
356
        } else {
357
            if (!empty($this->piVars['logicalPage'])) {
358
                $this->piVars['page'] = $this->doc->getPhysicalPage($this->piVars['logicalPage']);
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...
359
                // The logical page parameter should not appear again
360
                unset($this->piVars['logicalPage']);
361
            }
362
            // Set default values if not set.
363
            // $this->piVars['page'] may be integer or string (physical structure @ID)
364
            if ((int) $this->piVars['page'] > 0 || empty($this->piVars['page'])) {
365
                $this->piVars['page'] = \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange((int) $this->piVars['page'], 1, $this->doc->numPages, 1);
366
            } else {
367
                $this->piVars['page'] = array_search($this->piVars['page'], $this->doc->physicalStructure);
368
            }
369
            $this->piVars['double'] = \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange($this->piVars['double'], 0, 1, 0);
370
        }
371
        // Load template file.
372
        $this->getTemplate();
373
        // Get image data.
374
        $this->images[0] = $this->getImage($this->piVars['page']);
375
        $this->fulltexts[0] = $this->getFulltext($this->piVars['page']);
376
        $this->annotationContainers[0] = $this->getAnnotationContainers($this->piVars['page']);
377
        if ($this->piVars['double'] && $this->piVars['page'] < $this->doc->numPages) {
378
            $this->images[1] = $this->getImage($this->piVars['page'] + 1);
379
            $this->fulltexts[1] = $this->getFulltext($this->piVars['page'] + 1);
380
            $this->annotationContainers[1] = $this->getAnnotationContainers($this->piVars['page'] + 1);
381
        }
382
        // Get the controls for the map.
383
        $this->controls = explode(',', $this->conf['features']);
384
        // Fill in the template markers.
385
        $markerArray = array_merge($this->addInteraction(), $this->addBasketForm());
386
        $markerArray['###JAVASCRIPT###'] = $this->addViewerJS();
387
        $content .= $this->templateService->substituteMarkerArray($this->template, $markerArray);
388
        return $this->pi_wrapInBaseClass($content);
389
    }
390
}
391