Passed
Pull Request — master (#647)
by Tomas Norre
24:27 queued 20:23
created

StartRequestForm::showCrawlerInformationAction()   B

Complexity

Conditions 8
Paths 32

Size

Total Lines 79
Code Lines 54

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 72

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 8
eloc 54
c 4
b 0
f 0
nc 32
nop 1
dl 0
loc 79
ccs 0
cts 63
cp 0
crap 72
rs 7.7591

How to fix   Long Method   

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
            $scheduledTime = $this->getScheduledTime((string) GeneralUtility::_GP('tstamp'));
89
90
            $this->incomingConfigurationSelection = GeneralUtility::_GP('configurationSelection');
91
            $this->incomingConfigurationSelection = is_array($this->incomingConfigurationSelection) ? $this->incomingConfigurationSelection : [];
92
93
            $this->crawlerController = GeneralUtility::makeInstance(CrawlerController::class);
94
            $this->crawlerController->setAccessMode('gui');
95
            $this->crawlerController->setID = GeneralUtility::md5int(microtime());
96
97
            $code = '';
98
            $noConfigurationSelected = empty($this->incomingConfigurationSelection)
99
                || (count($this->incomingConfigurationSelection) === 1 && empty($this->incomingConfigurationSelection[0]));
100
            if ($noConfigurationSelected) {
101
                MessageUtility::addWarningMessage($this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.noConfigSelected'));
102
            } else {
103
                if ($submitCrawlUrls) {
104
                    $reason = new Reason();
105
                    $reason->setReason(Reason::REASON_GUI_SUBMIT);
106
                    $reason->setDetailText('The user ' . $GLOBALS['BE_USER']->user['username'] . ' added pages to the crawler queue manually');
107
108
                    $signalPayload = ['reason' => $reason];
109
                    SignalSlotUtility::emitSignal(
110
                        self::class,
111
                        SignalSlotUtility::SIGNAL_INVOKE_QUEUE_CHANGE,
112
                        $signalPayload
113
                    );
114
                }
115
116
                $code = $this->crawlerController->getPageTreeAndUrls(
117
                    $pageId,
118
                    $this->infoModuleController->MOD_SETTINGS['depth'],
119
                    $scheduledTime,
120
                    $this->reqMinute,
121
                    $submitCrawlUrls,
122
                    $downloadCrawlUrls,
123
                    // Do not filter any processing instructions
124
                    [],
125
                    $this->incomingConfigurationSelection
126
                );
127
            }
128
129
            $downloadUrls = $this->crawlerController->downloadUrls;
130
131
            $duplicateTrack = $this->crawlerController->duplicateTrack;
132
133
            $this->view->assign('noConfigurationSelected', $noConfigurationSelected);
134
            $this->view->assign('submitCrawlUrls', $submitCrawlUrls);
135
            $this->view->assign('amountOfUrls', count(array_keys($duplicateTrack)));
136
            $this->view->assign('selectors', $this->generateConfigurationSelectors());
137
            $this->view->assign('code', $code);
138
            $this->view->assign('displayActions', 0);
139
140
            // Download Urls to crawl:
141
            if ($downloadCrawlUrls) {
142
                // Creating output header:
143
                header('Content-Type: application/octet-stream');
144
                header('Content-Disposition: attachment; filename=CrawlerUrls.txt');
145
146
                // Printing the content of the CSV lines:
147
                echo implode(chr(13) . chr(10), $downloadUrls);
148
                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...
149
            }
150
        }
151
        return $this->view->render();
152
    }
153
154
    /**
155
     * Generates the configuration selectors for compiling URLs:
156
     */
157
    private function generateConfigurationSelectors(): array
158
    {
159
        $selectors = [];
160
        $selectors['depth'] = $this->selectorBox(
161
            [
162
                0 => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_0'),
163
                1 => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_1'),
164
                2 => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_2'),
165
                3 => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_3'),
166
                4 => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_4'),
167
                99 => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_infi'),
168
            ],
169
            'SET[depth]',
170
            $this->infoModuleController->MOD_SETTINGS['depth'],
171
            false
172
        );
173
174
        // Configurations
175
        $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...
176
        $selectors['configurations'] = $this->selectorBox(
177
            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

177
            /** @scrutinizer ignore-type */ empty($availableConfigurations) ? [] : array_combine($availableConfigurations, $availableConfigurations),
Loading history...
178
            'configurationSelection',
179
            $this->incomingConfigurationSelection,
180
            true
181
        );
182
183
        // Scheduled time:
184
        $selectors['scheduled'] = $this->selectorBox(
185
            [
186
                'now' => $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.time.now'),
187
                'midnight' => $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.time.midnight'),
188
                '04:00' => $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.time.4am'),
189
            ],
190
            'tstamp',
191
            GeneralUtility::_POST('tstamp'),
192
            false
193
        );
194
195
        return $selectors;
196
    }
197
198
    /**
199
     * Create selector box
200
     *
201
     * @param array $optArray Options key(value) => label pairs
202
     * @param string $name Selector box name
203
     * @param string|array $value Selector box value (array for multiple...)
204
     * @param boolean $multiple If set, will draw multiple box.
205
     *
206
     * @return string HTML select element
207
     */
208
    private function selectorBox($optArray, $name, $value, bool $multiple): string
209
    {
210
        if (! is_string($value) || ! is_array($value)) {
0 ignored issues
show
introduced by
The condition is_array($value) is always false.
Loading history...
211
            $value = '';
212
        }
213
214
        $options = [];
215
        foreach ($optArray as $key => $val) {
216
            $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...
217
            $options[] = '
218
                <option value="' . $key . '" ' . ($selected ? ' selected="selected"' : '') . '>' . htmlspecialchars($val, ENT_QUOTES | ENT_HTML5) . '</option>';
219
        }
220
221
        return '<select class="form-control" name="' . htmlspecialchars($name . ($multiple ? '[]' : ''), ENT_QUOTES | ENT_HTML5) . '"' . ($multiple ? ' multiple' : '') . '>' . implode('', $options) . '</select>';
222
    }
223
224
    /**
225
     * @return int
226
     */
227
    private function getScheduledTime(string $time)
228
    {
229
        switch ($time) {
230
            case 'midnight':
231
                $scheduledTime = mktime(0, 0, 0);
232
                break;
233
            case '04:00':
234
                $scheduledTime = mktime(0, 0, 0) + 4 * 3600;
235
                break;
236
            case 'now':
237
            default:
238
                $scheduledTime = time();
239
                break;
240
        }
241
        return $scheduledTime;
242
    }
243
}
244