Completed
Push — typo3v9 ( 5153b7...aa6d82 )
by Tomas Norre
20:31
created

BackendModule::addNoticeMessage()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
ccs 0
cts 4
cp 0
crap 2
1
<?php
2
namespace AOE\Crawler\Backend;
3
4
/***************************************************************
5
 *  Copyright notice
6
 *
7
 *  (c) 2018 AOE GmbH <[email protected]>
8
 *
9
 *  All rights reserved
10
 *
11
 *  This script is part of the TYPO3 project. The TYPO3 project is
12
 *  free software; you can redistribute it and/or modify
13
 *  it under the terms of the GNU General Public License as published by
14
 *  the Free Software Foundation; either version 3 of the License, or
15
 *  (at your option) any later version.
16
 *
17
 *  The GNU General Public License can be found at
18
 *  http://www.gnu.org/copyleft/gpl.html.
19
 *
20
 *  This script is distributed in the hope that it will be useful,
21
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
 *  GNU General Public License for more details.
24
 *
25
 *  This copyright notice MUST APPEAR in all copies of the script!
26
 ***************************************************************/
27
28
use AOE\Crawler\Backend\View\PaginationView;
29
use AOE\Crawler\Backend\View\ProcessListView;
30
use AOE\Crawler\Controller\CrawlerController;
31
use AOE\Crawler\Domain\Model\Reason;
32
use AOE\Crawler\Domain\Repository\ProcessRepository;
33
use AOE\Crawler\Domain\Repository\QueueRepository;
34
use AOE\Crawler\Event\EventDispatcher;
35
use AOE\Crawler\Service\ProcessService;
36
use AOE\Crawler\Utility\BackendModuleUtility;
37
use AOE\Crawler\Utility\CsvUtility;
38
use AOE\Crawler\Utility\ExtensionSettingUtility;
39
use AOE\Crawler\Utility\IconUtility;
40
use TYPO3\CMS\Backend\Module\AbstractFunctionModule;
41
use TYPO3\CMS\Backend\Tree\View\PageTreeView;
42
use TYPO3\CMS\Backend\Utility\BackendUtility;
43
use TYPO3\CMS\Beuser\Domain\Model\BackendUser;
44
use TYPO3\CMS\Beuser\Domain\Repository\BackendUserRepository;
45
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
46
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
47
use TYPO3\CMS\Core\Database\ConnectionPool;
48
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
49
use TYPO3\CMS\Core\Imaging\Icon;
50
use TYPO3\CMS\Core\Messaging\FlashMessage;
51
use TYPO3\CMS\Core\Messaging\FlashMessageService;
52
use TYPO3\CMS\Core\Utility\DebugUtility;
53
use TYPO3\CMS\Core\Utility\GeneralUtility;
54
use TYPO3\CMS\Core\Utility\MathUtility;
55
use TYPO3\CMS\Extbase\Object\ObjectManager;
56
use TYPO3\CMS\Extbase\Persistence\Generic\QueryResult;
57
58
/**
59
 * Class BackendModule
60
 *
61
 * @package AOE\Crawler\Backend
62
 */
63
class BackendModule extends AbstractFunctionModule
0 ignored issues
show
Deprecated Code introduced by
The class TYPO3\CMS\Backend\Module\AbstractFunctionModule has been deprecated with message: since TYPO3 v9, will be removed in TYPO3 v10.0

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
64
{
65
    // Internal, dynamic:
66
    public $duplicateTrack = [];
67
    public $submitCrawlUrls = false;
68
    public $downloadCrawlUrls = false;
69
70
    public $scheduledTime = 0;
71
    public $reqMinute = 0;
72
73
    const STATUS_ICON_ERROR = 3;
74
    const STATUS_ICON_WARNING = 2;
75
    const STATUS_ICON_NOTIFICATION = 1;
76
    const STATUS_ICON_OK = -1;
77
78
    /**
79
     * @var array holds the selection of configuration from the configuration selector box
80
     */
81
    public $incomingConfigurationSelection = [];
82
83
    /**
84
     * @var CrawlerController
85
     */
86
    public $crawlerController;
87
88
    public $CSVaccu = [];
89
90
    /**
91
     * If true the user requested a CSV export of the queue
92
     *
93
     * @var boolean
94
     */
95
    public $CSVExport = false;
96
97
    public $downloadUrls = [];
98
99
    /**
100
     * Holds the configuration from ext_conf_template loaded by loadExtensionSettings()
101
     *
102
     * @var array
103
     */
104
    protected $extensionSettings = [];
105
106
    /**
107
     * Indicate that an flash message with an error is present.
108
     *
109
     * @var boolean
110
     */
111
    protected $isErrorDetected = false;
112
113
    /**
114
     * @var ProcessService
115
     */
116
    protected $processManager;
117
118
    /**
119
     * @var BackendUserRepository
120
     */
121
    protected $backendUserRepository;
122
123
    /**
124
     * @var QueryBuilder
125
     */
126
    protected $queryBuilder;
127
128
    /**
129
     * @var QueueRepository
130
     */
131
    protected $queueRepository;
132
133
    /**
134
     * the constructor
135
     */
136 2
    public function __construct()
137
    {
138 2
        $objectManger = GeneralUtility::makeInstance(ObjectManager::class);
139 2
        $this->processManager = new ProcessService();
140 2
        $this->backendUserRepository = $objectManger->get(BackendUserRepository::class);
141 2
        $this->queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_crawler_queue');
142 2
        $this->queueRepository = $objectManger->get(QueueRepository::class);
143 2
    }
144
145
    /**
146
     * Additions to the function menu array
147
     *
148
     * @return array Menu array
149
     */
150
    public function modMenu()
151
    {
152
        global $LANG;
153
154
        return [
155
            'depth' => [
156
                0 => $LANG->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.depth_0'),
157
                1 => $LANG->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.depth_1'),
158
                2 => $LANG->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.depth_2'),
159
                3 => $LANG->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.depth_3'),
160
                4 => $LANG->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.depth_4'),
161
                99 => $LANG->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.depth_infi'),
162
            ],
163
            'crawlaction' => [
164
                'start' => $LANG->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.start'),
165
                'log' => $LANG->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.log'),
166
                'multiprocess' => $LANG->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.multiprocess')
167
            ],
168
            'log_resultLog' => '',
169
            'log_feVars' => '',
170
            'processListMode' => '',
171
            'log_display' => [
172
                'all' => $LANG->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.all'),
173
                'pending' => $LANG->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.pending'),
174
                'finished' => $LANG->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.finished')
175
            ],
176
            'itemsPerPage' => [
177
                '5' => $LANG->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.itemsPerPage.5'),
178
                '10' => $LANG->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.itemsPerPage.10'),
179
                '50' => $LANG->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.itemsPerPage.50'),
180
                '0' => $LANG->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.itemsPerPage.0')
181
            ]
182
        ];
183
    }
184
185
    /**
186
     * Load extension settings
187
     *
188
     * @return void
189
     *
190
     * @deprecated since crawler v7.0.0, will be removed in crawler v8.0.0.
191
     */
192
    protected function loadExtensionSettings()
193
    {
194
        $isVersionLowerThan9 = \TYPO3\CMS\Core\Utility\VersionNumberUtility::convertVersionNumberToInteger(TYPO3_version) < 9000000;
195
        if ($isVersionLowerThan9) {
196
            $this->extensionSettings = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['crawler']);
197
        } else {
198
            $this->extensionSettings = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('crawler');
199
        }
200
    }
201
202
    /**
203
     * Main function
204
     *
205
     * @return	string		HTML output
206
     */
207
    public function main()
208
    {
209
        global $LANG, $BACK_PATH;
210
211
        //$this->incLocalLang();
212
213
        $this->extensionSettings = ExtensionSettingUtility::loadExtensionSettings();
214
        if (empty($this->pObj->MOD_SETTINGS['processListMode'])) {
215
            $this->pObj->MOD_SETTINGS['processListMode'] = 'simple';
216
        }
217
218
        // Set CSS styles specific for this document:
219
        $this->pObj->content = str_replace('/*###POSTCSSMARKER###*/', '
220
			TABLE.c-list TR TD { white-space: nowrap; vertical-align: top; }
221
		', $this->pObj->content);
222
223
        $this->pObj->content .= '<style type="text/css"><!--
224
			table.url-table,
225
			table.param-expanded,
226
			table.crawlerlog {
227
				border-bottom: 1px solid grey;
228
				border-spacing: 0;
229
				border-collapse: collapse;
230
			}
231
			table.crawlerlog td,
232
			table.url-table td {
233
				border: 1px solid lightgrey;
234
				border-bottom: 1px solid grey;
235
				 white-space: nowrap; vertical-align: top;
236
			}
237
		--></style>
238
		<link rel="stylesheet" type="text/css" href="' . $BACK_PATH . '../typo3conf/ext/crawler/template/res.css" />
239
		';
240
241
        // Type function menu:
242
        $h_func = BackendUtility::getFuncMenu(
243
            $this->pObj->id,
244
            'SET[crawlaction]',
245
            $this->pObj->MOD_SETTINGS['crawlaction'],
246
            $this->pObj->MOD_MENU['crawlaction'],
247
            'index.php'
248
        );
249
250
        // Additional menus for the log type:
251
        if ($this->pObj->MOD_SETTINGS['crawlaction'] === 'log') {
252
            $h_func .= BackendUtility::getFuncMenu(
253
                $this->pObj->id,
254
                'SET[depth]',
255
                $this->pObj->MOD_SETTINGS['depth'],
256
                $this->pObj->MOD_MENU['depth'],
257
                'index.php'
258
            );
259
260
            $quiPart = GeneralUtility::_GP('qid_details') ? '&qid_details=' . intval(GeneralUtility::_GP('qid_details')) : '';
261
262
            $setId = intval(GeneralUtility::_GP('setID'));
263
264
            $h_func .= '<hr/>' .
265
                    $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.display') . ': ' . BackendUtility::getFuncMenu($this->pObj->id, 'SET[log_display]', $this->pObj->MOD_SETTINGS['log_display'], $this->pObj->MOD_MENU['log_display'], 'index.php', '&setID=' . $setId) . ' - ' .
266
                    $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.showresultlog') . ': ' . BackendUtility::getFuncCheck($this->pObj->id, 'SET[log_resultLog]', $this->pObj->MOD_SETTINGS['log_resultLog'], 'index.php', '&setID=' . $setId . $quiPart) . ' - ' .
267
                    $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.showfevars') . ': ' . BackendUtility::getFuncCheck($this->pObj->id, 'SET[log_feVars]', $this->pObj->MOD_SETTINGS['log_feVars'], 'index.php', '&setID=' . $setId . $quiPart) . ' - ' .
268
                    $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.itemsPerPage') . ': ' .
269
                    BackendUtility::getFuncMenu(
270
                        $this->pObj->id,
271
                        'SET[itemsPerPage]',
272
                        $this->pObj->MOD_SETTINGS['itemsPerPage'],
273
                        $this->pObj->MOD_MENU['itemsPerPage'],
274
                        'index.php'
275
                    );
276
        }
277
278
        $theOutput = $this->section($LANG->getLL('title'), $h_func, false, true);
279
280
        // Branch based on type:
281
        switch ((string)$this->pObj->MOD_SETTINGS['crawlaction']) {
282
            case 'start':
283
                if (empty($this->pObj->id)) {
284
                    $this->addErrorMessage($GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.noPageSelected'));
285
                } else {
286
                    $theOutput .= $this->section('', $this->drawURLs(), false, true);
287
                }
288
                break;
289
            case 'log':
290
                if (empty($this->pObj->id)) {
291
                    $this->addErrorMessage($GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.noPageSelected'));
292
                } else {
293
                    $theOutput .= $this->section('', $this->drawLog(), false, true);
294
                }
295
                break;
296
            case 'cli':
297
                // TODO: drawCLIstatus is not defined, why did we refactor it away?
298
                $theOutput .= $this->section('', $this->drawCLIstatus(), false, true);
0 ignored issues
show
Bug introduced by
The method drawCLIstatus() does not seem to exist on object<AOE\Crawler\Backend\BackendModule>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
299
                break;
300
            case 'multiprocess':
301
                $theOutput .= $this->section('', $this->drawProcessOverviewAction(), false, true);
302
                break;
303
        }
304
305
        return $theOutput;
306
    }
307
308
    /*******************************
309
     *
310
     * Generate URLs for crawling:
311
     *
312
     ******************************/
313
314
    /**
315
     * Produces a table with overview of the URLs to be crawled for each page
316
     *
317
     * @return	string		HTML output
318
     */
319
    public function drawURLs()
320
    {
321
        global $BACK_PATH, $BE_USER;
322
323
        $crawlerParameter = GeneralUtility::_GP('_crawl');
324
        $downloadParameter = GeneralUtility::_GP('_download');
325
326
        // Init:
327
        $this->duplicateTrack = [];
328
        $this->submitCrawlUrls = isset($crawlerParameter);
329
        $this->downloadCrawlUrls = isset($downloadParameter);
330
        $this->makeCrawlerProcessableChecks();
331
332
        switch ((string) GeneralUtility::_GP('tstamp')) {
333
            case 'midnight':
334
                $this->scheduledTime = mktime(0, 0, 0);
335
            break;
336
            case '04:00':
337
                $this->scheduledTime = mktime(0, 0, 0) + 4 * 3600;
338
            break;
339
            case 'now':
340
            default:
341
                $this->scheduledTime = time();
342
            break;
343
        }
344
        // $this->reqMinute = \TYPO3\CMS\Core\Utility\GeneralUtility::intInRange(\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('perminute'),1,10000);
345
        // TODO: check relevance
346
        $this->reqMinute = 1000;
347
348
        $this->incomingConfigurationSelection = GeneralUtility::_GP('configurationSelection');
0 ignored issues
show
Documentation Bug introduced by
It seems like \TYPO3\CMS\Core\Utility\...onfigurationSelection') can also be of type null or string. However, the property $incomingConfigurationSelection is declared as type array. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
349
        $this->incomingConfigurationSelection = is_array($this->incomingConfigurationSelection) ? $this->incomingConfigurationSelection : [];
350
351
        $this->crawlerController = GeneralUtility::makeInstance(CrawlerController::class);
352
        $this->crawlerController->setAccessMode('gui');
353
        $this->crawlerController->setID = GeneralUtility::md5int(microtime());
354
355
        if (empty($this->incomingConfigurationSelection)
356
            || (count($this->incomingConfigurationSelection) == 1 && empty($this->incomingConfigurationSelection[0]))
357
            ) {
358
            $this->addWarningMessage($GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.noConfigSelected'));
359
            $code = '
360
			<tr>
361
				<td colspan="7"><b>' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.noConfigSelected') . '</b></td>
362
			</tr>';
363
        } else {
364
            if ($this->submitCrawlUrls) {
365
                $reason = new Reason();
366
                $reason->setReason(Reason::REASON_GUI_SUBMIT);
367
368
                if ($BE_USER instanceof BackendUserAuthentication) {
369
                    $username = $BE_USER->user['username'];
370
                    $reason->setDetailText('The user ' . $username . ' added pages to the crawler queue manually ');
371
                }
372
373
                EventDispatcher::getInstance()->post(
374
                    'invokeQueueChange',
375
                    $this->findCrawler()->setID,
376
                    ['reason' => $reason]
377
                );
378
            }
379
380
            $code = $this->crawlerController->getPageTreeAndUrls(
381
                $this->pObj->id,
382
                $this->pObj->MOD_SETTINGS['depth'],
383
                $this->scheduledTime,
384
                $this->reqMinute,
385
                $this->submitCrawlUrls,
386
                $this->downloadCrawlUrls,
387
                [], // Do not filter any processing instructions
388
                $this->incomingConfigurationSelection
389
            );
390
        }
391
392
        $this->downloadUrls = $this->crawlerController->downloadUrls;
393
        $this->duplicateTrack = $this->crawlerController->duplicateTrack;
394
395
        $output = '';
396
        if ($code) {
397
            $output .= '<h3>' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.configuration') . ':</h3>';
398
            $output .= '<input type="hidden" name="id" value="' . intval($this->pObj->id) . '" />';
399
400
            if (!$this->submitCrawlUrls) {
401
                $output .= $this->drawURLs_cfgSelectors() . '<br />';
402
                $output .= '<input type="submit" name="_update" value="' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.triggerUpdate') . '" /> ';
403
                $output .= '<input type="submit" name="_crawl" value="' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.triggerCrawl') . '" /> ';
404
                $output .= '<input type="submit" name="_download" value="' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.triggerDownload') . '" /><br /><br />';
405
                $output .= $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.count') . ': ' . count(array_keys($this->duplicateTrack)) . '<br />';
406
                $output .= $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.curtime') . ': ' . date('H:i:s', time()) . '<br />';
407
                $output .= '<br />
408
					<table class="lrPadding c-list url-table">' .
409
                        $this->drawURLs_printTableHeader() .
410
                        $code .
411
                    '</table>';
412
            } else {
413
                $output .= count(array_keys($this->duplicateTrack)) . ' ' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.submitted') . '. <br /><br />';
414
                $output .= '<input type="submit" name="_" value="' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.continue') . '" />';
415
                $output .= '<input type="submit" onclick="this.form.elements[\'SET[crawlaction]\'].value=\'log\';" value="' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.continueinlog') . '" />';
416
            }
417
        }
418
419
        // Download Urls to crawl:
420
        if ($this->downloadCrawlUrls) {
421
422
                // Creating output header:
423
            $mimeType = 'application/octet-stream';
424
            Header('Content-Type: ' . $mimeType);
425
            Header('Content-Disposition: attachment; filename=CrawlerUrls.txt');
426
427
            // Printing the content of the CSV lines:
428
            echo implode(chr(13) . chr(10), $this->downloadUrls);
429
430
            exit;
431
        }
432
433
        return 	$output;
434
    }
435
436
    /**
437
     * Draws the configuration selectors for compiling URLs:
438
     *
439
     * @return	string		HTML table
440
     */
441
    public function drawURLs_cfgSelectors()
442
    {
443
        $cell = [];
444
445
        // depth
446
        $cell[] = $this->selectorBox(
447
            [
448
                0 => $GLOBALS['LANG']->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.depth_0'),
449
                1 => $GLOBALS['LANG']->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.depth_1'),
450
                2 => $GLOBALS['LANG']->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.depth_2'),
451
                3 => $GLOBALS['LANG']->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.depth_3'),
452
                4 => $GLOBALS['LANG']->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.depth_4'),
453
                99 => $GLOBALS['LANG']->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.depth_infi'),
454
            ],
455
            'SET[depth]',
456
            $this->pObj->MOD_SETTINGS['depth'],
457
            false
458
        );
459
        $availableConfigurations = $this->crawlerController->getConfigurationsForBranch($this->pObj->id, $this->pObj->MOD_SETTINGS['depth'] ? $this->pObj->MOD_SETTINGS['depth'] : 0);
460
461
        // Configurations
462
        $cell[] = $this->selectorBox(
463
            empty($availableConfigurations) ? [] : array_combine($availableConfigurations, $availableConfigurations),
464
            'configurationSelection',
465
            $this->incomingConfigurationSelection,
0 ignored issues
show
Documentation introduced by
$this->incomingConfigurationSelection is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
466
            true
467
        );
468
469
        // Scheduled time:
470
        $cell[] = $this->selectorBox(
471
            [
472
                'now' => $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.time.now'),
473
                'midnight' => $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.time.midnight'),
474
                '04:00' => $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.time.4am'),
475
            ],
476
            'tstamp',
477
            GeneralUtility::_POST('tstamp'),
0 ignored issues
show
Bug introduced by
It seems like \TYPO3\CMS\Core\Utility\...tility::_POST('tstamp') targeting TYPO3\CMS\Core\Utility\GeneralUtility::_POST() can also be of type array or null; however, AOE\Crawler\Backend\BackendModule::selectorBox() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
478
            false
479
        );
480
481
        $output = '
482
			<table class="lrPadding c-list">
483
				<tr class="bgColor5 tableheader">
484
					<td>' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.depth') . ':</td>
485
					<td>' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.configurations') . ':</td>
486
					<td>' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.scheduled') . ':</td>
487
				</tr>
488
				<tr class="bgColor4">
489
					<td valign="top">' . implode('</td>
490
					<td valign="top">', $cell) . '</td>
491
				</tr>
492
			</table>';
493
494
        return $output;
495
    }
496
497
    /**
498
     * Create Table header row for URL display
499
     *
500
     * @return	string		Table header
501
     */
502
    public function drawURLs_printTableHeader()
503
    {
504
        $content = '
505
			<tr class="bgColor5 tableheader">
506
				<td>' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.pagetitle') . ':</td>
507
				<td>' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.key') . ':</td>
508
				<td>' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.parametercfg') . ':</td>
509
				<td>' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.values') . ':</td>
510
				<td>' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.urls') . ':</td>
511
				<td>' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.options') . ':</td>
512
				<td>' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.parameters') . ':</td>
513
			</tr>';
514
515
        return $content;
516
    }
517
518
    /**
519
     * Begins an output section and sets header and content
520
     *
521
     * @param string $label The header
522
     * @param string $text The HTML-content
523
     * @param bool $nostrtoupper	A flag that will prevent the header from being converted to uppercase
524
     * @param bool $sH Defines the type of header (if set, "<h3>" rather than the default "h4")
525
     * @param int $type The number of an icon to show with the header (see the icon-function). -1,1,2,3
526
     * @param bool $allowHTMLinHeader If set, HTML tags are allowed in $label (otherwise this value is by default htmlspecialchars()'ed)
527
     * @return string HTML content
528
     * @see icons(), sectionHeader()
529
     */
530
    public function section($label, $text, $nostrtoupper = false, $sH = false, $type = 0, $allowHTMLinHeader = false)
531
    {
532
        $str = '';
533
        // Setting header
534
        if ($label) {
535
            if (!$allowHTMLinHeader) {
536
                $label = htmlspecialchars($label);
537
            }
538
            $str .= $this->sectionHeader($this->icons($type) . $label, $sH, $nostrtoupper ? '' : ' class="uppercase"');
539
        }
540
        // Setting content
541
        $str .= '
542
543
	<!-- Section content -->
544
' . $text;
545
        return $this->sectionBegin() . $str;
546
    }
547
548
    /**
549
     * Inserts a divider image
550
     * Ends a section (if open) before inserting the image
551
     *
552
     * @param int $dist The margin-top/-bottom of the <hr> ruler.
553
     * @return string HTML content
554
     */
555
    public function divider($dist)
556
    {
557
        $dist = (int)$dist;
558
        $str = '
559
560
	<!-- DIVIDER -->
561
	<hr style="margin-top: ' . $dist . 'px; margin-bottom: ' . $dist . 'px;" />
562
';
563
        return $this->sectionEnd() . $str;
564
    }
565
566
    /**
567
     * Make a section header.
568
     * Begins a section if not already open.
569
     *
570
     * @param string $label The label between the <h3> or <h4> tags. (Allows HTML)
571
     * @param bool $sH If set, <h3> is used, otherwise <h4>
572
     * @param string $addAttrib Additional attributes to h-tag, eg. ' class=""'
573
     * @return string HTML content
574
     */
575
    public function sectionHeader($label, $sH = false, $addAttrib = '')
576
    {
577
        $tag = $sH ? 'h2' : 'h3';
578
        if ($addAttrib && $addAttrib[0] !== ' ') {
579
            $addAttrib = ' ' . $addAttrib;
580
        }
581
        $str = '
582
583
	<!-- Section header -->
584
	<' . $tag . $addAttrib . '>' . $label . '</' . $tag . '>
585
';
586
        return $this->sectionBegin() . $str;
587
    }
588
589
    /**
590
     * Begins an output section.
591
     * Returns the <div>-begin tag AND sets the ->sectionFlag TRUE (if the ->sectionFlag is not already set!)
592
     * You can call this function even if a section is already begun since the function will only return something if the sectionFlag is not already set!
593
     *
594
     * @return string HTML content
595
     */
596
    public function sectionBegin()
597
    {
598
        if (!$this->sectionFlag) {
599
            $this->sectionFlag = 1;
0 ignored issues
show
Bug introduced by
The property sectionFlag does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
600
            $str = '
601
602
	<!-- ***********************
603
	      Begin output section.
604
	     *********************** -->
605
	<div>
606
';
607
            return $str;
608
        }
609
        return '';
610
    }
611
612
    /**
613
     * Ends and output section
614
     * Returns the </div>-end tag AND clears the ->sectionFlag (but does so only IF the sectionFlag is set - that is a section is 'open')
615
     * See sectionBegin() also.
616
     *
617
     * @return string HTML content
618
     */
619
    public function sectionEnd()
620
    {
621
        if ($this->sectionFlag) {
622
            $this->sectionFlag = 0;
623
            return '
624
	</div>
625
	<!-- *********************
626
	      End output section.
627
	     ********************* -->
628
';
629
        }
630
        return '';
631
    }
632
633
    /**
634
     * Returns an image-tag with an 18x16 icon of the following types:
635
     *
636
     * $type:
637
     * -1:	OK icon (Check-mark)
638
     * 1:	Notice (Speach-bubble)
639
     * 2:	Warning (Yellow triangle)
640
     * 3:	Fatal error (Red stop sign)
641
     *
642
     * @param int $type See description
643
     * @param string $styleAttribValue Value for style attribute
644
     * @return string HTML image tag (if applicable)
645
     */
646
    public function icons($type, $styleAttribValue = '')
0 ignored issues
show
Unused Code introduced by
The parameter $styleAttribValue is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
647
    {
648
        switch ($type) {
649
            case self::STATUS_ICON_ERROR:
650
                $icon = 'status-dialog-error';
651
                break;
652
            case self::STATUS_ICON_WARNING:
653
                $icon = 'status-dialog-warning';
654
                break;
655
            case self::STATUS_ICON_NOTIFICATION:
656
                $icon = 'status-dialog-notification';
657
                break;
658
            case self::STATUS_ICON_OK:
659
                $icon = 'status-dialog-ok';
660
                break;
661
            default:
662
                // Do nothing
663
        }
664
        if ($icon) {
665
            return $this->iconFactory->getIcon($icon, Icon::SIZE_SMALL)->render();
0 ignored issues
show
Bug introduced by
The property iconFactory does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
Bug introduced by
The variable $icon does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
666
        }
667
    }
668
669
    /*******************************
670
     *
671
     * Shows log of indexed URLs
672
     *
673
     ******************************/
674
675
    /**
676
     * Shows the log of indexed URLs
677
     *
678
     * @return	string		HTML output
679
     */
680
    public function drawLog()
681
    {
682
        global $BACK_PATH;
683
        $output = '';
684
685
        // Init:
686
        $this->crawlerController = GeneralUtility::makeInstance(CrawlerController::class);
687
        $this->crawlerController->setAccessMode('gui');
688
        $this->crawlerController->setID = GeneralUtility::md5int(microtime());
689
690
        $csvExport = GeneralUtility::_POST('_csv');
691
        $this->CSVExport = isset($csvExport);
692
693
        // Read URL:
694
        if (GeneralUtility::_GP('qid_read')) {
695
            $this->crawlerController->readUrl(intval(GeneralUtility::_GP('qid_read')), true);
696
        }
697
698
        // Look for set ID sent - if it is, we will display contents of that set:
699
        $showSetId = intval(GeneralUtility::_GP('setID'));
700
701
        // Show details:
702
        if (GeneralUtility::_GP('qid_details')) {
703
704
                // Get entry record:
705
            $q_entry = $this->queryBuilder
706
                ->from('tx_crawler_queue')
707
                ->select('*')
708
                ->where(
709
                    $this->queryBuilder->expr()->eq('qid', $this->queryBuilder->createNamedParameter(GeneralUtility::_GP('qid_details')))
710
                )
711
                ->execute()
712
                ->fetch();
713
714
            // Explode values:
715
            $resStatus = $this->getResStatus($q_entry);
716
            $q_entry['parameters'] = unserialize($q_entry['parameters']);
717
            $q_entry['result_data'] = unserialize($q_entry['result_data']);
718
            if (is_array($q_entry['result_data'])) {
719
                $q_entry['result_data']['content'] = unserialize($q_entry['result_data']['content']);
720
721
                if (!$this->pObj->MOD_SETTINGS['log_resultLog']) {
722
                    unset($q_entry['result_data']['content']['log']);
723
                }
724
            }
725
726
            // Print rudimentary details:
727
            $output .= '
728
				<br /><br />
729
				<input type="submit" value="' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.back') . '" name="_back" />
730
				<input type="hidden" value="' . $this->pObj->id . '" name="id" />
731
				<input type="hidden" value="' . $showSetId . '" name="setID" />
732
				<br />
733
				Current server time: ' . date('H:i:s', time()) . '<br />' .
734
                'Status: ' . $resStatus . '<br />' .
735
                DebugUtility::viewArray($q_entry);
736
        } else {	// Show list:
737
738
            // If either id or set id, show list:
739
            if ($this->pObj->id || $showSetId) {
740
                if ($this->pObj->id) {
741
                    // Drawing tree:
742
                    $tree = GeneralUtility::makeInstance(PageTreeView::class);
743
                    $perms_clause = $GLOBALS['BE_USER']->getPagePermsClause(1);
744
                    $tree->init('AND ' . $perms_clause);
745
746
                    // Set root row:
747
                    $HTML = IconUtility::getIconForRecord('pages', $this->pObj->pageinfo);
0 ignored issues
show
Bug introduced by
The property pageinfo does not seem to exist in TYPO3\CMS\Backend\Module\BaseScriptClass.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
748
                    $tree->tree[] = [
749
                        'row' => $this->pObj->pageinfo,
750
                        'HTML' => $HTML
751
                    ];
752
753
                    // Get branch beneath:
754
                    if ($this->pObj->MOD_SETTINGS['depth']) {
755
                        $tree->getTree($this->pObj->id, $this->pObj->MOD_SETTINGS['depth'], '');
756
                    }
757
758
                    // Traverse page tree:
759
                    $code = '';
760
                    $count = 0;
761
                    foreach ($tree->tree as $data) {
762
                        $code .= $this->drawLog_addRows(
763
                            $data['row'],
764
                            $data['HTML'] . BackendUtility::getRecordTitle('pages', $data['row'], true),
765
                            intval($this->pObj->MOD_SETTINGS['itemsPerPage'])
766
                        );
767
                        if (++$count == 1000) {
768
                            break;
769
                        }
770
                    }
771
                } else {
772
                    $code = '';
773
                    $code .= $this->drawLog_addRows(
774
                        $showSetId,
0 ignored issues
show
Documentation introduced by
$showSetId is of type integer, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
775
                        'Set ID: ' . $showSetId
776
                    );
777
                }
778
779
                if ($code) {
780
                    $output .= '
781
						<br /><br />
782
						<input type="submit" value="' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.reloadlist') . '" name="_reload" />
783
						<input type="submit" value="' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.downloadcsv') . '" name="_csv" />
784
						<input type="submit" value="' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.flushvisiblequeue') . '" name="_flush" onclick="return confirm(\'' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.confirmyouresure') . '\');" />
785
						<input type="submit" value="' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.flushfullqueue') . '" name="_flush_all" onclick="return confirm(\'' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.confirmyouresure') . '\');" />
786
						<input type="hidden" value="' . $this->pObj->id . '" name="id" />
787
						<input type="hidden" value="' . $showSetId . '" name="setID" />
788
						<br />
789
						' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.curtime') . ': ' . date('H:i:s', time()) . '
790
						<br /><br />
791
792
793
						<table class="lrPadding c-list crawlerlog">' .
794
                            $this->drawLog_printTableHeader() .
795
                            $code .
796
                        '</table>';
797
                }
798
            } else {	// Otherwise show available sets:
799
                /*
800
                 $setList = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
801
                                'set_id, count(*) as count_value, scheduled',
802
                                'tx_crawler_queue',
803
                                '',
804
                                'set_id, scheduled',
805
                                'scheduled DESC'
806
                            );
807
                */
808
                $setList = $this->queueRepository->getAvailableSets();
809
810
                $code = '
811
					<tr class="bgColor5 tableheader">
812
						<td>' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.setid') . ':</td>
813
						<td>' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.count') . 't:</td>
814
						<td>' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.time') . ':</td>
815
					</tr>
816
				';
817
818
                $cc = 0;
819
                foreach ($setList as $set) {
820
                    $code .= '
821
						<tr class="bgColor' . ($cc % 2 ? '-20' : '-10') . '">
822
							<td><a href="' . htmlspecialchars('index.php?setID=' . $set['set_id']) . '">' . $set['set_id'] . '</a></td>
823
							<td>' . $set['count_value'] . '</td>
824
							<td>' . BackendUtility::dateTimeAge($set['scheduled']) . '</td>
825
						</tr>
826
					';
827
828
                    $cc++;
829
                }
830
831
                $output .= '
832
					<br /><br />
833
					<table class="lrPadding c-list">' .
834
                        $code .
835
                    '</table>';
836
            }
837
        }
838
839
        if ($this->CSVExport) {
840
            $this->outputCsvFile();
841
        }
842
843
        // Return output
844
        return 	$output;
845
    }
846
847
    /**
848
     * Outputs the CSV file and sets the correct headers
849
     */
850
    protected function outputCsvFile()
851
    {
852
        if (!count($this->CSVaccu)) {
853
            $this->addWarningMessage($GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:message.canNotExportEmptyQueueToCsvText'));
854
            return;
855
        }
856
857
        $csvLines = [];
858
859
        // Field names:
860
        reset($this->CSVaccu);
861
        $fieldNames = array_keys(current($this->CSVaccu));
862
        $csvLines[] = CsvUtility::csvValues($fieldNames);
863
864
        // Data:
865
        foreach ($this->CSVaccu as $row) {
866
            $csvLines[] = CsvUtility::csvValues($row);
867
        }
868
869
        // Creating output header:
870
        $mimeType = 'application/octet-stream';
871
        Header('Content-Type: ' . $mimeType);
872
        Header('Content-Disposition: attachment; filename=CrawlerLog.csv');
873
874
        // Printing the content of the CSV lines:
875
        echo implode(chr(13) . chr(10), $csvLines);
876
877
        // Exits:
878
        exit;
879
    }
880
881
    /**
882
     * Create the rows for display of the page tree
883
     * For each page a number of rows are shown displaying GET variable configuration
884
     *
885
     * @param array $pageRow_setId Page row or set-id
886
     * @param string $titleString Title string
887
     * @param int $itemsPerPage Items per Page setting
888
     *
889
     * @return string HTML <tr> content (one or more)
890
     */
891
    public function drawLog_addRows($pageRow_setId, $titleString, $itemsPerPage = 10)
892
    {
893
894
            // If Flush button is pressed, flush tables instead of selecting entries:
895
896
        if (GeneralUtility::_POST('_flush')) {
897
            $doFlush = true;
898
            $doFullFlush = false;
899
        } elseif (GeneralUtility::_POST('_flush_all')) {
900
            $doFlush = true;
901
            $doFullFlush = true;
902
        } else {
903
            $doFlush = false;
904
            $doFullFlush = false;
905
        }
906
907
        // Get result:
908
        if (is_array($pageRow_setId)) {
909
            $res = $this->crawlerController->getLogEntriesForPageId($pageRow_setId['uid'], $this->pObj->MOD_SETTINGS['log_display'], $doFlush, $doFullFlush, intval($itemsPerPage));
910
        } else {
911
            $res = $this->crawlerController->getLogEntriesForSetId($pageRow_setId, $this->pObj->MOD_SETTINGS['log_display'], $doFlush, $doFullFlush, intval($itemsPerPage));
912
        }
913
914
        // Init var:
915
        $colSpan = 9
916
                + ($this->pObj->MOD_SETTINGS['log_resultLog'] ? -1 : 0)
917
                + ($this->pObj->MOD_SETTINGS['log_feVars'] ? 3 : 0);
918
919
        if (count($res)) {
920
            // Traverse parameter combinations:
921
            $c = 0;
922
            $content = '';
923
            foreach ($res as $kk => $vv) {
924
925
                    // Title column:
926
                if (!$c) {
927
                    $titleClm = '<td rowspan="' . count($res) . '">' . $titleString . '</td>';
928
                } else {
929
                    $titleClm = '';
930
                }
931
932
                // Result:
933
                $resLog = $this->getResultLog($vv);
934
935
                $resStatus = $this->getResStatus($vv);
936
                $resFeVars = $this->getResFeVars($vv);
937
938
                // Compile row:
939
                $parameters = unserialize($vv['parameters']);
940
941
                // Put data into array:
942
                $rowData = [];
943
                if ($this->pObj->MOD_SETTINGS['log_resultLog']) {
944
                    $rowData['result_log'] = $resLog;
945
                } else {
946
                    $rowData['scheduled'] = ($vv['scheduled'] > 0) ? BackendUtility::datetime($vv['scheduled']) : ' ' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.immediate');
947
                    $rowData['exec_time'] = $vv['exec_time'] ? BackendUtility::datetime($vv['exec_time']) : '-';
948
                }
949
                $rowData['result_status'] = GeneralUtility::fixed_lgd_cs($resStatus, 50);
950
                $rowData['url'] = '<a href="' . htmlspecialchars($parameters['url']) . '" target="_newWIndow">' . htmlspecialchars($parameters['url']) . '</a>';
951
                $rowData['feUserGroupList'] = $parameters['feUserGroupList'];
952
                $rowData['procInstructions'] = is_array($parameters['procInstructions']) ? implode('; ', $parameters['procInstructions']) : '';
953
                $rowData['set_id'] = $vv['set_id'];
954
955
                if ($this->pObj->MOD_SETTINGS['log_feVars']) {
956
                    $rowData['tsfe_id'] = $resFeVars['id'];
957
                    $rowData['tsfe_gr_list'] = $resFeVars['gr_list'];
958
                    $rowData['tsfe_no_cache'] = $resFeVars['no_cache'];
959
                }
960
961
                $setId = intval(GeneralUtility::_GP('setID'));
962
                $refreshIcon = IconUtility::getIcon('actions-system-refresh', Icon::SIZE_SMALL);
963
964
                // Put rows together:
965
                $content .= '
966
					<tr class="bgColor' . ($c % 2 ? '-20' : '-10') . '">
967
						' . $titleClm . '
968
						<td><a href="' . BackendModuleUtility::getInfoModuleUrl(['qid_details' => $vv['qid'], 'setID' => $setId]) . '">' . htmlspecialchars($vv['qid']) . '</a></td>
969
						<td><a href="' . BackendModuleUtility::getInfoModuleUrl(['qid_read' => $vv['qid'], 'setID' => $setId]) . '">' . $refreshIcon . '</a></td>';
970
                foreach ($rowData as $fKey => $value) {
971
                    if (GeneralUtility::inList('url', $fKey)) {
972
                        $content .= '
973
						<td>' . $value . '</td>';
974
                    } else {
975
                        $content .= '
976
						<td>' . nl2br(htmlspecialchars($value)) . '</td>';
977
                    }
978
                }
979
                $content .= '
980
					</tr>';
981
                $c++;
982
983
                if ($this->CSVExport) {
984
                    // Only for CSV (adding qid and scheduled/exec_time if needed):
985
                    $rowData['result_log'] = implode('// ', explode(chr(10), $resLog));
986
                    $rowData['qid'] = $vv['qid'];
987
                    $rowData['scheduled'] = BackendUtility::datetime($vv['scheduled']);
988
                    $rowData['exec_time'] = $vv['exec_time'] ? BackendUtility::datetime($vv['exec_time']) : '-';
989
                    $this->CSVaccu[] = $rowData;
990
                }
991
            }
992
        } else {
993
994
                // Compile row:
995
            $content = '
996
				<tr class="bgColor-20">
997
					<td>' . $titleString . '</td>
998
					<td colspan="' . $colSpan . '"><em>' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.noentries') . '</em></td>
999
				</tr>';
1000
        }
1001
1002
        return $content;
1003
    }
1004
1005
    /**
1006
     * Find Fe vars
1007
     *
1008
     * @param array $row
1009
     * @return array
1010
     */
1011
    public function getResFeVars($row)
1012
    {
1013
        $feVars = [];
1014
1015
        if ($row['result_data']) {
1016
            $resultData = unserialize($row['result_data']);
1017
            $requestResult = unserialize($resultData['content']);
1018
            $feVars = $requestResult['vars'];
1019
        }
1020
1021
        return $feVars;
1022
    }
1023
1024
    /**
1025
     * Create Table header row (log)
1026
     *
1027
     * @return	string		Table header
1028
     */
1029
    public function drawLog_printTableHeader()
1030
    {
1031
        $content = '
1032
			<tr class="bgColor5 tableheader">
1033
				<td>' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.pagetitle') . ':</td>
1034
				<td>' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.qid') . ':</td>
1035
				<td>&nbsp;</td>' .
1036
                ($this->pObj->MOD_SETTINGS['log_resultLog'] ? '
1037
				<td>' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.resultlog') . ':</td>' : '
1038
				<td>' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.scheduledtime') . ':</td>
1039
				<td>' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.runtime') . ':</td>') . '
1040
				<td>' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.status') . ':</td>
1041
				<td>' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.url') . ':</td>
1042
				<td>' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.groups') . ':</td>
1043
				<td>' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.procinstr') . ':</td>
1044
				<td>' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.setid') . ':</td>' .
1045
                ($this->pObj->MOD_SETTINGS['log_feVars'] ? '
1046
				<td>' . htmlspecialchars('TSFE->id') . '</td>
1047
				<td>' . htmlspecialchars('TSFE->gr_list') . '</td>
1048
				<td>' . htmlspecialchars('TSFE->no_cache') . '</td>' : '') . '
1049
			</tr>';
1050
1051
        return $content;
1052
    }
1053
1054
    /**
1055
     * Extract the log information from the current row and retrive it as formatted string.
1056
     *
1057
     * @param array $resultRow
1058
     *
1059
     * @return string
1060
     */
1061
    protected function getResultLog($resultRow)
1062
    {
1063
        $content = '';
1064
1065
        if (is_array($resultRow) && array_key_exists('result_data', $resultRow)) {
1066
            $requestContent = unserialize($resultRow['result_data']);
1067
            $requestResult = unserialize($requestContent['content']);
1068
1069
            if (is_array($requestResult) && array_key_exists('log', $requestResult)) {
1070
                $content = implode(chr(10), $requestResult['log']);
1071
            }
1072
        }
1073
1074
        return $content;
1075
    }
1076
1077
    public function getResStatus($vv)
1078
    {
1079
        if ($vv['result_data']) {
1080
            $requestContent = unserialize($vv['result_data']);
1081
            $requestResult = unserialize($requestContent['content']);
1082
            if (is_array($requestResult)) {
1083
                if (empty($requestResult['errorlog'])) {
1084
                    $resStatus = 'OK';
1085
                } else {
1086
                    $resStatus = implode("\n", $requestResult['errorlog']);
1087
                }
1088
            } else {
1089
                $resStatus = 'Error: ' . substr(preg_replace('/\s+/', ' ', strip_tags($requestContent['content'])), 0, 10000) . '...';
1090
            }
1091
        } else {
1092
            $resStatus = '-';
1093
        }
1094
        return $resStatus;
1095
    }
1096
1097
    /*****************************
1098
     *
1099
     * CLI status display
1100
     *
1101
     *****************************/
1102
1103
    /**
1104
     * This method is used to show an overview about the active an the finished crawling processes
1105
     *
1106
     * @param void
1107
     * @return string
1108
     */
1109
    protected function drawProcessOverviewAction()
1110
    {
1111
        $this->runRefreshHooks();
1112
1113
        global $BACK_PATH;
1114
        $this->makeCrawlerProcessableChecks();
1115
1116
        $crawler = $this->findCrawler();
1117
        try {
1118
            $this->handleProcessOverviewActions();
1119
        } catch (\Exception $e) {
1120
            $this->addErrorMessage($e->getMessage());
1121
        }
1122
1123
        $offset = intval(GeneralUtility::_GP('offset'));
1124
        $perpage = 20;
1125
1126
        $processRepository = new ProcessRepository();
1127
        $queueRepository = new QueueRepository();
1128
1129
        $mode = $this->pObj->MOD_SETTINGS['processListMode'];
1130
        $where = '';
1131
        if ($mode == 'simple') {
1132
            $where = 'active = 1';
1133
        }
1134
1135
        $allProcesses = $processRepository->findAll('ttl', 'DESC', $perpage, $offset, $where);
0 ignored issues
show
Unused Code introduced by
The call to ProcessRepository::findAll() has too many arguments starting with 'ttl'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
1136
        $allCount = $processRepository->countAll($where);
0 ignored issues
show
Unused Code introduced by
The call to ProcessRepository::countAll() has too many arguments starting with $where.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
1137
1138
        $listView = new ProcessListView();
1139
        $listView->setPageId($this->pObj->id);
1140
        $listView->setIconPath($BACK_PATH . '../typo3conf/ext/crawler/template/process/res/img/');
1141
        $listView->setProcessCollection($allProcesses);
1142
        $listView->setCliPath($this->processManager->getCrawlerCliPath());
1143
        $listView->setIsCrawlerEnabled(!$crawler->getDisabled() && !$this->isErrorDetected);
1144
        $listView->setTotalUnprocessedItemCount($queueRepository->countAllPendingItems());
1145
        $listView->setAssignedUnprocessedItemCount($queueRepository->countAllAssignedPendingItems());
1146
        $listView->setActiveProcessCount($processRepository->countActive());
1147
        $listView->setMaxActiveProcessCount(MathUtility::forceIntegerInRange($this->extensionSettings['processLimit'], 1, 99, 1));
1148
        $listView->setMode($mode);
1149
1150
        $paginationView = new PaginationView();
1151
        $paginationView->setCurrentOffset($offset);
1152
        $paginationView->setPerPage($perpage);
1153
        $paginationView->setTotalItemCount($allCount);
1154
1155
        $output = $listView->render();
1156
1157
        if ($paginationView->getTotalPagesCount() > 1) {
1158
            $output .= ' <br />' . $paginationView->render();
1159
        }
1160
1161
        return $output;
1162
    }
1163
1164
    /**
1165
     * Verify that the crawler is exectuable.
1166
     *
1167
     * @return void
1168
     */
1169
    protected function makeCrawlerProcessableChecks()
1170
    {
1171
        global $LANG;
1172
1173
        /*if ($this->isCrawlerUserAvailable() === false) {
1174
            $this->addErrorMessage($LANG->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:message.noBeUserAvailable'));
1175
        } elseif ($this->isCrawlerUserAdmin() === true) {
1176
            $this->addErrorMessage($LANG->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:message.beUserIsAdmin'));
1177
        }*/
1178
1179
        if ($this->isPhpForkAvailable() === false) {
1180
            $this->addErrorMessage($LANG->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:message.noPhpForkAvailable'));
1181
        }
1182
1183
        $exitCode = 0;
1184
        $out = [];
1185
        exec(escapeshellcmd($this->extensionSettings['phpPath'] . ' -v'), $out, $exitCode);
1186
        if ($exitCode > 0) {
1187
            $this->addErrorMessage(sprintf($LANG->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:message.phpBinaryNotFound'), htmlspecialchars($this->extensionSettings['phpPath'])));
1188
        }
1189
    }
1190
1191
    /**
1192
     * Indicate that the required PHP method "popen" is
1193
     * available in the system.
1194
     *
1195
     * @return boolean
1196
     */
1197
    protected function isPhpForkAvailable()
1198
    {
1199
        return function_exists('popen');
1200
    }
1201
1202
    /**
1203
     * Indicate that the required be_user "_cli_crawler" is
1204
     * global available in the system.
1205
     *
1206
     * @return boolean
1207
     */
1208 1
    protected function isCrawlerUserAvailable()
1209
    {
1210 1
        $isAvailable = false;
1211
1212 1
        $username = '_cli_crawler';
1213
        /** @var QueryResult $user */
1214 1
        $user = $this->backendUserRepository->findByUsername($username);
1215
1216 1
        if ($user->getFirst() instanceof BackendUser) {
1217 1
            $isAvailable = true;
1218
        }
1219
1220 1
        return $isAvailable;
1221
    }
1222
1223
    /**
1224
     * Check is the Crawler user has admin rights or not
1225
     *
1226
     * @return boolean
1227
     */
1228 1
    protected function isCrawlerUserAdmin()
1229
    {
1230 1
        $isAdmin = false;
1231
1232 1
        $username = '_cli_crawler';
1233
        /** @var QueryResult $user */
1234 1
        $user = $this->backendUserRepository->findByUsername($username);
1235 1
        if ($user->getFirst() instanceof BackendUser && $user->getFirst()->getIsAdministrator()) {
1236
            $isAdmin = true;
1237
        }
1238
1239 1
        return $isAdmin;
1240
    }
1241
1242
    /**
1243
     * Method to handle incomming actions of the process overview
1244
     *
1245
     * @throws \Exception
1246
     *
1247
     * @return void
1248
     */
1249
    protected function handleProcessOverviewActions()
1250
    {
1251
        $crawler = $this->findCrawler();
1252
1253
        switch (GeneralUtility::_GP('action')) {
1254
            case 'stopCrawling':
1255
                //set the cli status to disable (all processes will be terminated)
1256
                $crawler->setDisabled(true);
1257
                break;
1258
            case 'resumeCrawling':
1259
                //set the cli status to end (all processes will be terminated)
1260
                $crawler->setDisabled(false);
1261
                break;
1262
            case 'addProcess':
1263
                $handle = $this->processManager->startProcess();
1264
                if ($handle === false) {
1265
                    throw new \Exception($GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.newprocesserror'));
1266
                }
1267
                $this->addNoticeMessage($GLOBALS['LANG']->sL('LLL:EXT:crawler/Resources/Private/Language/locallang.xml:labels.newprocess'));
1268
                break;
1269
        }
1270
    }
1271
1272
    /**
1273
     * Returns the singleton instance of the crawler.
1274
     *
1275
     * @param void
1276
     * @return CrawlerController crawler object
1277
     */
1278
    protected function findCrawler()
1279
    {
1280
        if (!$this->crawlerController instanceof CrawlerController) {
1281
            $this->crawlerController = GeneralUtility::makeInstance(CrawlerController::class);
1282
        }
1283
        return $this->crawlerController;
1284
    }
1285
1286
    /*****************************
1287
     *
1288
     * General Helper Functions
1289
     *
1290
     *****************************/
1291
1292
    /**
1293
     * This method is used to add a message to the internal queue
1294
     *
1295
     * @param  string  the message itself
1296
     * @param  integer message level (-1 = success (default), 0 = info, 1 = notice, 2 = warning, 3 = error)
1297
     *
1298
     * @return void
1299
     */
1300
    private function addMessage($message, $severity = FlashMessage::OK)
1301
    {
1302
        $message = GeneralUtility::makeInstance(
1303
            FlashMessage::class,
1304
            $message,
1305
            '',
1306
            $severity
1307
        );
1308
1309
        // TODO:
1310
        /** @var FlashMessageService $flashMessageService */
1311
        $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
1312
        $flashMessageService->getMessageQueueByIdentifier()->addMessage($message);
1313
    }
1314
1315
    /**
1316
     * Add notice message to the user interface.
1317
     *
1318
     * @param string The message
1319
     *
1320
     * @return void
1321
     */
1322
    protected function addNoticeMessage($message)
1323
    {
1324
        $this->addMessage($message, FlashMessage::NOTICE);
1325
    }
1326
1327
    /**
1328
     * Add error message to the user interface.
1329
     *
1330
     * @param string The message
1331
     *
1332
     * @return void
1333
     */
1334
    protected function addErrorMessage($message)
1335
    {
1336
        $this->isErrorDetected = true;
1337
        $this->addMessage($message, FlashMessage::ERROR);
1338
    }
1339
1340
    /**
1341
     * Add error message to the user interface.
1342
     *
1343
     * NOTE:
1344
     * This method is basesd on TYPO3 4.3 or higher!
1345
     *
1346
     * @param string The message
1347
     *
1348
     * @return void
1349
     */
1350
    protected function addWarningMessage($message)
1351
    {
1352
        $this->addMessage($message, FlashMessage::WARNING);
1353
    }
1354
1355
    /**
1356
     * Create selector box
1357
     *
1358
     * @param	array		$optArray Options key(value) => label pairs
1359
     * @param	string		$name Selector box name
1360
     * @param	string		$value Selector box value (array for multiple...)
1361
     * @param	boolean		$multiple If set, will draw multiple box.
1362
     *
1363
     * @return	string		HTML select element
1364
     */
1365
    public function selectorBox($optArray, $name, $value, $multiple)
1366
    {
1367
        $options = [];
1368
        foreach ($optArray as $key => $val) {
1369
            $options[] = '
1370
				<option value="' . htmlspecialchars($key) . '"' . ((!$multiple && !strcmp($value, $key)) || ($multiple && in_array($key, (array)$value)) ? ' selected="selected"' : '') . '>' . htmlspecialchars($val) . '</option>';
1371
        }
1372
1373
        $output = '<select name="' . htmlspecialchars($name . ($multiple ? '[]' : '')) . '"' . ($multiple ? ' multiple="multiple" size="' . count($options) . '"' : '') . '>' . implode('', $options) . '</select>';
1374
1375
        return $output;
1376
    }
1377
1378
    /**
1379
     * Activate hooks
1380
     *
1381
     * @return	void
1382
     */
1383
    public function runRefreshHooks()
1384
    {
1385
        $crawlerLib = GeneralUtility::makeInstance(CrawlerController::class);
1386
        if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['crawler']['refresh_hooks'])) {
1387
            foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['crawler']['refresh_hooks'] as $objRef) {
1388
                $hookObj = GeneralUtility::makeInstance($objRef);
1389
                if (is_object($hookObj)) {
1390
                    $hookObj->crawler_init($crawlerLib);
1391
                }
1392
            }
1393
        }
1394
    }
1395
}
1396