Passed
Push — refactor/backendModule-ValueOb... ( ba8b37...91b878 )
by Tomas Norre
07:37
created

StartRequestForm::showCrawlerInformationAction()   C

Complexity

Conditions 11
Paths 125

Size

Total Lines 90
Code Lines 64

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 132

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 64
nc 125
nop 1
dl 0
loc 90
c 3
b 0
f 0
cc 11
ccs 0
cts 74
cp 0
crap 132
rs 6.4721

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace AOE\Crawler\Backend\RequestForm;
6
7
/*
8
 * (c) 2020 AOE GmbH <[email protected]>
9
 *
10
 * This file is part of the TYPO3 Crawler Extension.
11
 *
12
 * It is free software; you can redistribute it and/or modify it under
13
 * the terms of the GNU General Public License, either version 2
14
 * of the License, or any later version.
15
 *
16
 * For the full copyright and license information, please read the
17
 * LICENSE.txt file that was distributed with this source code.
18
 *
19
 * The TYPO3 project - inspiring people to share!
20
 */
21
22
use AOE\Crawler\Controller\CrawlerController;
23
use AOE\Crawler\Domain\Model\Reason;
24
use AOE\Crawler\Utility\MessageUtility;
25
use AOE\Crawler\Utility\SignalSlotUtility;
26
use TYPO3\CMS\Core\Utility\GeneralUtility;
27
use TYPO3\CMS\Fluid\View\StandaloneView;
28
use TYPO3\CMS\Info\Controller\InfoModuleController;
29
30
final class StartRequestForm extends AbstractRequestForm implements RequestFormInterface
31
{
32
    /**
33
     * @var StandaloneView
34
     */
35
    private $view;
36
37
    /**
38
     * @var InfoModuleController
39
     */
40
    private $infoModuleController;
41
42
    /**
43
     * @var int
44
     */
45
    private $reqMinute = 1000;
46
47
    /**
48
     * @var array holds the selection of configuration from the configuration selector box
49
     */
50
    private $incomingConfigurationSelection = [];
51
52
    public function __construct(StandaloneView $view, InfoModuleController $infoModuleController, array $extensionSettings)
53
    {
54
        $this->view = $view;
55
        $this->infoModuleController = $infoModuleController;
56
        $this->extensionSettings = $extensionSettings;
57
    }
58
59
    public function render($id, string $elementName, array $menuItems): string
60
    {
61
        return $this->showCrawlerInformationAction($id);
62
    }
63
64
    /*******************************
65
     *
66
     * Generate URLs for crawling:
67
     *
68
     ******************************/
69
70
    /**
71
     * Show a list of URLs to be crawled for each page
72
     */
73
    private function showCrawlerInformationAction(int $pageId): string
74
    {
75
        $this->view->setTemplate('ShowCrawlerInformation');
76
        if (empty($pageId)) {
77
            $this->isErrorDetected = true;
78
            MessageUtility::addErrorMessage($this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.noPageSelected'));
79
        } else {
80
            $crawlerParameter = GeneralUtility::_GP('_crawl');
81
            $downloadParameter = GeneralUtility::_GP('_download');
82
83
            $duplicateTrack = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $duplicateTrack is dead and can be removed.
Loading history...
84
            $submitCrawlUrls = isset($crawlerParameter);
85
            $downloadCrawlUrls = isset($downloadParameter);
86
            $this->makeCrawlerProcessableChecks($this->extensionSettings);
87
88
            switch ((string) GeneralUtility::_GP('tstamp')) {
89
                case 'midnight':
90
                    $scheduledTime = mktime(0, 0, 0);
91
                    break;
92
                case '04:00':
93
                    $scheduledTime = mktime(0, 0, 0) + 4 * 3600;
94
                    break;
95
                case 'now':
96
                default:
97
                    $scheduledTime = time();
98
                    break;
99
            }
100
101
            $this->incomingConfigurationSelection = GeneralUtility::_GP('configurationSelection');
102
            $this->incomingConfigurationSelection = is_array($this->incomingConfigurationSelection) ? $this->incomingConfigurationSelection : [];
103
104
            $this->crawlerController = GeneralUtility::makeInstance(CrawlerController::class);
105
            $this->crawlerController->setAccessMode('gui');
106
            $this->crawlerController->setID = GeneralUtility::md5int(microtime());
107
108
            $code = '';
109
            $noConfigurationSelected = empty($this->incomingConfigurationSelection)
110
                || (count($this->incomingConfigurationSelection) === 1 && empty($this->incomingConfigurationSelection[0]));
111
            if ($noConfigurationSelected) {
112
                MessageUtility::addWarningMessage($this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.noConfigSelected'));
113
            } else {
114
                if ($submitCrawlUrls) {
115
                    $reason = new Reason();
116
                    $reason->setReason(Reason::REASON_GUI_SUBMIT);
117
                    $reason->setDetailText('The user ' . $GLOBALS['BE_USER']->user['username'] . ' added pages to the crawler queue manually');
118
119
                    $signalPayload = ['reason' => $reason];
120
                    SignalSlotUtility::emitSignal(
121
                        self::class,
122
                        SignalSlotUtility::SIGNAL_INVOKE_QUEUE_CHANGE,
123
                        $signalPayload
124
                    );
125
                }
126
127
                $code = $this->crawlerController->getPageTreeAndUrls(
128
                    $pageId,
129
                    $this->infoModuleController->MOD_SETTINGS['depth'],
130
                    $scheduledTime,
131
                    $this->reqMinute,
132
                    $submitCrawlUrls,
133
                    $downloadCrawlUrls,
134
                    // Do not filter any processing instructions
135
                    [],
136
                    $this->incomingConfigurationSelection
137
                );
138
            }
139
140
            $downloadUrls = $this->crawlerController->downloadUrls;
141
142
            $duplicateTrack = $this->crawlerController->duplicateTrack;
143
144
            $this->view->assign('noConfigurationSelected', $noConfigurationSelected);
145
            $this->view->assign('submitCrawlUrls', $submitCrawlUrls);
146
            $this->view->assign('amountOfUrls', count(array_keys($duplicateTrack)));
147
            $this->view->assign('selectors', $this->generateConfigurationSelectors());
148
            $this->view->assign('code', $code);
149
            $this->view->assign('displayActions', 0);
150
151
            // Download Urls to crawl:
152
            if ($downloadCrawlUrls) {
153
                // Creating output header:
154
                header('Content-Type: application/octet-stream');
155
                header('Content-Disposition: attachment; filename=CrawlerUrls.txt');
156
157
                // Printing the content of the CSV lines:
158
                echo implode(chr(13) . chr(10), $downloadUrls);
159
                exit;
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return string. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
160
            }
161
        }
162
        return $this->view->render();
163
    }
164
165
    /**
166
     * Generates the configuration selectors for compiling URLs:
167
     */
168
    private function generateConfigurationSelectors(): array
169
    {
170
        $selectors = [];
171
        $selectors['depth'] = $this->selectorBox(
172
            [
173
                0 => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_0'),
174
                1 => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_1'),
175
                2 => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_2'),
176
                3 => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_3'),
177
                4 => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_4'),
178
                99 => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_infi'),
179
            ],
180
            'SET[depth]',
181
            $this->infoModuleController->MOD_SETTINGS['depth'],
182
            false
183
        );
184
185
        // Configurations
186
        $availableConfigurations = $this->crawlerController->getConfigurationsForBranch((int) $this->pageId, (int) $this->infoModuleController->MOD_SETTINGS['depth'] ?: 0);
0 ignored issues
show
Bug Best Practice introduced by
The property pageId does not exist on AOE\Crawler\Backend\RequestForm\StartRequestForm. Did you maybe forget to declare it?
Loading history...
187
        $selectors['configurations'] = $this->selectorBox(
188
            empty($availableConfigurations) ? [] : array_combine($availableConfigurations, $availableConfigurations),
0 ignored issues
show
Bug introduced by
It seems like empty($availableConfigur...vailableConfigurations) can also be of type false; however, parameter $optArray of AOE\Crawler\Backend\Requ...uestForm::selectorBox() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

188
            /** @scrutinizer ignore-type */ empty($availableConfigurations) ? [] : array_combine($availableConfigurations, $availableConfigurations),
Loading history...
189
            'configurationSelection',
190
            $this->incomingConfigurationSelection,
191
            true
192
        );
193
194
        // Scheduled time:
195
        $selectors['scheduled'] = $this->selectorBox(
196
            [
197
                'now' => $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.time.now'),
198
                'midnight' => $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.time.midnight'),
199
                '04:00' => $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.time.4am'),
200
            ],
201
            'tstamp',
202
            GeneralUtility::_POST('tstamp'),
203
            false
204
        );
205
206
        return $selectors;
207
    }
208
209
    /**
210
     * Create selector box
211
     *
212
     * @param array $optArray Options key(value) => label pairs
213
     * @param string $name Selector box name
214
     * @param string|array $value Selector box value (array for multiple...)
215
     * @param boolean $multiple If set, will draw multiple box.
216
     *
217
     * @return string HTML select element
218
     */
219
    private function selectorBox($optArray, $name, $value, bool $multiple): string
220
    {
221
        if (! is_string($value) || ! is_array($value)) {
0 ignored issues
show
introduced by
The condition is_array($value) is always false.
Loading history...
222
            $value = '';
223
        }
224
225
        $options = [];
226
        foreach ($optArray as $key => $val) {
227
            $selected = (! $multiple && ! strcmp($value, (string) $key)) || ($multiple && in_array($key, (array) $value, true));
0 ignored issues
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: $selected = (! $multiple..., (array)$value, true)), Probably Intended Meaning: $selected = ! $multiple ..., (array)$value, true))
Loading history...
228
            $options[] = '
229
                <option value="' . $key . '" ' . ($selected ? ' selected="selected"' : '') . '>' . htmlspecialchars($val, ENT_QUOTES | ENT_HTML5) . '</option>';
230
        }
231
232
        return '<select class="form-control" name="' . htmlspecialchars($name . ($multiple ? '[]' : ''), ENT_QUOTES | ENT_HTML5) . '"' . ($multiple ? ' multiple' : '') . '>' . implode('', $options) . '</select>';
233
    }
234
}
235