Passed
Push — refactor/backendModule-ValueOb... ( 355cec )
by Tomas Norre
07:44
created

BackendModule::getModuleMenu()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 29
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 1.0298

Importance

Changes 0
Metric Value
cc 1
eloc 24
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 29
ccs 20
cts 29
cp 0.6897
crap 1.0298
rs 9.536
1
<?php
2
3
declare(strict_types=1);
4
5
namespace AOE\Crawler\Backend;
6
7
/***************************************************************
8
 *  Copyright notice
9
 *
10
 *  (c) 2020 AOE GmbH <[email protected]>
11
 *
12
 *  All rights reserved
13
 *
14
 *  This script is part of the TYPO3 project. The TYPO3 project is
15
 *  free software; you can redistribute it and/or modify
16
 *  it under the terms of the GNU General Public License as published by
17
 *  the Free Software Foundation; either version 3 of the License, or
18
 *  (at your option) any later version.
19
 *
20
 *  The GNU General Public License can be found at
21
 *  http://www.gnu.org/copyleft/gpl.html.
22
 *
23
 *  This script is distributed in the hope that it will be useful,
24
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
25
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26
 *  GNU General Public License for more details.
27
 *
28
 *  This copyright notice MUST APPEAR in all copies of the script!
29
 ***************************************************************/
30
31
use AOE\Crawler\Configuration\ExtensionConfigurationProvider;
32
use AOE\Crawler\Controller\CrawlerController;
33
use AOE\Crawler\Converter\JsonCompatibilityConverter;
34
use AOE\Crawler\Domain\Model\Reason;
35
use AOE\Crawler\Domain\Repository\ProcessRepository;
36
use AOE\Crawler\Domain\Repository\QueueRepository;
37
use AOE\Crawler\Hooks\CrawlerHookInterface;
38
use AOE\Crawler\Service\ProcessService;
39
use AOE\Crawler\Utility\MessageUtility;
40
use AOE\Crawler\Utility\PhpBinaryUtility;
41
use AOE\Crawler\Utility\SignalSlotUtility;
42
use AOE\Crawler\Value\CrawlAction;
43
use AOE\Crawler\Value\ModuleMenu;
44
use AOE\Crawler\Value\ModuleSettings;
45
use Psr\Http\Message\UriInterface;
46
use TYPO3\CMS\Backend\Routing\UriBuilder;
47
use TYPO3\CMS\Backend\Template\ModuleTemplate;
48
use TYPO3\CMS\Backend\Tree\View\PageTreeView;
49
use TYPO3\CMS\Backend\Utility\BackendUtility;
50
use TYPO3\CMS\Core\Compatibility\PublicMethodDeprecationTrait;
51
use TYPO3\CMS\Core\Database\ConnectionPool;
52
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
53
use TYPO3\CMS\Core\Http\Uri;
54
use TYPO3\CMS\Core\Imaging\Icon;
55
use TYPO3\CMS\Core\Imaging\IconFactory;
56
use TYPO3\CMS\Core\Localization\LanguageService;
57
use TYPO3\CMS\Core\Utility\CommandUtility;
58
use TYPO3\CMS\Core\Utility\CsvUtility;
59
use TYPO3\CMS\Core\Utility\DebugUtility;
60
use TYPO3\CMS\Core\Utility\GeneralUtility;
61
use TYPO3\CMS\Core\Utility\MathUtility;
62
use TYPO3\CMS\Extbase\Object\ObjectManager;
63
use TYPO3\CMS\Fluid\View\StandaloneView;
64
use TYPO3\CMS\Info\Controller\InfoModuleController;
65
66
/**
67
 * Function for Info module, containing three main actions:
68
 * - List of all queued items
69
 * - Log functionality
70
 * - Process overview
71
 */
72
class BackendModule
73
{
74
    /**
75
     * @var InfoModuleController Contains a reference to the parent calling object
76
     */
77
    protected $pObj;
78
79
    /**
80
     * The current page ID
81
     * @var int
82
     */
83
    protected $id;
84
85
    // Internal, dynamic:
86
87
    /**
88
     * @var array
89
     */
90
    protected $duplicateTrack = [];
91
92
    /**
93
     * @var bool
94
     */
95
    protected $submitCrawlUrls = false;
96
97
    /**
98
     * @var bool
99
     */
100
    protected $downloadCrawlUrls = false;
101
102
    /**
103
     * @var int
104
     */
105
    protected $scheduledTime = 0;
106
107
    /**
108
     * @var int
109
     */
110
    protected $reqMinute = 1000;
111
112
    /**
113
     * @var array holds the selection of configuration from the configuration selector box
114
     */
115
    protected $incomingConfigurationSelection = [];
116
117
    /**
118
     * @var CrawlerController
119
     */
120
    protected $crawlerController;
121
122
    /**
123
     * @var array
124
     */
125
    protected $CSVaccu = [];
126
127
    /**
128
     * If true the user requested a CSV export of the queue
129
     *
130
     * @var boolean
131
     */
132
    protected $CSVExport = false;
133
134
    /**
135
     * @var array
136
     */
137
    protected $downloadUrls = [];
138
139
    /**
140
     * Holds the configuration from ext_conf_template loaded by getExtensionConfiguration()
141
     *
142
     * @var array
143
     */
144
    protected $extensionSettings = [];
145
146
    /**
147
     * Indicate that an flash message with an error is present.
148
     *
149
     * @var boolean
150
     */
151
    protected $isErrorDetected = false;
152
153
    /**
154
     * @var ProcessService
155
     */
156
    protected $processManager;
157
158
    /**
159
     * @var QueryBuilder
160
     */
161
    protected $queryBuilder;
162
163
    /**
164
     * @var QueueRepository
165
     */
166
    protected $queueRepository;
167
168
    /**
169
     * @var StandaloneView
170
     */
171
    protected $view;
172
173
    /**
174
     * @var IconFactory
175
     */
176
    protected $iconFactory;
177
178
    /**
179
     * @var JsonCompatibilityConverter
180
     */
181
    protected $jsonCompatibilityConverter;
182
183
    /**
184
     * @var LanguageService
185
     */
186
    private $languageService;
187
188
    /**
189
     * @var ModuleSettings
190
     */
191
    private $moduleSettings;
0 ignored issues
show
introduced by
The private property $moduleSettings is not used, and could be removed.
Loading history...
192
193
    public function __construct()
194
    {
195
        $this->languageService = $GLOBALS['LANG'];
196
        $objectManger = GeneralUtility::makeInstance(ObjectManager::class);
197
        $this->processManager = $objectManger->get(ProcessService::class);
198
        $this->queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_crawler_queue');
199
        $this->queueRepository = $objectManger->get(QueueRepository::class);
200
        $this->initializeView();
201
        $this->extensionSettings = GeneralUtility::makeInstance(ExtensionConfigurationProvider::class)->getExtensionConfiguration();
202
        $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
203
        $this->jsonCompatibilityConverter = GeneralUtility::makeInstance(JsonCompatibilityConverter::class);
204
    }
205
206
    /**
207
     * Called by the InfoModuleController
208
     */
209
    public function init(InfoModuleController $pObj): void
210
    {
211
212
        $this->pObj = $pObj;
213
        $this->id = (int) GeneralUtility::_GP('id');
214
        // Setting MOD_MENU items as we need them for logging:
215
        $this->pObj->MOD_MENU = array_merge($this->pObj->MOD_MENU, $this->getModuleMenu());
216
    }
217
218 1
    private function getModuleMenu(): array
219
    {
220
        return [
221
            'depth' => [
222 1
                0 => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_0'),
223 1
                1 => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_1'),
224 1
                2 => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_2'),
225 1
                3 => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_3'),
226 1
                4 => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_4'),
227 1
                99 => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_infi'),
228
            ],
229
            'crawlaction' => [
230 1
                'start' => $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.start'),
231 1
                'log' => $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.log'),
232 1
                'multiprocess' => $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.multiprocess'),
233
            ],
234 1
            'log_resultLog' => '',
235 1
            'log_feVars' => '',
236 1
            'processListMode' => '',
237
            'log_display' => [
238 1
                'all' => $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.all'),
239 1
                'pending' => $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.pending'),
240 1
                'finished' => $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.finished'),
241
            ],
242
            'itemsPerPage' => [
243 1
                '5' => $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.itemsPerPage.5'),
244 1
                '10' => $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.itemsPerPage.10'),
245 1
                '50' => $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.itemsPerPage.50'),
246 1
                '0' => $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.itemsPerPage.0'),
247
            ],
248
        ];
249
    }
250
251
    /**
252
     * Additions to the function menu array
253
     *
254
     * @return array Menu array
255
     * @deprecated Using BackendModule->modMenu() is deprecated since 9.1.1 and will be removed in v11.x
256
     */
257 1
    public function modMenu(): array
258
    {
259 1
        return $this->getModuleMenu();
260
    }
261
262
    public function main(): string
263
    {
264
        if (empty($this->pObj->MOD_SETTINGS['processListMode'])) {
265
            $this->pObj->MOD_SETTINGS['processListMode'] = 'simple';
266
        }
267
        $this->view->assign('currentPageId', $this->id);
268
269
        $selectedAction = (string) $this->pObj->MOD_SETTINGS['crawlaction'] ?? 'start';
270
271
        // Type function menu:
272
        $actionDropdown = BackendUtility::getFuncMenu(
273
            $this->id,
274
            'SET[crawlaction]',
275
            $selectedAction,
276
            $this->pObj->MOD_MENU['crawlaction']
277
        );
278
279
        $theOutput = '<h2>' . htmlspecialchars($this->getLanguageService()->getLL('title')) . '</h2>' . $actionDropdown;
280
281
        // Branch based on type:
282
        switch ($selectedAction) {
283
            case 'log':
284
                $quiPart = GeneralUtility::_GP('qid_details') ? '&qid_details=' . (int) GeneralUtility::_GP('qid_details') : '';
285
                $setId = (int) GeneralUtility::_GP('setID');
286
287
                // Additional menus for the log type:
288
                $theOutput .= $this->getDepthDropDownHtml();
289
                $theOutput .= $this->showLogAction($setId, $quiPart);
290
                break;
291
            case 'multiprocess':
292
                $theOutput .= $this->processOverviewAction();
293
                break;
294
            case 'start':
295
            default:
296
                $theOutput .= $this->showCrawlerInformationAction();
297
                break;
298
        }
299
300
        return $theOutput;
301
    }
302
303
    /*******************************
304
     *
305
     * Generate URLs for crawling:
306
     *
307
     ******************************/
308
309
    /**
310
     * Show a list of URLs to be crawled for each page
311
     */
312
    protected function showCrawlerInformationAction(): string
313
    {
314
        $this->view->setTemplate('ShowCrawlerInformation');
315
        if (empty($this->id)) {
316
            $this->isErrorDetected = true;
317
            MessageUtility::addErrorMessage($this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.noPageSelected'));
318
        } else {
319
            $crawlerParameter = GeneralUtility::_GP('_crawl');
320
            $downloadParameter = GeneralUtility::_GP('_download');
321
322
            $this->duplicateTrack = [];
323
            $this->submitCrawlUrls = isset($crawlerParameter);
324
            $this->downloadCrawlUrls = isset($downloadParameter);
325
            $this->makeCrawlerProcessableChecks();
326
327
            switch ((string) GeneralUtility::_GP('tstamp')) {
328
                case 'midnight':
329
                    $this->scheduledTime = mktime(0, 0, 0);
330
                    break;
331
                case '04:00':
332
                    $this->scheduledTime = mktime(0, 0, 0) + 4 * 3600;
333
                    break;
334
                case 'now':
335
                default:
336
                    $this->scheduledTime = time();
337
                    break;
338
            }
339
340
            $this->incomingConfigurationSelection = GeneralUtility::_GP('configurationSelection');
341
            $this->incomingConfigurationSelection = is_array($this->incomingConfigurationSelection) ? $this->incomingConfigurationSelection : [];
342
343
            $this->crawlerController = GeneralUtility::makeInstance(CrawlerController::class);
344
            $this->crawlerController->setAccessMode('gui');
345
            $this->crawlerController->setID = GeneralUtility::md5int(microtime());
346
347
            $code = '';
348
            $noConfigurationSelected = empty($this->incomingConfigurationSelection)
349
                || (count($this->incomingConfigurationSelection) === 1 && empty($this->incomingConfigurationSelection[0]));
350
            if ($noConfigurationSelected) {
351
                MessageUtility::addWarningMessage($this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.noConfigSelected'));
352
            } else {
353
                if ($this->submitCrawlUrls) {
354
                    $reason = new Reason();
355
                    $reason->setReason(Reason::REASON_GUI_SUBMIT);
356
                    $reason->setDetailText('The user ' . $GLOBALS['BE_USER']->user['username'] . ' added pages to the crawler queue manually');
357
358
                    $signalPayload = ['reason' => $reason];
359
                    SignalSlotUtility::emitSignal(
360
                        self::class,
361
                        SignalSlotUtility::SIGNAL_INVOKE_QUEUE_CHANGE,
362
                        $signalPayload
363
                    );
364
                }
365
366
                $code = $this->crawlerController->getPageTreeAndUrls(
367
                    $this->id,
368
                    $this->pObj->MOD_SETTINGS['depth'],
369
                    $this->scheduledTime,
370
                    $this->reqMinute,
371
                    $this->submitCrawlUrls,
372
                    $this->downloadCrawlUrls,
373
                    [], // Do not filter any processing instructions
374
                    $this->incomingConfigurationSelection
375
                );
376
            }
377
378
            $this->downloadUrls = $this->crawlerController->downloadUrls;
379
            $this->duplicateTrack = $this->crawlerController->duplicateTrack;
380
381
            $this->view->assign('noConfigurationSelected', $noConfigurationSelected);
382
            $this->view->assign('submitCrawlUrls', $this->submitCrawlUrls);
383
            $this->view->assign('amountOfUrls', count(array_keys($this->duplicateTrack)));
384
            $this->view->assign('selectors', $this->generateConfigurationSelectors());
385
            $this->view->assign('code', $code);
386
            $this->view->assign('displayActions', 0);
387
388
            // Download Urls to crawl:
389
            if ($this->downloadCrawlUrls) {
390
                // Creating output header:
391
                header('Content-Type: application/octet-stream');
392
                header('Content-Disposition: attachment; filename=CrawlerUrls.txt');
393
394
                // Printing the content of the CSV lines:
395
                echo implode(chr(13) . chr(10), $this->downloadUrls);
396
                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...
397
            }
398
        }
399
        return $this->view->render();
400
    }
401
402
    /**
403
     * Generates the configuration selectors for compiling URLs:
404
     */
405
    protected function generateConfigurationSelectors(): array
406
    {
407
        $selectors = [];
408
        $selectors['depth'] = $this->selectorBox(
409
            [
410
                0 => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_0'),
411
                1 => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_1'),
412
                2 => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_2'),
413
                3 => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_3'),
414
                4 => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_4'),
415
                99 => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_infi'),
416
            ],
417
            'SET[depth]',
418
            $this->pObj->MOD_SETTINGS['depth'],
419
            false
420
        );
421
422
        // Configurations
423
        $availableConfigurations = $this->crawlerController->getConfigurationsForBranch((int) $this->id, (int) $this->pObj->MOD_SETTINGS['depth'] ?: 0);
424
        $selectors['configurations'] = $this->selectorBox(
425
            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\BackendModule::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

425
            /** @scrutinizer ignore-type */ empty($availableConfigurations) ? [] : array_combine($availableConfigurations, $availableConfigurations),
Loading history...
426
            'configurationSelection',
427
            $this->incomingConfigurationSelection,
428
            true
429
        );
430
431
        // Scheduled time:
432
        $selectors['scheduled'] = $this->selectorBox(
433
            [
434
                'now' => $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.time.now'),
435
                'midnight' => $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.time.midnight'),
436
                '04:00' => $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.time.4am'),
437
            ],
438
            'tstamp',
439
            GeneralUtility::_POST('tstamp'),
440
            false
441
        );
442
443
        return $selectors;
444
    }
445
446
    /*******************************
447
     *
448
     * Shows log of indexed URLs
449
     *
450
     ******************************/
451
452
    /**
453
     * @throws \TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException
454
     */
455
    protected function showLogAction(int $setId, string $quiPath): string
456
    {
457
        $this->view->setTemplate('ShowLog');
458
        if (empty($this->id)) {
459
            $this->isErrorDetected = true;
460
            MessageUtility::addErrorMessage($this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.noPageSelected'));
461
        } else {
462
            $this->crawlerController = GeneralUtility::makeInstance(CrawlerController::class);
463
            $this->crawlerController->setAccessMode('gui');
464
            $this->crawlerController->setID = GeneralUtility::md5int(microtime());
465
466
            $csvExport = GeneralUtility::_POST('_csv');
467
            $this->CSVExport = isset($csvExport);
468
469
            // Read URL:
470
            if (GeneralUtility::_GP('qid_read')) {
471
                $this->crawlerController->readUrl((int) GeneralUtility::_GP('qid_read'), true);
472
            }
473
474
            // Look for set ID sent - if it is, we will display contents of that set:
475
            $showSetId = (int) GeneralUtility::_GP('setID');
476
477
            $queueId = GeneralUtility::_GP('qid_details');
478
            $this->view->assign('queueId', $queueId);
479
            $this->view->assign('setId', $showSetId);
480
            // Show details:
481
            if ($queueId) {
482
                // Get entry record:
483
                $q_entry = $this->queryBuilder
484
                    ->from('tx_crawler_queue')
485
                    ->select('*')
486
                    ->where(
487
                        $this->queryBuilder->expr()->eq('qid', $this->queryBuilder->createNamedParameter($queueId))
488
                    )
489
                    ->execute()
490
                    ->fetch();
491
492
                // Explode values
493
                $q_entry['parameters'] = $this->jsonCompatibilityConverter->convert($q_entry['parameters']);
494
                $q_entry['result_data'] = $this->jsonCompatibilityConverter->convert($q_entry['result_data']);
495
                $resStatus = $this->getResStatus($q_entry['result_data']);
496
                if (is_array($q_entry['result_data'])) {
497
                    $q_entry['result_data']['content'] = $this->jsonCompatibilityConverter->convert($q_entry['result_data']['content']);
498
                    if (! $this->pObj->MOD_SETTINGS['log_resultLog']) {
499
                        unset($q_entry['result_data']['content']['log']);
500
                    }
501
                }
502
503
                $this->view->assign('queueStatus', $resStatus);
504
                $this->view->assign('queueDetails', DebugUtility::viewArray($q_entry));
505
            } else {
506
                // Show list
507
                // Drawing tree:
508
                $tree = GeneralUtility::makeInstance(PageTreeView::class);
509
                $perms_clause = $GLOBALS['BE_USER']->getPagePermsClause(1);
510
                $tree->init('AND ' . $perms_clause);
511
512
                // Set root row:
513
                $pageinfo = BackendUtility::readPageAccess(
514
                    $this->id,
515
                    $perms_clause
516
                );
517
                $HTML = $this->iconFactory->getIconForRecord('pages', $pageinfo, Icon::SIZE_SMALL)->render();
518
                $tree->tree[] = [
519
                    'row' => $pageinfo,
520
                    'HTML' => $HTML,
521
                ];
522
523
                // Get branch beneath:
524
                if ($this->pObj->MOD_SETTINGS['depth']) {
525
                    $tree->getTree($this->id, $this->pObj->MOD_SETTINGS['depth']);
526
                }
527
528
                // If Flush button is pressed, flush tables instead of selecting entries:
529
                if (GeneralUtility::_POST('_flush')) {
530
                    $doFlush = true;
531
                    $doFullFlush = false;
532
                } elseif (GeneralUtility::_POST('_flush_all')) {
533
                    $doFlush = true;
534
                    $doFullFlush = true;
535
                } else {
536
                    $doFlush = false;
537
                    $doFullFlush = false;
538
                }
539
                $itemsPerPage = (int) $this->pObj->MOD_SETTINGS['itemsPerPage'];
540
                // Traverse page tree:
541
                $code = '';
542
                $count = 0;
543
                foreach ($tree->tree as $data) {
544
                    // Get result:
545
                    $logEntriesOfPage = $this->crawlerController->getLogEntriesForPageId(
546
                        (int) $data['row']['uid'],
547
                        $this->pObj->MOD_SETTINGS['log_display'],
548
                        $doFlush,
549
                        $doFullFlush,
550
                        $itemsPerPage
551
                    );
552
553
                    $code .= $this->drawLog_addRows(
554
                        $logEntriesOfPage,
555
                        $data['HTML'] . BackendUtility::getRecordTitle('pages', $data['row'], true)
556
                    );
557
                    if (++$count === 1000) {
558
                        break;
559
                    }
560
                }
561
                $this->view->assign('code', $code);
562
            }
563
564
            if ($this->CSVExport) {
565
                $this->outputCsvFile();
566
            }
567
        }
568
        $this->view->assign('showResultLog', (bool) $this->pObj->MOD_SETTINGS['log_resultLog']);
569
        $this->view->assign('showFeVars', (bool) $this->pObj->MOD_SETTINGS['log_feVars']);
570
        $this->view->assign('displayActions', 1);
571
        $this->view->assign('displayLogFilterHtml', $this->getDisplayLogFilterHtml($setId));
572
        $this->view->assign('itemPerPageHtml', $this->getItemsPerPageDropDownHtml());
573
        $this->view->assign('showResultLogHtml', $this->getShowResultLogCheckBoxHtml($setId, $quiPath));
574
        $this->view->assign('showFeVarsHtml', $this->getShowFeVarsCheckBoxHtml($setId, $quiPath));
575
        return $this->view->render();
576
    }
577
578
    /**
579
     * Outputs the CSV file and sets the correct headers
580
     */
581
    protected function outputCsvFile(): void
582
    {
583
        if (! count($this->CSVaccu)) {
584
            MessageUtility::addWarningMessage($this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:message.canNotExportEmptyQueueToCsvText'));
585
            return;
586
        }
587
        $csvLines = [];
588
589
        // Field names:
590
        reset($this->CSVaccu);
591
        $fieldNames = array_keys(current($this->CSVaccu));
592
        $csvLines[] = CsvUtility::csvValues($fieldNames);
593
594
        // Data:
595
        foreach ($this->CSVaccu as $row) {
596
            $csvLines[] = CsvUtility::csvValues($row);
597
        }
598
599
        // Creating output header:
600
        header('Content-Type: application/octet-stream');
601
        header('Content-Disposition: attachment; filename=CrawlerLog.csv');
602
603
        // Printing the content of the CSV lines:
604
        echo implode(chr(13) . chr(10), $csvLines);
605
        exit;
0 ignored issues
show
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...
606
    }
607
608
    /**
609
     * Create the rows for display of the page tree
610
     * For each page a number of rows are shown displaying GET variable configuration
611
     *
612
     * @param array $logEntriesOfPage Log items of one page
613
     * @param string $titleString Title string
614
     * @return string HTML <tr> content (one or more)
615
     * @throws \TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException
616
     */
617
    protected function drawLog_addRows(array $logEntriesOfPage, string $titleString): string
618
    {
619
        $colSpan = 9
620
            + ($this->pObj->MOD_SETTINGS['log_resultLog'] ? -1 : 0)
621
            + ($this->pObj->MOD_SETTINGS['log_feVars'] ? 3 : 0);
622
623
        if (! empty($logEntriesOfPage)) {
624
            $setId = (int) GeneralUtility::_GP('setID');
625
            $refreshIcon = $this->iconFactory->getIcon('actions-system-refresh', Icon::SIZE_SMALL);
626
            // Traverse parameter combinations:
627
            $c = 0;
628
            $content = '';
629
            foreach ($logEntriesOfPage as $vv) {
630
                // Title column:
631
                if (! $c) {
632
                    $titleClm = '<td rowspan="' . count($logEntriesOfPage) . '">' . $titleString . '</td>';
633
                } else {
634
                    $titleClm = '';
635
                }
636
637
                // Result:
638
                $resLog = $this->getResultLog($vv);
639
640
                $resultData = $vv['result_data'] ? $this->jsonCompatibilityConverter->convert($vv['result_data']) : [];
641
                $resStatus = $this->getResStatus($resultData);
642
643
                // Compile row:
644
                $parameters = $this->jsonCompatibilityConverter->convert($vv['parameters']);
645
646
                // Put data into array:
647
                $rowData = [];
648
                if ($this->pObj->MOD_SETTINGS['log_resultLog']) {
649
                    $rowData['result_log'] = $resLog;
650
                } else {
651
                    $rowData['scheduled'] = ($vv['scheduled'] > 0) ? BackendUtility::datetime($vv['scheduled']) : ' ' . $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.immediate');
652
                    $rowData['exec_time'] = $vv['exec_time'] ? BackendUtility::datetime($vv['exec_time']) : '-';
653
                }
654
                $rowData['result_status'] = GeneralUtility::fixed_lgd_cs($resStatus, 50);
655
                $url = htmlspecialchars($parameters['url'] ?? $parameters['alturl']);
656
                $rowData['url'] = '<a href="' . $url . '" target="_newWIndow">' . $url . '</a>';
657
                $rowData['feUserGroupList'] = $parameters['feUserGroupList'] ?: '';
658
                $rowData['procInstructions'] = is_array($parameters['procInstructions']) ? implode('; ', $parameters['procInstructions']) : '';
659
                $rowData['set_id'] = (string) $vv['set_id'];
660
661
                if ($this->pObj->MOD_SETTINGS['log_feVars']) {
662
                    $resFeVars = $this->getResFeVars($resultData ?: []);
0 ignored issues
show
Bug introduced by
It seems like $resultData ?: array() can also be of type true; however, parameter $resultData of AOE\Crawler\Backend\BackendModule::getResFeVars() 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

662
                    $resFeVars = $this->getResFeVars(/** @scrutinizer ignore-type */ $resultData ?: []);
Loading history...
663
                    $rowData['tsfe_id'] = $resFeVars['id'] ?: '';
664
                    $rowData['tsfe_gr_list'] = $resFeVars['gr_list'] ?: '';
665
                    $rowData['tsfe_no_cache'] = $resFeVars['no_cache'] ?: '';
666
                }
667
668
                $trClass = '';
669
                $warningIcon = '';
670
                if ($rowData['exec_time'] !== 0 && $resultData === false) {
671
                    $trClass = 'class="bg-danger"';
672
                    $warningIcon = $this->iconFactory->getIcon('actions-ban', Icon::SIZE_SMALL);
673
                }
674
675
                // Put rows together:
676
                $content .= '
677
                    <tr ' . $trClass . ' >
678
                        ' . $titleClm . '
679
                        <td><a href="' . $this->getInfoModuleUrl(['qid_details' => $vv['qid'], 'setID' => $setId]) . '">' . htmlspecialchars((string) $vv['qid']) . '</a></td>
680
                        <td><a href="' . $this->getInfoModuleUrl(['qid_read' => $vv['qid'], 'setID' => $setId]) . '">' . $refreshIcon . '</a>&nbsp;&nbsp;' . $warningIcon . '</td>';
681
                foreach ($rowData as $fKey => $value) {
682
                    if ($fKey === 'url') {
683
                        $content .= '<td>' . $value . '</td>';
684
                    } else {
685
                        $content .= '<td>' . nl2br(htmlspecialchars(strval($value))) . '</td>';
686
                    }
687
                }
688
                $content .= '</tr>';
689
                $c++;
690
691
                if ($this->CSVExport) {
692
                    // Only for CSV (adding qid and scheduled/exec_time if needed):
693
                    $rowData['result_log'] = implode('// ', explode(chr(10), $resLog));
694
                    $rowData['qid'] = $vv['qid'];
695
                    $rowData['scheduled'] = BackendUtility::datetime($vv['scheduled']);
696
                    $rowData['exec_time'] = $vv['exec_time'] ? BackendUtility::datetime($vv['exec_time']) : '-';
697
                    $this->CSVaccu[] = $rowData;
698
                }
699
            }
700
        } else {
701
            // Compile row:
702
            $content = '
703
                <tr>
704
                    <td>' . $titleString . '</td>
705
                    <td colspan="' . $colSpan . '"><em>' . $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.noentries') . '</em></td>
706
                </tr>';
707
        }
708
709
        return $content;
710
    }
711
712
    /**
713
     * Find Fe vars
714
     */
715 4
    protected function getResFeVars(array $resultData): array
716
    {
717 4
        if (empty($resultData)) {
718 1
            return [];
719
        }
720 3
        $requestResult = $this->jsonCompatibilityConverter->convert($resultData['content']);
721 3
        return $requestResult['vars'] ?? [];
722
    }
723
724
    /**
725
     * Extract the log information from the current row and retrieve it as formatted string.
726
     *
727
     * @param array $resultRow
728
     * @return string
729
     */
730 6
    protected function getResultLog($resultRow)
731
    {
732 6
        $content = '';
733 6
        if (is_array($resultRow) && array_key_exists('result_data', $resultRow)) {
734 5
            $requestContent = $this->jsonCompatibilityConverter->convert($resultRow['result_data']) ?: ['content' => ''];
735 5
            if (! array_key_exists('content', $requestContent)) {
0 ignored issues
show
Bug introduced by
It seems like $requestContent can also be of type true; however, parameter $search of array_key_exists() 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

735
            if (! array_key_exists('content', /** @scrutinizer ignore-type */ $requestContent)) {
Loading history...
736 1
                return $content;
737
            }
738 4
            $requestResult = $this->jsonCompatibilityConverter->convert($requestContent['content']);
739
740 4
            if (is_array($requestResult) && array_key_exists('log', $requestResult)) {
741 2
                $content = implode(chr(10), $requestResult['log']);
742
            }
743
        }
744 5
        return $content;
745
    }
746
747 7
    protected function getResStatus($requestContent): string
748
    {
749 7
        if (empty($requestContent)) {
750 2
            return '-';
751
        }
752 5
        if (! array_key_exists('content', $requestContent)) {
753 1
            return 'Content index does not exists in requestContent array';
754
        }
755
756 4
        $requestResult = $this->jsonCompatibilityConverter->convert($requestContent['content']);
757 4
        if (is_array($requestResult)) {
758 3
            if (empty($requestResult['errorlog'])) {
759 1
                return 'OK';
760
            }
761 2
            return implode("\n", $requestResult['errorlog']);
762
        }
763
764 1
        if (is_bool($requestResult)) {
0 ignored issues
show
introduced by
The condition is_bool($requestResult) is always true.
Loading history...
765 1
            return 'Error - no info, sorry!';
766
        }
767
768
        return 'Error: ' . substr(preg_replace('/\s+/', ' ', strip_tags($requestResult)), 0, 10000) . '...';
769
    }
770
771
    /**
772
     * This method is used to show an overview about the active an the finished crawling processes
773
     *
774
     * @return string
775
     */
776
    protected function processOverviewAction()
777
    {
778
        $this->view->setTemplate('ProcessOverview');
779
        $this->runRefreshHooks();
780
        $this->makeCrawlerProcessableChecks();
781
782
        try {
783
            $this->handleProcessOverviewActions();
784
        } catch (\Throwable $e) {
785
            $this->isErrorDetected = true;
786
            MessageUtility::addErrorMessage($e->getMessage());
787
        }
788
789
        $processRepository = new ProcessRepository();
790
        $queueRepository = new QueueRepository();
791
792
        $mode = $this->pObj->MOD_SETTINGS['processListMode'];
793
        if ($mode === 'simple') {
794
            $allProcesses = $processRepository->findAllActive();
795
        } else {
796
            $allProcesses = $processRepository->findAll();
797
        }
798
        $isCrawlerEnabled = ! $this->findCrawler()->getDisabled() && ! $this->isErrorDetected;
799
        $currentActiveProcesses = $processRepository->countActive();
800
        $maxActiveProcesses = MathUtility::forceIntegerInRange($this->extensionSettings['processLimit'], 1, 99, 1);
801
        $this->view->assignMultiple([
802
            'pageId' => (int) $this->id,
803
            'refreshLink' => $this->getRefreshLink(),
804
            'addLink' => $this->getAddLink($currentActiveProcesses, $maxActiveProcesses, $isCrawlerEnabled),
805
            'modeLink' => $this->getModeLink($mode),
806
            'enableDisableToggle' => $this->getEnableDisableLink($isCrawlerEnabled),
807
            'processCollection' => $allProcesses,
808
            'cliPath' => $this->processManager->getCrawlerCliPath(),
809
            'isCrawlerEnabled' => $isCrawlerEnabled,
810
            'totalUnprocessedItemCount' => $queueRepository->countAllPendingItems(),
811
            'assignedUnprocessedItemCount' => $queueRepository->countAllAssignedPendingItems(),
812
            'activeProcessCount' => $currentActiveProcesses,
813
            'maxActiveProcessCount' => $maxActiveProcesses,
814
            'mode' => $mode,
815
            'displayActions' => 0,
816
        ]);
817
818
        return $this->view->render();
819
    }
820
821
    /**
822
     * Returns a tag for the refresh icon
823
     *
824
     * @throws \TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException
825
     */
826
    protected function getRefreshLink(): string
827
    {
828
        return $this->getLinkButton(
829
            'actions-refresh',
830
            $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.refresh'),
831
            $this->getInfoModuleUrl(['SET[\'crawleraction\']' => 'crawleraction', 'id' => $this->id])
832
        );
833
    }
834
835
    /**
836
     * Returns a link for the panel to enable or disable the crawler
837
     *
838
     * @throws \TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException
839
     */
840
    protected function getEnableDisableLink(bool $isCrawlerEnabled): string
841
    {
842
        if ($isCrawlerEnabled) {
843
            return $this->getLinkButton(
844
                'tx-crawler-stop',
845
                $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.disablecrawling'),
846
                $this->getInfoModuleUrl(['action' => 'stopCrawling'])
847
            );
848
        }
849
        return $this->getLinkButton(
850
            'tx-crawler-start',
851
            $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.enablecrawling'),
852
            $this->getInfoModuleUrl(['action' => 'resumeCrawling'])
853
        );
854
    }
855
856
    /**
857
     * @throws \TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException
858
     */
859
    protected function getModeLink(string $mode): string
860
    {
861
        if ($mode === 'detail') {
862
            return $this->getLinkButton(
863
                'actions-document-view',
864
                $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.show.running'),
865
                $this->getInfoModuleUrl(['SET[\'processListMode\']' => 'simple'])
866
            );
867
        } elseif ($mode === 'simple') {
868
            return $this->getLinkButton(
869
                'actions-document-view',
870
                $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.show.all'),
871
                $this->getInfoModuleUrl(['SET[\'processListMode\']' => 'detail'])
872
            );
873
        }
874
        return '';
875
    }
876
877
    /**
878
     * @throws \TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException
879
     */
880
    protected function getAddLink(int $currentActiveProcesses, int $maxActiveProcesses, bool $isCrawlerEnabled): string
881
    {
882
        if (! $isCrawlerEnabled) {
883
            return '';
884
        }
885
        if ($currentActiveProcesses >= $maxActiveProcesses) {
886
            return '';
887
        }
888
889
        return $this->getLinkButton(
890
            'actions-add',
891
            $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.process.add'),
892
            $this->getInfoModuleUrl(['action' => 'addProcess'])
893
        );
894
    }
895
896
    /**
897
     * Verify that the crawler is executable.
898
     */
899
    protected function makeCrawlerProcessableChecks(): void
900
    {
901
        if (! $this->isPhpForkAvailable()) {
902
            $this->isErrorDetected = true;
903
            MessageUtility::addErrorMessage($this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:message.noPhpForkAvailable'));
904
        }
905
906
        $exitCode = 0;
907
        $out = [];
908
        CommandUtility::exec(
909
            PhpBinaryUtility::getPhpBinary() . ' -v',
910
            $out,
911
            $exitCode
912
        );
913
        if ($exitCode > 0) {
914
            $this->isErrorDetected = true;
915
            MessageUtility::addErrorMessage(sprintf($this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:message.phpBinaryNotFound'), htmlspecialchars($this->extensionSettings['phpPath'])));
916
        }
917
    }
918
919
    /**
920
     * Indicate that the required PHP method "popen" is
921
     * available in the system.
922
     */
923
    protected function isPhpForkAvailable(): bool
924
    {
925
        return function_exists('popen');
926
    }
927
928
    /**
929
     * Method to handle incomming actions of the process overview
930
     *
931
     * @throws ProcessException
932
     */
933
    protected function handleProcessOverviewActions(): void
934
    {
935
        $crawler = $this->findCrawler();
936
937
        switch (GeneralUtility::_GP('action')) {
938
            case 'stopCrawling':
939
                //set the cli status to disable (all processes will be terminated)
940
                $crawler->setDisabled(true);
941
                break;
942
            case 'addProcess':
943
                if ($this->processManager->startProcess() === false) {
0 ignored issues
show
introduced by
The condition $this->processManager->startProcess() === false is always false.
Loading history...
944
                    throw new ProcessException($this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.newprocesserror'));
0 ignored issues
show
Bug introduced by
The type AOE\Crawler\Backend\ProcessException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
945
                }
946
                MessageUtility::addNoticeMessage($this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.newprocess'));
947
                break;
948
            case 'resumeCrawling':
949
            default:
950
                //set the cli status to end (all processes will be terminated)
951
                $crawler->setDisabled(false);
952
                break;
953
        }
954
    }
955
956
    /**
957
     * Returns the singleton instance of the crawler.
958
     */
959
    protected function findCrawler(): CrawlerController
960
    {
961
        if (! $this->crawlerController instanceof CrawlerController) {
0 ignored issues
show
introduced by
$this->crawlerController is always a sub-type of AOE\Crawler\Controller\CrawlerController.
Loading history...
962
            $this->crawlerController = GeneralUtility::makeInstance(CrawlerController::class);
963
        }
964
        return $this->crawlerController;
965
    }
966
967
    /*****************************
968
     *
969
     * General Helper Functions
970
     *
971
     *****************************/
972
973
    /**
974
     * Create selector box
975
     *
976
     * @param array $optArray Options key(value) => label pairs
977
     * @param string $name Selector box name
978
     * @param string|array $value Selector box value (array for multiple...)
979
     * @param boolean $multiple If set, will draw multiple box.
980
     *
981
     * @return string HTML select element
982
     */
983
    protected function selectorBox($optArray, $name, $value, bool $multiple): string
984
    {
985
        if (! is_string($value) || ! is_array($value)) {
0 ignored issues
show
introduced by
The condition is_array($value) is always false.
Loading history...
986
            $value = '';
987
        }
988
989
        $options = [];
990
        foreach ($optArray as $key => $val) {
991
            $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...
992
            $options[] = '
993
                <option value="' . $key . '" ' . ($selected ? ' selected="selected"' : '') . '>' . htmlspecialchars($val) . '</option>';
994
        }
995
996
        return '<select class="form-control" name="' . htmlspecialchars($name . ($multiple ? '[]' : '')) . '"' . ($multiple ? ' multiple' : '') . '>' . implode('', $options) . '</select>';
997
    }
998
999
    /**
1000
     * Activate hooks
1001
     */
1002
    protected function runRefreshHooks(): void
1003
    {
1004
        $crawlerLib = GeneralUtility::makeInstance(CrawlerController::class);
1005
        foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['crawler']['refresh_hooks'] ?? [] as $objRef) {
1006
            /** @var CrawlerHookInterface $hookObj */
1007
            $hookObj = GeneralUtility::makeInstance($objRef);
1008
            if (is_object($hookObj)) {
1009
                $hookObj->crawler_init($crawlerLib);
1010
            }
1011
        }
1012
    }
1013
1014
    protected function initializeView(): void
1015
    {
1016
        $view = GeneralUtility::makeInstance(StandaloneView::class);
1017
        $view->setLayoutRootPaths(['EXT:crawler/Resources/Private/Layouts']);
1018
        $view->setPartialRootPaths(['EXT:crawler/Resources/Private/Partials']);
1019
        $view->setTemplateRootPaths(['EXT:crawler/Resources/Private/Templates/Backend']);
1020
        $view->getRequest()->setControllerExtensionName('Crawler');
1021
        $this->view = $view;
1022
    }
1023
1024
    protected function getLanguageService(): LanguageService
1025
    {
1026
        return $GLOBALS['LANG'];
1027
    }
1028
1029
    protected function getLinkButton(string $iconIdentifier, string $title, UriInterface $href): string
1030
    {
1031
        $moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
1032
        $buttonBar = $moduleTemplate->getDocHeaderComponent()->getButtonBar();
1033
        return (string) $buttonBar->makeLinkButton()
1034
            ->setHref((string) $href)
1035
            ->setIcon($this->iconFactory->getIcon($iconIdentifier, Icon::SIZE_SMALL))
1036
            ->setTitle($title)
1037
            ->setShowLabelText(true);
1038
    }
1039
1040
    /**
1041
     * Returns the URL to the current module, including $_GET['id'].
1042
     *
1043
     * @param array $uriParameters optional parameters to add to the URL
1044
     *
1045
     * @throws \TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException
1046
     */
1047
    protected function getInfoModuleUrl(array $uriParameters = []): Uri
1048
    {
1049
        if (GeneralUtility::_GP('id')) {
1050
            $uriParameters = array_merge($uriParameters, [
1051
                'id' => GeneralUtility::_GP('id'),
1052
            ]);
1053
        }
1054
        /** @var UriBuilder $uriBuilder */
1055
        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
1056
        return $uriBuilder->buildUriFromRoute('web_info', $uriParameters);
1057
    }
1058
1059
    private function getDepthDropDownHtml(): string
1060
    {
1061
        return BackendUtility::getFuncMenu(
1062
            $this->id,
1063
            'SET[depth]',
1064
            $this->pObj->MOD_SETTINGS['depth'],
1065
            $this->pObj->MOD_MENU['depth']
1066
        );
1067
    }
1068
1069
    private function getDisplayLogFilterHtml(int $setId): string
1070
    {
1071
        return $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.display') . ': ' . BackendUtility::getFuncMenu(
1072
                $this->id,
1073
                'SET[log_display]',
1074
                $this->pObj->MOD_SETTINGS['log_display'],
1075
                $this->pObj->MOD_MENU['log_display'],
1076
                'index.php',
1077
                '&setID=' . $setId
1078
            );
1079
    }
1080
1081
    private function getShowResultLogCheckBoxHtml(int $setId, string $quiPart): string
1082
    {
1083
        return BackendUtility::getFuncCheck(
1084
                $this->id,
1085
                'SET[log_resultLog]',
1086
                $this->pObj->MOD_SETTINGS['log_resultLog'],
1087
                'index.php',
1088
                '&setID=' . $setId . $quiPart
1089
            ) . '&nbsp;' . $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.showresultlog');
1090
    }
1091
1092
    private function getShowFeVarsCheckBoxHtml(int $setId, string $quiPart): string
1093
    {
1094
        return BackendUtility::getFuncCheck(
1095
                $this->id,
1096
                'SET[log_feVars]',
1097
                $this->pObj->MOD_SETTINGS['log_feVars'],
1098
                'index.php',
1099
                '&setID=' . $setId . $quiPart
1100
            ) . '&nbsp;' . $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.showfevars');
1101
    }
1102
1103
    private function getItemsPerPageDropDownHtml(): string
1104
    {
1105
        return $this->getLanguageService()->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xlf:labels.itemsPerPage') . ': ' .
1106
            BackendUtility::getFuncMenu(
1107
                $this->id,
1108
                'SET[itemsPerPage]',
1109
                $this->pObj->MOD_SETTINGS['itemsPerPage'],
1110
                $this->pObj->MOD_MENU['itemsPerPage']
1111
            );
1112
    }
1113
}
1114