Completed
Push — issue/229 ( a96a0e...77baa4 )
by
unknown
03:49
created

tx_crawler_modfunc1::drawURLs_cfgSelectors()   B

Complexity

Conditions 3
Paths 1

Size

Total Lines 76
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 31
nc 1
nop 0
dl 0
loc 76
rs 8.9667
c 0
b 0
f 0

How to fix   Long Method   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
3
/***************************************************************
4
*  Copyright notice
5
*
6
*  (c) 2004-2005 Kasper Skaarhoj ([email protected])
7
*  All rights reserved
8
*
9
*  This script is part of the TYPO3 project. The TYPO3 project is
10
*  free software; you can redistribute it and/or modify
11
*  it under the terms of the GNU General Public License as published by
12
*  the Free Software Foundation; either version 2 of the License, or
13
*  (at your option) any later version.
14
*
15
*  The GNU General Public License can be found at
16
*  http://www.gnu.org/copyleft/gpl.html.
17
*
18
*  This script is distributed in the hope that it will be useful,
19
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
20
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
*  GNU General Public License for more details.
22
*
23
*  This copyright notice MUST APPEAR in all copies of the script!
24
***************************************************************/
25
26
/**
27
 * Class tx_crawler_modfunc1
28
 */
29
class tx_crawler_modfunc1 extends \TYPO3\CMS\Backend\Module\AbstractFunctionModule
30
{
31
    // Internal, dynamic:
32
    public $duplicateTrack = [];
33
    public $submitCrawlUrls = false;
34
    public $downloadCrawlUrls = false;
35
36
    public $scheduledTime = 0;
37
    public $reqMinute = 0;
38
39
    /**
40
     * @var array holds the selection of configuration from the configuration selector box
41
     */
42
    public $incomingConfigurationSelection = [];
43
44
    /**
45
     * @var tx_crawler_lib
46
     */
47
    public $crawlerObj;
48
49
    public $CSVaccu = [];
50
51
    /**
52
     * If true the user requested a CSV export of the queue
53
     *
54
     * @var boolean
55
     */
56
    public $CSVExport = false;
57
58
    public $downloadUrls = [];
59
60
    /**
61
     * Holds the configuration from ext_conf_template loaded by loadExtensionSettings()
62
     *
63
     * @var array
64
     */
65
    protected $extensionSettings = [];
66
67
    /**
68
     * Indicate that an flash message with an error is present.
69
     *
70
     * @var boolean
71
     */
72
    protected $isErrorDetected = false;
73
74
    /**
75
     * the constructor
76
     */
77
    public function __construct()
78
    {
79
        $this->processManager = new tx_crawler_domain_process_manager();
0 ignored issues
show
Bug introduced by
The property processManager 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...
80
    }
81
82
    /**
83
     * Additions to the function menu array
84
     *
85
     * @return	array		Menu array
86
     */
87
    public function modMenu()
88
    {
89
        global $LANG;
90
91
        return [
92
            'depth' => [
93
                0 => $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.depth_0'),
94
                1 => $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.depth_1'),
95
                2 => $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.depth_2'),
96
                3 => $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.depth_3'),
97
                4 => $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.depth_4'),
98
                99 => $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.depth_infi'),
99
            ],
100
            'crawlaction' => [
101
                'start' => $LANG->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.start'),
102
                'log' => $LANG->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.log'),
103
                'multiprocess' => $LANG->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.multiprocess')
104
            ],
105
            'log_resultLog' => '',
106
            'log_feVars' => '',
107
            'processListMode' => '',
108
            'log_display' => [
109
                'all' => $LANG->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.all'),
110
                'pending' => $LANG->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.pending'),
111
                'finished' => $LANG->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.finished')
112
            ],
113
            'itemsPerPage' => [
114
                '5' => $LANG->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.itemsPerPage.5'),
115
                '10' => $LANG->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.itemsPerPage.10'),
116
                '50' => $LANG->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.itemsPerPage.50'),
117
                '0' => $LANG->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.itemsPerPage.0')
118
            ]
119
        ];
120
    }
121
122
    /**
123
     * Load extension settings
124
     *
125
     * @param void
126
     * @return void
127
     */
128
    protected function loadExtensionSettings()
129
    {
130
        $this->extensionSettings = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['crawler']);
131
    }
132
133
    /**
134
     * Main function
135
     *
136
     * @return	string		HTML output
137
     */
138
    public function main()
139
    {
140
        global $LANG, $BACK_PATH;
141
142
        $this->incLocalLang();
143
144
        $this->loadExtensionSettings();
145
        if (empty($this->pObj->MOD_SETTINGS['processListMode'])) {
146
            $this->pObj->MOD_SETTINGS['processListMode'] = 'simple';
147
        }
148
149
        // Set CSS styles specific for this document:
150
        $this->pObj->content = str_replace('/*###POSTCSSMARKER###*/', '
151
			TABLE.c-list TR TD { white-space: nowrap; vertical-align: top; }
152
		', $this->pObj->content);
153
154
        $this->pObj->content .= '<style type="text/css"><!--
155
			table.url-table,
156
			table.param-expanded,
157
			table.crawlerlog {
158
				border-bottom: 1px solid grey;
159
				border-spacing: 0;
160
				border-collapse: collapse;
161
			}
162
			table.crawlerlog td,
163
			table.url-table td {
164
				border: 1px solid lightgrey;
165
				border-bottom: 1px solid grey;
166
				 white-space: nowrap; vertical-align: top;
167
			}
168
		--></style>
169
		<link rel="stylesheet" type="text/css" href="'.$BACK_PATH.'../typo3conf/ext/crawler/template/res.css" />
170
		';
171
172
        // Type function menu:
173
        $h_func = \TYPO3\CMS\Backend\Utility\BackendUtility::getFuncMenu(
174
            $this->pObj->id,
175
            'SET[crawlaction]',
176
            $this->pObj->MOD_SETTINGS['crawlaction'],
177
            $this->pObj->MOD_MENU['crawlaction'],
178
            'index.php'
179
        );
180
181
        /*
182
            // Showing depth-menu in certain cases:
183
        if ($this->pObj->MOD_SETTINGS['crawlaction']!=='cli' && $this->pObj->MOD_SETTINGS['crawlaction']!== 'multiprocess' && ($this->pObj->MOD_SETTINGS['crawlaction']!=='log' || $this->pObj->id))	{
184
            $h_func .= \TYPO3\CMS\Backend\Utility\BackendUtility::getFuncMenu(
185
                $this->pObj->id,
186
                'SET[depth]',
187
                $this->pObj->MOD_SETTINGS['depth'],
188
                $this->pObj->MOD_MENU['depth'],
189
                'index.php'
190
            );
191
        }
192
        */
193
194
        // Additional menus for the log type:
195
        if ($this->pObj->MOD_SETTINGS['crawlaction'] === 'log') {
196
            $h_func .= \TYPO3\CMS\Backend\Utility\BackendUtility::getFuncMenu(
197
                $this->pObj->id,
198
                'SET[depth]',
199
                $this->pObj->MOD_SETTINGS['depth'],
200
                $this->pObj->MOD_MENU['depth'],
201
                'index.php'
202
            );
203
204
            $quiPart = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('qid_details') ? '&qid_details=' . intval(\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('qid_details')) : '';
205
206
            $setId = intval(\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('setID'));
207
208
            $h_func .= '<hr/>'.
209
                    $GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.display').': '.\TYPO3\CMS\Backend\Utility\BackendUtility::getFuncMenu($this->pObj->id, 'SET[log_display]', $this->pObj->MOD_SETTINGS['log_display'], $this->pObj->MOD_MENU['log_display'], 'index.php', '&setID='.$setId) . ' - ' .
210
                    $GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.showresultlog').': '.\TYPO3\CMS\Backend\Utility\BackendUtility::getFuncCheck($this->pObj->id, 'SET[log_resultLog]', $this->pObj->MOD_SETTINGS['log_resultLog'], 'index.php', '&setID='.$setId . $quiPart) . ' - ' .
211
                    $GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.showfevars').': '.\TYPO3\CMS\Backend\Utility\BackendUtility::getFuncCheck($this->pObj->id, 'SET[log_feVars]', $this->pObj->MOD_SETTINGS['log_feVars'], 'index.php', '&setID='.$setId . $quiPart) . ' - ' .
212
                    $GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.itemsPerPage').': ' .
213
                    \TYPO3\CMS\Backend\Utility\BackendUtility::getFuncMenu(
214
                        $this->pObj->id,
215
                        'SET[itemsPerPage]',
216
                        $this->pObj->MOD_SETTINGS['itemsPerPage'],
217
                        $this->pObj->MOD_MENU['itemsPerPage'],
218
                        'index.php'
219
                    );
220
        }
221
222
        $theOutput = $this->pObj->doc->spacer(5);
0 ignored issues
show
Deprecated Code introduced by
The method TYPO3\CMS\Backend\Templa...umentTemplate::spacer() has been deprecated with message: since TYPO3 CMS 7, will be removed in TYPO3 CMS 8

This method has been deprecated. The supplier of the class has supplied an explanatory message.

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

Loading history...
223
        $theOutput .= $this->pObj->doc->section($LANG->getLL('title'), $h_func, 0, 1);
0 ignored issues
show
Documentation introduced by
0 is of type integer, but the function expects a boolean.

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...
224
225
        // Branch based on type:
226
        switch ((string)$this->pObj->MOD_SETTINGS['crawlaction']) {
227
            case 'start':
228
                if (empty($this->pObj->id)) {
229
                    $this->addErrorMessage($GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.noPageSelected'));
230
                } else {
231
                    $theOutput .= $this->pObj->doc->section('', $this->drawURLs(), 0, 1);
0 ignored issues
show
Documentation introduced by
0 is of type integer, but the function expects a boolean.

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...
232
                }
233
                break;
234
            case 'log':
235
                if (empty($this->pObj->id)) {
236
                    $this->addErrorMessage($GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.noPageSelected'));
237
                } else {
238
                    $theOutput .= $this->pObj->doc->section('', $this->drawLog(), 0, 1);
0 ignored issues
show
Documentation introduced by
0 is of type integer, but the function expects a boolean.

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...
239
                }
240
                break;
241
            case 'cli':
242
                $theOutput .= $this->pObj->doc->section('', $this->drawCLIstatus(), 0, 1);
0 ignored issues
show
Bug introduced by
The method drawCLIstatus() does not seem to exist on object<tx_crawler_modfunc1>.

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...
Documentation introduced by
0 is of type integer, but the function expects a boolean.

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...
243
                break;
244
            case 'multiprocess':
245
                $theOutput .= $this->pObj->doc->section('', $this->drawProcessOverviewAction(), 0, 1);
0 ignored issues
show
Documentation introduced by
0 is of type integer, but the function expects a boolean.

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...
246
                break;
247
        }
248
249
        return $theOutput;
250
    }
251
252
    /*******************************
253
     *
254
     * Generate URLs for crawling:
255
     *
256
     ******************************/
257
258
    /**
259
     * Produces a table with overview of the URLs to be crawled for each page
260
     *
261
     * @return	string		HTML output
262
     */
263
    public function drawURLs()
264
    {
265
        global $BACK_PATH, $BE_USER;
266
267
        // Init:
268
        $this->duplicateTrack = [];
269
        $this->submitCrawlUrls = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('_crawl');
0 ignored issues
show
Documentation Bug introduced by
It seems like \TYPO3\CMS\Core\Utility\...lUtility::_GP('_crawl') can also be of type array or string. However, the property $submitCrawlUrls is declared as type boolean. 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...
270
        $this->downloadCrawlUrls = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('_download');
0 ignored issues
show
Documentation Bug introduced by
It seems like \TYPO3\CMS\Core\Utility\...ility::_GP('_download') can also be of type array or string. However, the property $downloadCrawlUrls is declared as type boolean. 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...
271
        $this->makeCrawlerProcessableChecks();
272
273
        switch ((string)\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('tstamp')) {
274
            case 'midnight':
275
                $this->scheduledTime = mktime(0, 0, 0);
276
            break;
277
            case '04:00':
278
                $this->scheduledTime = mktime(0, 0, 0) + 4 * 3600;
279
            break;
280
            case 'now':
281
            default:
282
                $this->scheduledTime = time();
283
            break;
284
        }
285
        // $this->reqMinute = \TYPO3\CMS\Core\Utility\GeneralUtility::intInRange(\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('perminute'),1,10000);
286
        // TODO: check relevance
287
        $this->reqMinute = 1000;
288
289
        $this->incomingConfigurationSelection = \TYPO3\CMS\Core\Utility\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...
290
        $this->incomingConfigurationSelection = is_array($this->incomingConfigurationSelection) ? $this->incomingConfigurationSelection : [''];
291
292
        $this->crawlerObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('tx_crawler_lib');
293
        $this->crawlerObj->setAccessMode('gui');
294
        $this->crawlerObj->setID = \TYPO3\CMS\Core\Utility\GeneralUtility::md5int(microtime());
295
296
        if (empty($this->incomingConfigurationSelection)
297
            || (count($this->incomingConfigurationSelection) == 1 && empty($this->incomingConfigurationSelection[0]))
298
            ) {
299
            $code = '
300
			<tr>
301
				<td colspan="7"><b>'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.noConfigSelected').'</b></td>
302
			</tr>';
303
        } else {
304
            if ($this->submitCrawlUrls) {
305
                $reason = new tx_crawler_domain_reason();
306
                $reason->setReason(tx_crawler_domain_reason::REASON_GUI_SUBMIT);
307
308
                if ($BE_USER instanceof \TYPO3\CMS\Core\Authentication\BackendUserAuthentication) {
309
                    $username = $BE_USER->user['username'];
310
                }
311
                $reason->setDetailText('The user '.$username.' added pages to the crawler queue manually ');
0 ignored issues
show
Bug introduced by
The variable $username 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...
312
313
                tx_crawler_domain_events_dispatcher::getInstance()->post(
314
                    'invokeQueueChange',
315
                                                                            $this->findCrawler()->setID,
316
                                                                            [	'reason' => $reason ]
317
                );
318
            }
319
320
            $code = $this->crawlerObj->getPageTreeAndUrls(
321
                $this->pObj->id,
322
                $this->pObj->MOD_SETTINGS['depth'],
323
                $this->scheduledTime,
324
                $this->reqMinute,
325
                $this->submitCrawlUrls,
326
                $this->downloadCrawlUrls,
327
                [], // Do not filter any processing instructions
328
                $this->incomingConfigurationSelection
329
            );
330
        }
331
332
        $this->downloadUrls = $this->crawlerObj->downloadUrls;
333
        $this->duplicateTrack = $this->crawlerObj->duplicateTrack;
334
335
        $output = '';
336
        if ($code) {
337
            $output .= '<h3>'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.configuration').':</h3>';
338
            $output .= '<input type="hidden" name="id" value="'.intval($this->pObj->id).'" />';
339
340
            if (!$this->submitCrawlUrls) {
341
                $output .= $this->drawURLs_cfgSelectors().'<br />';
342
                $output .= '<input type="submit" name="_update" value="'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.triggerUpdate').'" /> ';
343
                $output .= '<input type="submit" name="_crawl" value="'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.triggerCrawl').'" /> ';
344
                $output .= '<input type="submit" name="_download" value="'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.triggerDownload').'" /><br /><br />';
345
                $output .= $GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.count').': '.count(array_keys($this->duplicateTrack)).'<br />';
346
                $output .= $GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.curtime').': '.date('H:i:s', time()).'<br />';
347
                $output .= '<br />
348
					<table class="lrPadding c-list url-table">'.
349
                        $this->drawURLs_printTableHeader().
350
                        $code.
351
                    '</table>';
352
            } else {
353
                $output .= count(array_keys($this->duplicateTrack)).' '.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.submitted').'. <br /><br />';
354
                $output .= '<input type="submit" name="_" value="'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.continue').'" />';
355
                $output .= '<input type="submit" onclick="this.form.elements[\'SET[crawlaction]\'].value=\'log\';" value="'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.continueinlog').'" />';
356
            }
357
        }
358
359
        // Download Urls to crawl:
360
        if ($this->downloadCrawlUrls) {
361
362
                // Creating output header:
363
            $mimeType = 'application/octet-stream';
364
            Header('Content-Type: '.$mimeType);
365
            Header('Content-Disposition: attachment; filename=CrawlerUrls.txt');
366
367
            // Printing the content of the CSV lines:
368
            echo implode(chr(13).chr(10), $this->downloadUrls);
369
370
            // Exits:
371
            exit;
372
        }
373
374
        // Return output:
375
        return 	$output;
376
    }
377
378
    /**
379
     * Draws the configuration selectors for compiling URLs:
380
     *
381
     * @return	string		HTML table
382
     */
383
    public function drawURLs_cfgSelectors()
384
    {
385
386
            // depth
387
        $cell[] = $this->selectorBox(
0 ignored issues
show
Coding Style Comprehensibility introduced by
$cell was never initialized. Although not strictly required by PHP, it is generally a good practice to add $cell = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
388
            [
389
                0 => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.depth_0'),
390
                1 => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.depth_1'),
391
                2 => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.depth_2'),
392
                3 => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.depth_3'),
393
                4 => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.depth_4'),
394
                99 => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.depth_infi'),
395
            ],
396
            'SET[depth]',
397
            $this->pObj->MOD_SETTINGS['depth'],
398
            0
399
        );
400
        $availableConfigurations = $this->crawlerObj->getConfigurationsForBranch($this->pObj->id, $this->pObj->MOD_SETTINGS['depth']?$this->pObj->MOD_SETTINGS['depth']:0);
401
402
        // Configurations
403
        $cell[] = $this->selectorBox(
404
            empty($availableConfigurations)?[]:array_combine($availableConfigurations, $availableConfigurations),
405
            'configurationSelection',
406
            $this->incomingConfigurationSelection,
407
            1
408
        );
409
410
        // Scheduled time:
411
        $cell[] = $this->selectorBox(
412
            [
413
                'now' => $GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.time.now'),
414
                'midnight' => $GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.time.midnight'),
415
                '04:00' => $GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.time.4am'),
416
            ],
417
            'tstamp',
418
            \TYPO3\CMS\Core\Utility\GeneralUtility::_POST('tstamp'),
419
            0
420
        );
421
422
        // TODO: check relevance
423
        /*
424
            // Requests per minute:
425
        $cell[] = $this->selectorBox(
426
            array(
427
                30 => '[Default]',
428
                1 => '1',
429
                5 => '5',
430
                10 => '10',
431
                20 => '20',
432
                30 => '30',
433
                50 => '50',
434
                100 => '100',
435
                200 => '200',
436
                1000 => '1000',
437
            ),
438
            'SET[perminute]',
439
            $this->pObj->MOD_SETTINGS['perminute'],
440
            0
441
        );
442
        */
443
444
        $output = '
445
			<table class="lrPadding c-list">
446
				<tr class="bgColor5 tableheader">
447
					<td>'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.depth').':</td>
448
					<td>'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.configurations').':</td>
449
					<td>'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.scheduled').':</td>
450
				</tr>
451
				<tr class="bgColor4">
452
					<td valign="top">' . implode('</td>
453
					<td valign="top">', $cell).'</td>
454
				</tr>
455
			</table>';
456
457
        return $output;
458
    }
459
460
    /**
461
     * Create Table header row for URL display
462
     *
463
     * @return	string		Table header
464
     */
465
    public function drawURLs_printTableHeader()
466
    {
467
        $content = '
468
			<tr class="bgColor5 tableheader">
469
				<td>'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.pagetitle').':</td>
470
				<td>'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.key').':</td>
471
				<td>'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.parametercfg').':</td>
472
				<td>'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.values').':</td>
473
				<td>'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.urls').':</td>
474
				<td>'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.options').':</td>
475
				<td>'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.parameters').':</td>
476
			</tr>';
477
478
        return $content;
479
    }
480
481
    /*******************************
482
     *
483
     * Shows log of indexed URLs
484
     *
485
     ******************************/
486
487
    /**
488
     * Shows the log of indexed URLs
489
     *
490
     * @return	string		HTML output
491
     */
492
    public function drawLog()
493
    {
494
        global $BACK_PATH;
495
        $output = '';
496
497
        // Init:
498
        $this->crawlerObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('tx_crawler_lib');
499
        $this->crawlerObj->setAccessMode('gui');
500
        $this->crawlerObj->setID = \TYPO3\CMS\Core\Utility\GeneralUtility::md5int(microtime());
501
502
        $this->CSVExport = \TYPO3\CMS\Core\Utility\GeneralUtility::_POST('_csv');
0 ignored issues
show
Documentation Bug introduced by
It seems like \TYPO3\CMS\Core\Utility\...lUtility::_POST('_csv') can also be of type array or string. However, the property $CSVExport is declared as type boolean. 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...
503
504
        // Read URL:
505
        if (\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('qid_read')) {
506
            $this->crawlerObj->readUrl(intval(\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('qid_read')), true);
507
        }
508
509
        // Look for set ID sent - if it is, we will display contents of that set:
510
        $showSetId = intval(\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('setID'));
511
512
        // Show details:
513
        if (\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('qid_details')) {
514
515
                // Get entry record:
516
            list($q_entry) = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', 'tx_crawler_queue', 'qid='.intval(\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('qid_details')));
517
518
            // Explode values:
519
            $resStatus = $this->getResStatus($q_entry);
520
            $q_entry['parameters'] = unserialize($q_entry['parameters']);
521
            $q_entry['result_data'] = unserialize($q_entry['result_data']);
522
            if (is_array($q_entry['result_data'])) {
523
                $q_entry['result_data']['content'] = unserialize($q_entry['result_data']['content']);
524
            }
525
526
            if (!$this->pObj->MOD_SETTINGS['log_resultLog']) {
527
                unset($q_entry['result_data']['content']['log']);
528
            }
529
530
            // Print rudimentary details:
531
            $output .= '
532
				<br /><br />
533
				<input type="submit" value="' . $GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.back') . '" name="_back" />
534
				<input type="hidden" value="' . $this->pObj->id . '" name="id" />
535
				<input type="hidden" value="' . $showSetId . '" name="setID" />
536
				<br />
537
				Current server time: ' . date('H:i:s', time()) . '<br />' .
538
                'Status: ' . $resStatus . '<br />' .
539
                \TYPO3\CMS\Core\Utility\DebugUtility::viewArray($q_entry);
540
        } else {	// Show list:
541
542
            // If either id or set id, show list:
543
            if ($this->pObj->id || $showSetId) {
544
                if ($this->pObj->id) {
545
                    // Drawing tree:
546
                    $tree = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Backend\Tree\View\PageTreeView');
547
                    $perms_clause = $GLOBALS['BE_USER']->getPagePermsClause(1);
548
                    $tree->init('AND '.$perms_clause);
549
550
                    // Set root row:
551
                    $HTML = \AOE\Crawler\Utility\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...
552
                    $tree->tree[] = [
553
                        'row' => $this->pObj->pageinfo,
554
                        'HTML' => $HTML
555
                    ];
556
557
                    // Get branch beneath:
558
                    if ($this->pObj->MOD_SETTINGS['depth']) {
559
                        $tree->getTree($this->pObj->id, $this->pObj->MOD_SETTINGS['depth'], '');
560
                    }
561
562
                    // Traverse page tree:
563
                    $code = '';
564
                    $count = 0;
565
                    foreach ($tree->tree as $data) {
566
                        $code .= $this->drawLog_addRows(
567
                                    $data['row'],
568
                                    $data['HTML'] . \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordTitle('pages', $data['row'], true),
569
                                    intval($this->pObj->MOD_SETTINGS['itemsPerPage'])
570
                                );
571
                        if (++$count == 1000) {
572
                            break;
573
                        }
574
                    }
575
                } else {
576
                    $code = '';
577
                    $code .= $this->drawLog_addRows(
578
                                $showSetId,
579
                                'Set ID: '.$showSetId
580
                            );
581
                }
582
583
                if ($code) {
584
                    $output .= '
585
						<br /><br />
586
						<input type="submit" value="'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.reloadlist').'" name="_reload" />
587
						<input type="submit" value="'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.downloadcsv').'" name="_csv" />
588
						<input type="submit" value="'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.flushvisiblequeue').'" name="_flush" onclick="return confirm(\''.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.confirmyouresure').'\');" />
589
						<input type="submit" value="'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.flushfullqueue').'" name="_flush_all" onclick="return confirm(\''.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.confirmyouresure').'\');" />
590
						<input type="hidden" value="'.$this->pObj->id.'" name="id" />
591
						<input type="hidden" value="'.$showSetId.'" name="setID" />
592
						<br />
593
						'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.curtime').': '.date('H:i:s', time()).'
594
						<br /><br />
595
596
597
						<table class="lrPadding c-list crawlerlog">'.
598
                            $this->drawLog_printTableHeader().
599
                            $code.
600
                        '</table>';
601
                }
602
            } else {	// Otherwise show available sets:
603
                $setList = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
604
                                'set_id, count(*) as count_value, scheduled',
605
                                'tx_crawler_queue',
606
                                '',
607
                                'set_id, scheduled',
608
                                'scheduled DESC'
609
                            );
610
611
                $code = '
612
					<tr class="bgColor5 tableheader">
613
						<td>'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.setid').':</td>
614
						<td>'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.count').'t:</td>
615
						<td>'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.time').':</td>
616
					</tr>
617
				';
618
619
                $cc = 0;
620
                foreach ($setList as $set) {
621
                    $code .= '
622
						<tr class="bgColor'.($cc % 2 ? '-20':'-10').'">
623
							<td><a href="'.htmlspecialchars('index.php?setID='.$set['set_id']).'">'.$set['set_id'].'</a></td>
624
							<td>'.$set['count_value'].'</td>
625
							<td>'.\TYPO3\CMS\Backend\Utility\BackendUtility::dateTimeAge($set['scheduled']).'</td>
626
						</tr>
627
					';
628
629
                    $cc++;
630
                }
631
632
                $output .= '
633
					<br /><br />
634
					<table class="lrPadding c-list">'.
635
                        $code.
636
                    '</table>';
637
            }
638
        }
639
640
        if ($this->CSVExport) {
641
            $this->outputCsvFile();
642
        }
643
644
        // Return output
645
        return 	$output;
646
    }
647
648
    /**
649
     * Outputs the CSV file and sets the correct headers
650
     */
651
    protected function outputCsvFile()
652
    {
653
        if (!count($this->CSVaccu)) {
654
            $this->addWarningMessage($GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:message.canNotExportEmptyQueueToCsvText'));
655
            return;
656
        }
657
658
        $csvLines = [];
659
660
        // Field names:
661
        reset($this->CSVaccu);
662
        $fieldNames = array_keys(current($this->CSVaccu));
663
        $csvLines[] = \TYPO3\CMS\Core\Utility\GeneralUtility::csvValues($fieldNames);
664
665
        // Data:
666
        foreach ($this->CSVaccu as $row) {
667
            $csvLines[] = \TYPO3\CMS\Core\Utility\GeneralUtility::csvValues($row);
668
        }
669
670
        // Creating output header:
671
        $mimeType = 'application/octet-stream';
672
        Header('Content-Type: '.$mimeType);
673
        Header('Content-Disposition: attachment; filename=CrawlerLog.csv');
674
675
        // Printing the content of the CSV lines:
676
        echo implode(chr(13).chr(10), $csvLines);
677
678
        // Exits:
679
        exit;
680
    }
681
682
    /**
683
     * Create the rows for display of the page tree
684
     * For each page a number of rows are shown displaying GET variable configuration
685
     *
686
     * @param	array		Page row or set-id
687
     * @param	string		Title string
688
     * @param	int			Items per Page setting
689
     * @return	string		HTML <tr> content (one or more)
690
     */
691
    public function drawLog_addRows($pageRow_setId, $titleString, $itemsPerPage = 10)
692
    {
693
694
            // If Flush button is pressed, flush tables instead of selecting entries:
695
696
        if (\TYPO3\CMS\Core\Utility\GeneralUtility::_POST('_flush')) {
697
            $doFlush = true;
698
            $doFullFlush = false;
699
        } elseif (\TYPO3\CMS\Core\Utility\GeneralUtility::_POST('_flush_all')) {
700
            $doFlush = true;
701
            $doFullFlush = true;
702
        } else {
703
            $doFlush = false;
704
            $doFullFlush = false;
705
        }
706
707
        // Get result:
708
        if (is_array($pageRow_setId)) {
709
            $res = $this->crawlerObj->getLogEntriesForPageId($pageRow_setId['uid'], $this->pObj->MOD_SETTINGS['log_display'], $doFlush, $doFullFlush, intval($itemsPerPage));
710
        } else {
711
            $res = $this->crawlerObj->getLogEntriesForSetId($pageRow_setId, $this->pObj->MOD_SETTINGS['log_display'], $doFlush, $doFullFlush, intval($itemsPerPage));
712
        }
713
714
        // Init var:
715
        $colSpan = 9
716
                + ($this->pObj->MOD_SETTINGS['log_resultLog'] ? -1 : 0)
717
                + ($this->pObj->MOD_SETTINGS['log_feVars'] ? 3 : 0);
718
719
        if (count($res)) {
720
            // Traverse parameter combinations:
721
            $c = 0;
722
            $content = '';
723
            foreach ($res as $kk => $vv) {
724
725
                    // Title column:
726
                if (!$c) {
727
                    $titleClm = '<td rowspan="'.count($res).'">'.$titleString.'</td>';
728
                } else {
729
                    $titleClm = '';
730
                }
731
732
                // Result:
733
                $resLog = $this->getResultLog($vv);
734
735
                $resStatus = $this->getResStatus($vv);
736
                $resFeVars = $this->getResFeVars($vv);
737
738
                // Compile row:
739
                $parameters = unserialize($vv['parameters']);
740
741
                // Put data into array:
742
                $rowData = [];
743
                if ($this->pObj->MOD_SETTINGS['log_resultLog']) {
744
                    $rowData['result_log'] = $resLog;
745
                } else {
746
                    $rowData['scheduled'] = ($vv['scheduled'] > 0) ? \TYPO3\CMS\Backend\Utility\BackendUtility::datetime($vv['scheduled']) : ' '.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.immediate');
747
                    $rowData['exec_time'] = $vv['exec_time'] ? \TYPO3\CMS\Backend\Utility\BackendUtility::datetime($vv['exec_time']) : '-';
748
                }
749
                $rowData['result_status'] = \TYPO3\CMS\Core\Utility\GeneralUtility::fixed_lgd_cs($resStatus, 50);
750
                $rowData['url'] = '<a href="'.htmlspecialchars($parameters['url']).'" target="_newWIndow">'.htmlspecialchars($parameters['url']).'</a>';
751
                $rowData['feUserGroupList'] = $parameters['feUserGroupList'];
752
                $rowData['procInstructions'] = is_array($parameters['procInstructions']) ? implode('; ', $parameters['procInstructions']) : '';
753
                $rowData['set_id'] = $vv['set_id'];
754
755
                if ($this->pObj->MOD_SETTINGS['log_feVars']) {
756
                    $rowData['tsfe_id'] = $resFeVars['id'];
757
                    $rowData['tsfe_gr_list'] = $resFeVars['gr_list'];
758
                    $rowData['tsfe_no_cache'] = $resFeVars['no_cache'];
759
                }
760
761
                $setId = intval(\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('setID'));
762
763
                $refreshIcon = $GLOBALS['BACK_PATH'] . 'gfx/refresh_n.gif';
764
                if (version_compare(TYPO3_version, '7.0', '>=')) {
765
                    $refreshIcon = $GLOBALS['BACK_PATH'] . 'sysext/t3skin/extjs/images/grid/refresh.gif';
766
                }
767
768
                // Put rows together:
769
                $content .= '
770
					<tr class="bgColor'.($c % 2 ? '-20':'-10').'">
771
						'.$titleClm.'
772
						<td><a href="' . $this->getModuleUrl(['qid_details' => $vv['qid'], 'setID' => $setId]) . '">'.htmlspecialchars($vv['qid']).'</a></td>
773
						<td><a href="' . $this->getModuleUrl(['qid_read' => $vv['qid'], 'setID' => $setId]) . '"><img src="' . $refreshIcon . '" width="14" hspace="1" vspace="2" height="14" border="0" title="'.htmlspecialchars('Read').'" alt="" /></a></td>';
774
                foreach ($rowData as $fKey => $value) {
775
                    if (\TYPO3\CMS\Core\Utility\GeneralUtility::inList('url', $fKey)) {
776
                        $content .= '
777
						<td>'.$value.'</td>';
778
                    } else {
779
                        $content .= '
780
						<td>'.nl2br(htmlspecialchars($value)).'</td>';
781
                    }
782
                }
783
                $content .= '
784
					</tr>';
785
                $c++;
786
787
                if ($this->CSVExport) {
788
                    // Only for CSV (adding qid and scheduled/exec_time if needed):
789
                    $rowData['result_log'] = implode('// ', explode(chr(10), $resLog));
790
                    $rowData['qid'] = $vv['qid'];
791
                    $rowData['scheduled'] = \TYPO3\CMS\Backend\Utility\BackendUtility::datetime($vv['scheduled']);
792
                    $rowData['exec_time'] = $vv['exec_time'] ? \TYPO3\CMS\Backend\Utility\BackendUtility::datetime($vv['exec_time']) : '-';
793
                    $this->CSVaccu[] = $rowData;
794
                }
795
            }
796
        } else {
797
798
                // Compile row:
799
            $content = '
800
				<tr class="bgColor-20">
801
					<td>'.$titleString.'</td>
802
					<td colspan="'.$colSpan.'"><em>'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.noentries').'</em></td>
803
				</tr>';
804
        }
805
806
        return $content;
807
    }
808
809
    /**
810
     * Find Fe vars
811
     *
812
     * @param array $row
813
     * @return array
814
     */
815
    public function getResFeVars($row)
816
    {
817
        $feVars = [];
818
819
        if ($row['result_data']) {
820
            $resultData = unserialize($row['result_data']);
821
            $requestResult = unserialize($resultData['content']);
822
            $feVars = $requestResult['vars'];
823
        }
824
825
        return $feVars;
826
    }
827
828
    /**
829
     * Create Table header row (log)
830
     *
831
     * @return	string		Table header
832
     */
833
    public function drawLog_printTableHeader()
834
    {
835
        $content = '
836
			<tr class="bgColor5 tableheader">
837
				<td>'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.pagetitle').':</td>
838
				<td>'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.qid').':</td>
839
				<td>&nbsp;</td>'.
840
                ($this->pObj->MOD_SETTINGS['log_resultLog'] ? '
841
				<td>'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.resultlog').':</td>' : '
842
				<td>'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.scheduledtime').':</td>
843
				<td>'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.runtime').':</td>').'
844
				<td>'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.status').':</td>
845
				<td>'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.url').':</td>
846
				<td>'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.groups').':</td>
847
				<td>'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.procinstr').':</td>
848
				<td>'.$GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.setid').':</td>'.
849
                ($this->pObj->MOD_SETTINGS['log_feVars'] ? '
850
				<td>'.htmlspecialchars('TSFE->id').'</td>
851
				<td>'.htmlspecialchars('TSFE->gr_list').'</td>
852
				<td>'.htmlspecialchars('TSFE->no_cache').'</td>' : '').'
853
			</tr>';
854
855
        return $content;
856
    }
857
858
    /**
859
     * Extract the log information from the current row and retrive it as formatted string.
860
     *
861
     * @param array $resultRow
862
     *
863
     * @return string
864
     */
865
    protected function getResultLog($resultRow)
866
    {
867
        $content = '';
868
869
        if (is_array($resultRow) && array_key_exists('result_data', $resultRow)) {
870
            $requestContent = unserialize($resultRow['result_data']);
871
            $requestResult = unserialize($requestContent['content']);
872
873
            if (is_array($requestResult) && array_key_exists('log', $requestResult)) {
874
                $content = implode(chr(10), $requestResult['log']);
875
            }
876
        }
877
878
        return $content;
879
    }
880
881
    public function getResStatus($vv)
882
    {
883
        if ($vv['result_data']) {
884
            $requestContent = unserialize($vv['result_data']);
885
            $requestResult = unserialize($requestContent['content']);
886
            if (is_array($requestResult)) {
887
                if (empty($requestResult['errorlog'])) {
888
                    $resStatus = 'OK';
889
                } else {
890
                    $resStatus = implode("\n", $requestResult['errorlog']);
891
                }
892
                $resLog = is_array($requestResult['log']) ?  implode(chr(10), $requestResult['log']) : '';
0 ignored issues
show
Unused Code introduced by
$resLog is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
893
            } else {
894
                $resStatus = 'Error: '.substr(preg_replace('/\s+/', ' ', strip_tags($requestContent['content'])), 0, 10000).'...';
895
            }
896
        } else {
897
            $resStatus = '-';
898
        }
899
        return $resStatus;
900
    }
901
902
    /*****************************
903
     *
904
     * CLI status display
905
     *
906
     *****************************/
907
908
    /**
909
     * This method is used to show an overview about the active an the finished crawling processes
910
     *
911
     * @param void
912
     * @return string
913
     */
914
    protected function drawProcessOverviewAction()
915
    {
916
        $this->runRefreshHooks();
917
918
        global $BACK_PATH;
919
        $this->makeCrawlerProcessableChecks();
920
921
        $crawler = $this->findCrawler();
922
        try {
923
            $this->handleProcessOverviewActions();
924
        } catch (Exception $e) {
925
            $this->addErrorMessage($e->getMessage());
926
        }
927
928
        $offset = intval(\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('offset'));
929
        $perpage = 20;
930
931
        $processRepository = new tx_crawler_domain_process_repository();
932
        $queueRepository = new tx_crawler_domain_queue_repository();
933
934
        $mode = $this->pObj->MOD_SETTINGS['processListMode'];
935
        if ($mode == 'detail') {
936
            $where = '';
937
        } elseif ($mode == 'simple') {
938
            $where = 'active = 1';
939
        }
940
941
        $allProcesses = $processRepository->findAll('ttl', 'DESC', $perpage, $offset, $where);
0 ignored issues
show
Bug introduced by
The variable $where 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...
942
        $allCount = $processRepository->countAll($where);
943
944
        $listView = new tx_crawler_view_process_list();
945
        $listView->setPageId($this->pObj->id);
946
        $listView->setIconPath($BACK_PATH.'../typo3conf/ext/crawler/template/process/res/img/');
947
        $listView->setProcessCollection($allProcesses);
948
        $listView->setCliPath($this->processManager->getCrawlerCliPath());
949
        $listView->setIsCrawlerEnabled(!$crawler->getDisabled() && !$this->isErrorDetected);
950
        $listView->setTotalUnprocessedItemCount($queueRepository->countAllPendingItems());
951
        $listView->setAssignedUnprocessedItemCount($queueRepository->countAllAssignedPendingItems());
952
        $listView->setActiveProcessCount($processRepository->countActive());
953
        $listView->setMaxActiveProcessCount(tx_crawler_api::forceIntegerInRange($this->extensionSettings['processLimit'], 1, 99, 1));
954
        $listView->setMode($mode);
955
956
        $paginationView = new tx_crawler_view_pagination();
957
        $paginationView->setCurrentOffset($offset);
958
        $paginationView->setPerPage($perpage);
959
        $paginationView->setTotalItemCount($allCount);
960
961
        $output = $listView->render();
962
963
        if ($paginationView->getTotalPagesCount() > 1) {
964
            $output .= ' <br />'.$paginationView->render();
965
        }
966
967
        return $output;
968
    }
969
970
    /**
971
     * Verify that the crawler is exectuable.
972
     *
973
     * @return void
974
     */
975
    protected function makeCrawlerProcessableChecks()
976
    {
977
        global $LANG;
978
979
        if ($this->isCrawlerUserAvailable() === false) {
980
            $this->addErrorMessage($LANG->sL('LLL:EXT:crawler/modfunc1/locallang.xml:message.noBeUserAvailable'));
981
        } elseif ($this->isCrawlerUserNotAdmin() === false) {
982
            $this->addErrorMessage($LANG->sL('LLL:EXT:crawler/modfunc1/locallang.xml:message.beUserIsAdmin'));
983
        }
984
985
        if ($this->isPhpForkAvailable() === false) {
986
            $this->addErrorMessage($LANG->sL('LLL:EXT:crawler/modfunc1/locallang.xml:message.noPhpForkAvailable'));
987
        }
988
989
        $exitCode = 0;
990
        $out = [];
991
        exec(escapeshellcmd($this->extensionSettings['phpPath'] . ' -v'), $out, $exitCode);
992
        if ($exitCode > 0) {
993
            $this->addErrorMessage(sprintf($LANG->sL('LLL:EXT:crawler/modfunc1/locallang.xml:message.phpBinaryNotFound'), htmlspecialchars($this->extensionSettings['phpPath'])));
994
        }
995
    }
996
997
    /**
998
     * Indicate that the required PHP method "popen" is
999
     * available in the system.
1000
     *
1001
     * @return boolean
1002
     */
1003
    protected function isPhpForkAvailable()
1004
    {
1005
        return function_exists('popen');
1006
    }
1007
1008
    /**
1009
     * Indicate that the required be_user "_cli_crawler" is
1010
     * global available in the system.
1011
     *
1012
     * @return boolean
1013
     */
1014
    protected function isCrawlerUserAvailable()
1015
    {
1016
        $isAvailable = false;
1017
        $userArray = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordsByField('be_users', 'username', '_cli_crawler');
1018
1019
        if (is_array($userArray)) {
1020
            $isAvailable = true;
1021
        }
1022
1023
        return $isAvailable;
1024
    }
1025
1026
    /**
1027
     * Indicate that the required be_user "_cli_crawler" is
1028
     * has no admin rights.
1029
     *
1030
     * @return boolean
1031
     */
1032
    protected function isCrawlerUserNotAdmin()
1033
    {
1034
        $isAvailable = false;
1035
        $userArray = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordsByField('be_users', 'username', '_cli_crawler');
1036
1037
        if (is_array($userArray) && $userArray[0]['admin'] == 0) {
1038
            $isAvailable = true;
1039
        }
1040
1041
        return $isAvailable;
1042
    }
1043
1044
    /**
1045
     * Method to handle incomming actions of the process overview
1046
     *
1047
     * @return void
1048
     * @throws Exception
1049
     */
1050
    protected function handleProcessOverviewActions()
1051
    {
1052
        $crawler = $this->findCrawler();
1053
1054
        switch (\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('action')) {
1055
            case 'stopCrawling':
1056
                //set the cli status to disable (all processes will be terminated)
1057
                $crawler->setDisabled(true);
1058
                break;
1059
            case 'resumeCrawling':
1060
                //set the cli status to end (all processes will be terminated)
1061
                $crawler->setDisabled(false);
1062
                break;
1063
            case 'addProcess':
1064
                $handle = $this->processManager->startProcess();
1065
                if ($handle === false) {
1066
                    throw new Exception($GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.newprocesserror'));
1067
                }
1068
                $this->addNoticeMessage($GLOBALS['LANG']->sL('LLL:EXT:crawler/modfunc1/locallang.xml:labels.newprocess'));
1069
                break;
1070
        }
1071
    }
1072
1073
    /**
1074
     * Returns the singleton instance of the crawler.
1075
     *
1076
     * @param void
1077
     * @return tx_crawler_lib crawler object
1078
     */
1079
    protected function findCrawler()
1080
    {
1081
        if (!$this->crawlerObj instanceof tx_crawler_lib) {
0 ignored issues
show
Bug introduced by
The class tx_crawler_lib does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
1082
            $this->crawlerObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('tx_crawler_lib');
1083
        }
1084
        return $this->crawlerObj;
1085
    }
1086
1087
    /*****************************
1088
     *
1089
     * General Helper Functions
1090
     *
1091
     *****************************/
1092
1093
    /**
1094
     * This method is used to add a message to the internal queue
1095
     *
1096
     * NOTE:
1097
     * This method is basesd on TYPO3 4.3 or higher!
1098
     *
1099
     * @param  string  the message itself
1100
     * @param  integer message level (-1 = success (default), 0 = info, 1 = notice, 2 = warning, 3 = error)
1101
     *
1102
     * @return void
1103
     */
1104
    private function addMessage($message, $severity = \TYPO3\CMS\Core\Messaging\FlashMessage::OK)
1105
    {
1106
        $message = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
1107
            'TYPO3\CMS\Core\Messaging\FlashMessage',
1108
            $message,
1109
            '',
1110
            $severity
1111
        );
1112
1113
        // TODO:
1114
        /** @var \TYPO3\CMS\Core\Messaging\FlashMessageService $flashMessageService */
1115
        $flashMessageService = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessageService::class);
1116
        $flashMessageService->getMessageQueueByIdentifier()->addMessage($message);
1117
    }
1118
1119
    /**
1120
     * Add notice message to the user interface.
1121
     *
1122
     * NOTE:
1123
     * This method is basesd on TYPO3 4.3 or higher!
1124
     *
1125
     * @param string The message
1126
     *
1127
     * @return void
1128
     */
1129
    protected function addNoticeMessage($message)
1130
    {
1131
        $this->addMessage($message, \TYPO3\CMS\Core\Messaging\FlashMessage::NOTICE);
1132
    }
1133
1134
    /**
1135
     * Add error message to the user interface.
1136
     *
1137
     * NOTE:
1138
     * This method is basesd on TYPO3 4.3 or higher!
1139
     *
1140
     * @param string The message
1141
     *
1142
     * @return void
1143
     */
1144
    protected function addErrorMessage($message)
1145
    {
1146
        $this->isErrorDetected = true;
1147
        $this->addMessage($message, \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR);
1148
    }
1149
1150
    /**
1151
     * Add error message to the user interface.
1152
     *
1153
     * NOTE:
1154
     * This method is basesd on TYPO3 4.3 or higher!
1155
     *
1156
     * @param string The message
1157
     *
1158
     * @return void
1159
     */
1160
    protected function addWarningMessage($message)
1161
    {
1162
        $this->addMessage($message, \TYPO3\CMS\Core\Messaging\FlashMessage::WARNING);
1163
    }
1164
1165
    /**
1166
     * Create selector box
1167
     *
1168
     * @param	array		Options key(value) => label pairs
1169
     * @param	string		Selector box name
1170
     * @param	string		Selector box value (array for multiple...)
1171
     * @param	boolean		If set, will draw multiple box.
1172
     * @return	string		HTML select element
1173
     */
1174
    public function selectorBox($optArray, $name, $value, $multiple)
1175
    {
1176
        $options = [];
1177
        foreach ($optArray as $key => $val) {
1178
            $options[] = '
1179
				<option value="'.htmlspecialchars($key).'"'.((!$multiple && !strcmp($value, $key)) || ($multiple && in_array($key, (array)$value))?' selected="selected"':'').'>'.htmlspecialchars($val).'</option>';
1180
        }
1181
1182
        $output = '<select name="'.htmlspecialchars($name.($multiple?'[]':'')).'"'.($multiple ? ' multiple="multiple" size="'.count($options).'"' : '').'>'.implode('', $options).'</select>';
1183
1184
        return $output;
1185
    }
1186
1187
    /**
1188
     * Activate hooks
1189
     *
1190
     * @return	void
1191
     */
1192
    public function runRefreshHooks()
1193
    {
1194
        $crawlerLib = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('tx_crawler_lib');
1195
        if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['crawler']['refresh_hooks'])) {
1196
            foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['crawler']['refresh_hooks'] as $objRef) {
1197
                $hookObj = &\TYPO3\CMS\Core\Utility\GeneralUtility::getUserObj($objRef);
1198
                if (is_object($hookObj)) {
1199
                    $hookObj->crawler_init($crawlerLib);
1200
                }
1201
            }
1202
        }
1203
    }
1204
1205
    /**
1206
     * Returns the URL to the current module, including $_GET['id'].
1207
     *
1208
     * @param array $urlParameters optional parameters to add to the URL
1209
     * @return string
1210
     */
1211
    protected function getModuleUrl(array $urlParameters = [])
1212
    {
1213
        if ($this->pObj->id) {
1214
            $urlParameters = array_merge($urlParameters, [
1215
                'id' => $this->pObj->id
1216
            ]);
1217
        }
1218
        return \TYPO3\CMS\Backend\Utility\BackendUtility::getModuleUrl(\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('M'), $urlParameters);
0 ignored issues
show
Bug introduced by
It seems like \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('M') targeting TYPO3\CMS\Core\Utility\GeneralUtility::_GP() can also be of type array or null; however, TYPO3\CMS\Backend\Utilit...Utility::getModuleUrl() 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...
1219
    }
1220
}
1221
1222
if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/crawler/modfunc1/class.tx_crawler_modfunc1.php']) {
1223
    include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/crawler/modfunc1/class.tx_crawler_modfunc1.php']);
1224
}
1225