Completed
Push — develop ( 5cb106...80f130 )
by Dmytro
13:36
created

import.php ➔ pop_index()   A

Complexity

Conditions 6
Paths 9

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
nc 9
nop 1
dl 0
loc 18
rs 9.0444
c 0
b 0
f 0
1
<?php
2
if(!function_exists('run')) {
3
    /**
4
     * @return string
5
     */
6
    function run()
0 ignored issues
show
Coding Style introduced by
run uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
7
    {
8
        $modx = evolutionCMS();
9
        global $_lang;
10
11
        $tbl_site_content = $modx->getDatabase()->getFullTableName('site_content');
12
        $output = '';
13
        $maxtime = $_POST['maxtime'];
14
15
        if (!is_numeric($maxtime)) {
16
            $maxtime = 30;
17
        }
18
19
        @set_time_limit($maxtime);
20
21
        $mtime = microtime();
22
        $mtime = explode(' ', $mtime);
23
        $mtime = $mtime[1] + $mtime[0];
24
        $importstart = $mtime;
25
26
        if ($_POST['reset'] == 'on') {
27
            $modx->getDatabase()->truncate($tbl_site_content);
28
            $modx->getDatabase()->query("ALTER TABLE {$tbl_site_content} AUTO_INCREMENT = 1");
29
        }
30
31
        $parent = (int)$_POST['parent'];
32
33
        if (is_dir(MODX_BASE_PATH . 'temp/import')) {
34
            $filedir = MODX_BASE_PATH . 'temp/import/';
35
        } elseif (is_dir(MODX_BASE_PATH . 'assets/import')) {
36
            $filedir = MODX_BASE_PATH . 'assets/import/';
37
        } else {
38
            $filedir = '';
39
        }
40
41
        $filesfound = 0;
42
43
        $files = getFiles($filedir);
44
        $files = pop_index($files);
45
46
        // no. of files to import
47
        $output .= sprintf('<p>' . $_lang['import_files_found'] . '</p>', $filesfound);
48
49
        // import files
50
        if (0 < count($files)) {
51
            $modx->getDatabase()->update(array('isfolder' => 1), $tbl_site_content, "id='{$parent}'");
52
            importFiles($parent, $filedir, $files, 'root');
53
        }
54
55
        $mtime = microtime();
56
        $mtime = explode(' ', $mtime);
57
        $mtime = $mtime[1] + $mtime[0];
58
        $importend = $mtime;
59
        $totaltime = ($importend - $importstart);
60
        $output .= sprintf('<p>' . $_lang['import_site_time'] . '</p>', round($totaltime, 3));
61
62
        if ($_POST['convert_link'] == 'on') {
63
            convertLink();
64
        }
65
66
        return $output;
67
    }
68
}
69
70
if(!function_exists('importFiles')) {
71
    /**
72
     * @param int $parent
73
     * @param string $filedir
74
     * @param array $files
75
     * @param string $mode
76
     */
77
    function importFiles($parent, $filedir, $files, $mode)
0 ignored issues
show
Coding Style introduced by
importFiles uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
78
    {
79
        $modx = evolutionCMS();
80
        global $_lang, $allowedfiles;
81
        global $search_default, $cache_default, $publish_default;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
82
83
        $tbl_site_content = $modx->getDatabase()->getFullTableName('site_content');
84
        $tbl_system_settings = $modx->getDatabase()->getFullTableName('system_settings');
85
86
        $createdby = $modx->getLoginUserID();
87
        if (!is_array($files)) {
88
            return;
89
        }
90
        if ($_POST['object'] === 'all') {
91
            $modx->config['default_template'] = '0';
92
            $richtext = '0';
93
        } else {
94
            $richtext = '1';
95
        }
96
97
        foreach ($files as $id => $value) {
98
            if (is_array($value)) {
99
                // create folder
100
                $alias = $id;
101
                printf('<span>' . $_lang['import_site_importing_document'] . '</span>', $alias);
102
                $field = array();
103
                $field['type'] = 'document';
104
                $field['contentType'] = 'text/html';
105
                $field['published'] = $publish_default;
106
                $field['parent'] = $parent;
107
                $field['alias'] = $modx->stripAlias($alias);
108
                $field['richtext'] = $richtext;
109
                $field['template'] = $modx->config['default_template'];
110
                $field['searchable'] = $search_default;
111
                $field['cacheable'] = $cache_default;
112
                $field['createdby'] = $createdby;
113
                $field['isfolder'] = 1;
114
                $field['menuindex'] = 1;
115
                $find = false;
116
                foreach (array(
117
                             'index.html',
118
                             'index.htm'
119
                         ) as $filename) {
120
                    $filepath = $filedir . $alias . '/' . $filename;
121
                    if ($find === false && file_exists($filepath)) {
122
                        $file = getFileContent($filepath);
123
                        list($pagetitle, $content, $description) = treatContent($file, $filename, $alias);
124
125
                        $date = filemtime($filepath);
126
                        $field['pagetitle'] = $pagetitle;
127
                        $field['longtitle'] = $pagetitle;
128
                        $field['description'] = $description;
129
                        $field['content'] = $modx->getDatabase()->escape($content);
130
                        $field['createdon'] = $date;
131
                        $field['editedon'] = $date;
132
                        $newid = $modx->getDatabase()->insert($field, $tbl_site_content);
133 View Code Duplication
                        if ($newid) {
134
                            $find = true;
135
                            echo ' - <span class="success">' . $_lang['import_site_success'] . '</span><br />' . "\n";
136
                            importFiles($newid, $filedir . $alias . '/', $value, 'sub');
137
                        } else {
138
                            echo '<span class="fail">' . $_lang["import_site_failed"] . "</span> " . $_lang["import_site_failed_db_error"] . $modx->getDatabase()->getLastError();
139
                            exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The function importFiles() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
140
                        }
141
                    }
142
                }
143
                if ($find === false) {
144
                    $date = time();
145
                    $field['pagetitle'] = '---';
146
                    $field['content'] = '';
147
                    $field['createdon'] = $date;
148
                    $field['editedon'] = $date;
149
                    $field['hidemenu'] = '1';
150
                    $newid = $modx->getDatabase()->insert($field, $tbl_site_content);
151 View Code Duplication
                    if ($newid) {
152
                        $find = true;
153
                        echo ' - <span class="success">' . $_lang['import_site_success'] . '</span><br />' . "\n";
154
                        importFiles($newid, $filedir . $alias . '/', $value, 'sub');
155
                    } else {
156
                        echo '<span class="fail">' . $_lang["import_site_failed"] . "</span> " . $_lang["import_site_failed_db_error"] . $modx->getDatabase()->getLastError();
157
                        exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The function importFiles() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
158
                    }
159
                }
160
            } else {
161
                // create document
162
                if ($mode == 'sub' && $value == 'index.html') {
163
                    continue;
164
                }
165
                $filename = $value;
166
                $fparts = explode('.', $value);
167
                $alias = $fparts[0];
168
                $ext = (count($fparts) > 1) ? $fparts[count($fparts) - 1] : "";
169
                printf("<span>" . $_lang['import_site_importing_document'] . "</span>", $filename);
170
171
                if (!in_array($ext, $allowedfiles)) {
172
                    echo ' - <span class="fail">' . $_lang["import_site_skip"] . '</span><br />' . "\n";
173
                } else {
174
                    $filepath = $filedir . $filename;
175
                    $file = getFileContent($filepath);
176
                    list($pagetitle, $content, $description) = treatContent($file, $filename, $alias);
177
178
                    $date = filemtime($filepath);
179
                    $field = array();
180
                    $field['type'] = 'document';
181
                    $field['contentType'] = 'text/html';
182
                    $field['pagetitle'] = $pagetitle;
183
                    $field['longtitle'] = $pagetitle;
184
                    $field['description'] = $description;
185
                    $field['alias'] = $modx->stripAlias($alias);
186
                    $field['published'] = $publish_default;
187
                    $field['parent'] = $parent;
188
                    $field['content'] = $modx->getDatabase()->escape($content);
189
                    $field['richtext'] = $richtext;
190
                    $field['template'] = $modx->config['default_template'];
191
                    $field['searchable'] = $search_default;
192
                    $field['cacheable'] = $cache_default;
193
                    $field['createdby'] = $createdby;
194
                    $field['createdon'] = $date;
195
                    $field['editedon'] = $date;
196
                    $field['isfolder'] = 0;
197
                    $field['menuindex'] = ($alias == 'index') ? 0 : 2;
198
                    $newid = $modx->getDatabase()->insert($field, $tbl_site_content);
199
                    if ($newid) {
200
                        echo ' - <span class="success">' . $_lang['import_site_success'] . '</span><br />' . "\n";
201
                    } else {
202
                        echo '<span class="fail">' . $_lang["import_site_failed"] . "</span> " . $_lang["import_site_failed_db_error"] . $modx->getDatabase()->getLastError();
203
                        exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The function importFiles() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
204
                    }
205
206
                    $is_site_start = false;
207
                    if ($filename == 'index.html') {
208
                        $is_site_start = true;
209
                    }
210
                    if ($is_site_start == true && $_POST['reset'] == 'on') {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
211
                        $modx->getDatabase()->update(array('setting_value' => $newid), $tbl_system_settings,
212
                            "setting_name='site_start'");
213
                        $modx->getDatabase()->update(array('menuindex' => 0), $tbl_site_content, "id='{$newid}'");
214
                    }
215
                }
216
            }
217
        }
218
    }
219
}
220
221
if(!function_exists('getFiles')) {
222
    /**
223
     * @param string $directory
224
     * @param array $listing
225
     * @param int $count
226
     * @return array
227
     */
228
    function getFiles($directory, $listing = array(), $count = 0)
229
    {
230
        global $_lang;
231
        global $filesfound;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
232
        $dummy = $count;
233
        if (!empty($directory) && $files = scandir($directory)) {
234
            foreach ($files as $file) {
235
                if ($file == '.' || $file == '..') {
236
                    continue;
237
                } elseif ($h = @opendir($directory . $file . "/")) {
238
                    closedir($h);
239
                    $count = -1;
240
                    $listing[$file] = getFiles($directory . $file . "/", array(), $count + 1);
241
                } elseif (strpos($file, '.htm') !== false) {
242
                    $listing[$dummy] = $file;
243
                    $dummy = $dummy + 1;
0 ignored issues
show
Coding Style introduced by
Increment operators should be used where possible; found "$dummy = $dummy + 1;" but expected "$dummy++"
Loading history...
244
                    $filesfound++;
245
                }
246
            }
247
        } else {
248
            echo '<p><span class="fail">' . $_lang["import_site_failed"] . "</span> " . $_lang["import_site_failed_no_open_dir"] . $directory . ".</p>";
249
        }
250
251
        return ($listing);
252
    }
253
}
254
255
if(!function_exists('getFileContent')) {
256
    /**
257
     * @param string $filepath
258
     * @return bool|string
0 ignored issues
show
Documentation introduced by
Should the return type not be null|string?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
259
     */
260
    function getFileContent($filepath)
261
    {
262
        global $_lang;
263
        // get the file
264
        if (!$buffer = file_get_contents($filepath)) {
265
            echo '<p><span class="fail">' . $_lang['import_site_failed'] . "</span> " . $_lang["import_site_failed_no_retrieve_file"] . $filepath . ".</p>";
266
        } else {
267
            return $buffer;
268
        }
269
    }
270
}
271
272
if(!function_exists('pop_index')) {
273
    /**
274
     * @param array $array
275
     * @return array
276
     */
277
    function pop_index($array)
0 ignored issues
show
Coding Style introduced by
As per coding-style, this function should be in camelCase.

CamelCase (...) is the practice of writing compound words or phrases such that
each word or abbreviation begins with a capital letter.

Learn more about camelCase.

Loading history...
278
    {
279
        $new_array = array();
280
        foreach ($array as $k => $v) {
281
            if ($v !== 'index.html' && $v !== 'index.htm') {
282
                $new_array[$k] = $v;
283
            } else {
284
                array_unshift($new_array, $v);
285
            }
286
        }
287
        foreach ($array as $k => $v) {
288
            if (is_array($v)) {
289
                $new_array[$k] = $v;
290
            }
291
        }
292
293
        return $new_array;
294
    }
295
}
296
297
if(!function_exists('treatContent')) {
298
    /**
299
     * @param string $src
300
     * @param string $filename
301
     * @param string $alias
302
     * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<array|string>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
303
     */
304
    function treatContent($src, $filename, $alias)
0 ignored issues
show
Coding Style introduced by
treatContent uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
305
    {
306
        $modx = evolutionCMS();
307
308
        $src = mb_convert_encoding($src, $modx->config['modx_charset'], 'UTF-8,SJIS-win,eucJP-win,SJIS,EUC-JP,ASCII');
309
310 View Code Duplication
        if (preg_match("@<title>(.*)</title>@i", $src, $matches)) {
311
            $pagetitle = ($matches[1] !== '') ? $matches[1] : $filename;
312
            $pagetitle = str_replace('[*pagetitle*]', '', $pagetitle);
313
        } else {
314
            $pagetitle = $alias;
315
        }
316
        if (!$pagetitle) {
317
            $pagetitle = $alias;
318
        }
319
320 View Code Duplication
        if (preg_match('@<meta[^>]+"description"[^>]+content=[\'"](.*)[\'"].+>@i', $src, $matches)) {
321
            $description = ($matches[1] !== '') ? $matches[1] : $filename;
322
            $description = str_replace('[*description*]', '', $description);
323
        } else {
324
            $description = '';
325
        }
326
327
        if ((preg_match("@<body[^>]*>(.*)[^<]+</body>@is", $src, $matches)) && $_POST['object'] == 'body') {
328
            $content = $matches[1];
329
        } else {
330
            $content = $src;
331
            $s = '/(<meta[^>]+charset\s*=)[^>"\'=]+(.+>)/i';
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $s. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
332
            $r = '$1' . $modx->config['modx_charset'] . '$2';
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $r. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
333
            $content = preg_replace($s, $r, $content);
334
            $content = preg_replace('@<title>.*</title>@i', "<title>[*pagetitle*]</title>", $content);
335
        }
336
        $content = str_replace('[*content*]', '[ *content* ]', $content);
337
        $content = trim($content);
338
        $pagetitle = $modx->getDatabase()->escape($pagetitle);
339
340
        return array(
341
            $pagetitle,
342
            $content,
343
            $description
344
        );
345
    }
346
}
347
348
if(!function_exists('convertLink')) {
349
    /**
350
     * @return void
351
     */
352
    function convertLink()
353
    {
354
        $modx = evolutionCMS();
355
        $tbl_site_content = $modx->getDatabase()->getFullTableName('site_content');
356
357
        $rs = $modx->getDatabase()->select('id,content', $tbl_site_content);
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $rs. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
358
        $p = array();
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $p. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
359
        $target = array();
360
        $dir = '';
361
        while ($row = $modx->getDatabase()->getRow($rs)) {
0 ignored issues
show
Bug introduced by
It seems like $rs defined by $modx->getDatabase()->se...nt', $tbl_site_content) on line 357 can also be of type boolean; however, EvolutionCMS\Database::getRow() does only seem to accept object<mysqli_result>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
362
            $id = $row['id'];
363
            $array = explode('<a href=', $row['content']);
364
            $c = 0;
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $c. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
365
            foreach ($array as $v) {
366
                if ($v[0] === '"') {
367
                    $v = substr($v, 1);
368
                    list($href, $v) = explode('"', $v, 2);
369
                    $_ = $href;
370
                    if (strpos($_, $modx->config['site_url']) !== false) {
371
                        $_ = $modx->config['base_url'] . str_replace($modx->config['site_url'], '', $_);
372
                    }
373
                    if ($_[0] === '/') {
374
                        $_ = substr($_, 1);
375
                    }
376
                    $_ = str_replace('/index.html', '.html', $_);
377
                    $level = substr_count($_, '../');
378
                    if (1 < $level) {
379
                        if (!isset($p[$id])) {
380
                            $p[$id] = $modx->getParentIds($id);
381
                        }
382
                        $k = array_keys($p[$id]);
383
                        while (0 < $level) {
384
                            $dir = array_shift($k);
385
                            $level--;
386
                        }
387
                        if ($dir != '') {
388
                            $dir .= '/';
389
                        }
390
                    } else {
391
                        $dir = '';
392
                    }
393
394
                    $_ = trim($_, './');
395
                    if (strpos($_, '/') !== false) {
396
                        $_ = substr($_, strrpos($_, '/'));
397
                    }
398
                    $_ = $dir . str_replace('.html', '', $_);
399
                    if (!isset($target[$_])) {
400
                        $target[$_] = $modx->getIdFromAlias($_);
401
                    }
402
                    $target[$_] = trim($target[$_]);
403
                    if (!empty($target[$_])) {
404
                        $href = '[~' . $target[$_] . '~]';
405
                    }
406
                    $array[$c] = '<a href="' . $href . '"' . $v;
407
                }
408
                $c++;
409
            }
410
            $content = implode('', $array);
411
            $f['content'] = $modx->getDatabase()->escape($content);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$f was never initialized. Although not strictly required by PHP, it is generally a good practice to add $f = 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...
Comprehensibility introduced by
Avoid variables with short names like $f. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
412
            $modx->getDatabase()->update($f, $tbl_site_content, "id='{$id}'");
413
        }
414
    }
415
}
416