Completed
Push — master ( 7c306d...d9f77c )
by Yannick
24:48
created

getAllPhpFiles()   C

Complexity

Conditions 7
Paths 12

Size

Total Lines 31
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 21
nc 12
nop 2
dl 0
loc 31
rs 6.7272
c 1
b 0
f 0
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Symfony\Component\Filesystem\Filesystem;
5
6
/**
7
 * This is the file manage library for Chamilo.
8
 * Include/require it in your code to use its functionality.
9
 *
10
 * @package chamilo.library
11
 */
12
13
/**
14
 * Cheks a file or a directory actually exist at this location.
15
 *
16
 * @author Hugues Peeters <[email protected]>
17
 *
18
 * @param string $file_path Path of the presume existing file or dir
19
 *
20
 * @return bool TRUE if the file or the directory exists or FALSE otherwise
21
 */
22
function check_name_exist($file_path)
23
{
24
    clearstatcache();
25
    $save_dir = getcwd();
26
    if (!is_dir(dirname($file_path))) {
27
        return false;
28
    }
29
    chdir(dirname($file_path));
30
    $file_name = basename($file_path);
31
32
    if (file_exists($file_name)) {
33
        chdir($save_dir);
34
35
        return true;
36
    } else {
37
        chdir($save_dir);
38
39
        return false;
40
    }
41
}
42
43
/**
44
 * Deletes a file or a directory.
45
 *
46
 * @author - Hugues Peeters
47
 *
48
 * @param  $file (String) - the path of file or directory to delete
49
 *
50
 * @return bool - true if the delete succeed, false otherwise
51
 *
52
 * @see    - delete() uses check_name_exist() and removeDir() functions
53
 */
54
function my_delete($file)
55
{
56
    if (check_name_exist($file)) {
57
        if (is_file($file)) { // FILE CASE
58
            unlink($file);
59
60
            return true;
61
        } elseif (is_dir($file)) { // DIRECTORY CASE
62
            removeDir($file);
63
64
            return true;
65
        }
66
    }
67
    return false; // no file or directory to delete
68
}
69
70
/**
71
 * Removes a directory recursively.
72
 *
73
 * @returns true if OK, otherwise false
74
 *
75
 * @author Amary <[email protected]> (from Nexen.net)
76
 * @author Olivier Brouckaert <[email protected]>
77
 *
78
 * @param string $dir directory to remove
79
 */
80
function removeDir($dir)
81
{
82
    if (!@$opendir = opendir($dir)) {
83
        return false;
84
    }
85
86
    while ($readdir = readdir($opendir)) {
0 ignored issues
show
Bug introduced by
It seems like $opendir can also be of type false; however, parameter $dir_handle of readdir() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

86
    while ($readdir = readdir(/** @scrutinizer ignore-type */ $opendir)) {
Loading history...
87
        if ($readdir != '..' && $readdir != '.') {
88
            if (is_file($dir.'/'.$readdir)) {
89
                if (!@unlink($dir.'/'.$readdir)) {
90
                    return false;
91
                }
92
            } elseif (is_dir($dir.'/'.$readdir)) {
93
                if (!removeDir($dir.'/'.$readdir)) {
94
                    return false;
95
                }
96
            }
97
        }
98
    }
99
100
    closedir($opendir);
0 ignored issues
show
Bug introduced by
It seems like $opendir can also be of type false; however, parameter $dir_handle of closedir() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

100
    closedir(/** @scrutinizer ignore-type */ $opendir);
Loading history...
101
102
    if (!@rmdir($dir)) {
103
        return false;
104
    }
105
106
    return true;
107
}
108
109
/**
110
 * Return true if folder is empty.
111
 *
112
 * @author [email protected]
113
 *
114
 * @param string $in_folder folder path on disk
115
 *
116
 * @return int 1 if folder is empty, 0 otherwise
117
 */
118
function folder_is_empty($in_folder)
119
{
120
    $folder_is_empty = 0;
121
    if (is_dir($in_folder)) {
122
        $tab_folder_content = scandir($in_folder);
123
        if ((
124
            count($tab_folder_content) == 2 &&
125
            in_array(".", $tab_folder_content) &&
126
            in_array("..", $tab_folder_content)
127
            ) ||
128
            (count($tab_folder_content) < 2)
129
        ) {
130
            $folder_is_empty = 1;
131
        }
132
    }
133
134
    return $folder_is_empty;
135
}
136
137
/**
138
 * Renames a file or a directory.
139
 *
140
 * @author Hugues Peeters <[email protected]>
141
 *
142
 * @param string $file_path     complete path of the file or the directory
143
 * @param string $new_file_name new name for the file or the directory
144
 *
145
 * @return bool true if succeed, false otherwise
146
 *
147
 * @see rename() uses the check_name_exist() and php2phps() functions
148
 */
149
function my_rename($file_path, $new_file_name)
150
{
151
    $save_dir = getcwd();
152
    $path = dirname($file_path);
153
    $old_file_name = basename($file_path);
154
    $new_file_name = api_replace_dangerous_char($new_file_name);
155
156
    // If no extension, take the old one
157
    if ((strpos($new_file_name, '.') === false) && ($dotpos = strrpos($old_file_name, '.'))) {
158
        $new_file_name .= substr($old_file_name, $dotpos);
159
    }
160
161
    // Note: still possible: 'xx.yy' -rename-> '.yy' -rename-> 'zz'
162
    // This is useful for folder names, where otherwise '.' would be sticky
163
164
    // Extension PHP is not allowed, change to PHPS
165
    $new_file_name = php2phps($new_file_name);
166
167
    if ($new_file_name == $old_file_name) {
168
        return $old_file_name;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $old_file_name returns the type string which is incompatible with the documented return type boolean.
Loading history...
169
    }
170
171
    if (strtolower($new_file_name) != strtolower($old_file_name) && check_name_exist($path.'/'.$new_file_name)) {
172
        return false;
173
    }
174
    // On a Windows server, it would be better not to do the above check
175
    // because it succeeds for some new names resembling the old name.
176
    // But on Unix/Linux the check must be done because rename overwrites.
177
178
    chdir($path);
179
    $res = rename($old_file_name, $new_file_name) ? $new_file_name : false;
180
    chdir($save_dir);
181
182
    return $res;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $res also could return the type string which is incompatible with the documented return type boolean.
Loading history...
183
}
184
185
/**
186
 * Moves a file or a directory to an other area.
187
 *
188
 * @author Hugues Peeters <[email protected]>
189
 *
190
 * @param string $source      the path of file or directory to move
191
 * @param string $target      the path of the new area
192
 * @param bool   $forceMove   Whether to force a move or to make a copy (safer but slower) and then delete the original
193
 * @param bool   $moveContent In some cases (including migrations), we need to move the *content* and not the folder itself
194
 *
195
 * @return bool true if the move succeed, false otherwise
196
 *
197
 * @see move() uses check_name_exist() and copyDirTo() functions
198
 */
199
function move($source, $target, $forceMove = true, $moveContent = false)
200
{
201
    $target = realpath($target); // remove trailing slash
202
    $source = realpath($source);
203
    if (check_name_exist($source)) {
204
        $file_name = basename($source);
205
        // move onto self illegal: mv a/b/c a/b/c or mv a/b/c a/b
206
        if (strcasecmp($target, dirname($source)) === 0) {
207
            return false;
208
        }
209
        $isWindowsOS = api_is_windows_os();
210
        $canExec = function_exists('exec');
211
212
        /* File case */
213
        if (is_file($source)) {
214
            if ($forceMove) {
215
                if (!$isWindowsOS && $canExec) {
216
                    exec('mv '.$source.' '.$target.'/'.$file_name);
217
                } else {
218
                    // Try copying
219
                    copy($source, $target.'/'.$file_name);
220
                    unlink($source);
221
                }
222
            } else {
223
                copy($source, $target.'/'.$file_name);
224
                unlink($source);
225
            }
226
227
            return true;
228
        } elseif (is_dir($source)) {
229
            // move dir down will cause loop: mv a/b/ a/b/c/ not legal
230
            if (strncasecmp($target, $source, strlen($source)) == 0) {
231
                return false;
232
            }
233
            /* Directory */
234
            if ($forceMove && !$isWindowsOS && $canExec) {
235
                if ($moveContent) {
236
                    $base = basename($source);
237
                    $out = [];
238
                    $retVal = -1;
239
                    exec('mv '.$source.'/* '.$target.'/'.$base, $out, $retVal);
240
                    if ($retVal !== 0) {
241
                        return false; // mv should return 0 on success
242
                    }
243
                    exec('rm -rf '.$source);
244
                } else {
245
                    $out = [];
246
                    $retVal = -1;
247
                    exec("mv $source $target", $out, $retVal);
248
                    if ($retVal !== 0) {
249
                        error_log("Chamilo error fileManage.lib.php: mv $source $target\n");
250
251
                        return false; // mv should return 0 on success
252
                    }
253
                }
254
            } else {
255
                return copyDirTo($source, $target);
256
            }
257
258
            return true;
259
        }
260
    }
261
    return false;
262
}
263
264
/**
265
 * Moves a directory and its content to an other area.
266
 *
267
 * @author Hugues Peeters <[email protected]>
268
 *
269
 * @param string $source      the path of the directory to move
270
 * @param string $destination the path of the new area
271
 * @param bool   $move        Whether we want to remove the source at the end
272
 *
273
 * @return bool false on error
274
 */
275
function copyDirTo($source, $destination, $move = true)
276
{
277
    $fs = new Filesystem();
278
    if (is_dir($source)) {
279
        $fs->mkdir($destination);
280
        if (!is_dir($destination)) {
281
            error_log("Chamilo copyDirTo cannot mkdir $destination\n");
282
283
            return false; // could not create destination dir
284
        }
285
        $fs->mirror($source, $destination);
286
        if ($move) {
287
            $fs->remove($source);
288
        }
289
    }
290
291
    return true;
292
}
293
294
/**
295
 * Copy a directory and its directories (not files) to an other area.
296
 *
297
 * @param string $source      the path of the directory to move
298
 * @param string $destination the path of the new area
299
 *
300
 * @return bool false on error
301
 */
302
function copyDirWithoutFilesTo($source, $destination)
303
{
304
    $fs = new Filesystem();
305
306
    if (!is_dir($source)) {
307
        return false;
308
    }
309
310
    if (!$fs->exists($destination)) {
311
        $fs->mkdir($destination);
312
    }
313
314
    $dirIterator = new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS);
315
    $iterator = new RecursiveIteratorIterator($dirIterator, RecursiveIteratorIterator::SELF_FIRST);
316
317
    /** @var \SplFileInfo $item */
318
    foreach ($iterator as $item) {
319
        if ($item->isFile()) {
320
            continue;
321
        }
322
323
        $newDir = $destination.'/'.$item->getFilename();
324
325
        if (!$fs->exists($newDir)) {
326
            $fs->mkdir($destination.'/'.$item->getFilename());
327
        }
328
    }
329
330
    return true;
331
}
332
333
/**
334
 * Extracting extension of a filename.
335
 *
336
 * @returns array
337
 *
338
 * @param string $filename filename
339
 */
340
function getextension($filename)
341
{
342
    $bouts = explode('.', $filename);
343
344
    return [array_pop($bouts), implode('.', $bouts)];
345
}
346
347
/**
348
 * Get a list of all PHP (.php) files in a given directory. Includes .tpl files
349
 * @param string $base_path The base path in which to find the corresponding files
350
 * @param bool $includeStatic Include static .html, .htm and .css files
351
 * @return array
352
 */
353
function getAllPhpFiles($base_path, $includeStatic = false)
354
{
355
    $list = scandir($base_path);
356
    $files = [];
357
    $extensionsArray = ['.php', '.tpl'];
358
    if ($includeStatic) {
359
        $extensionsArray[] = 'html';
360
        $extensionsArray[] = '.htm';
361
        $extensionsArray[] = '.css';
362
    }
363
    foreach ($list as $item) {
364
        if (substr($item, 0, 1) == '.') {
365
            continue;
366
        }
367
        $special_dirs = [api_get_path(SYS_TEST_PATH), api_get_path(SYS_COURSE_PATH), api_get_path(SYS_LANG_PATH), api_get_path(SYS_ARCHIVE_PATH)];
368
        if (in_array($base_path.$item.'/', $special_dirs)) {
369
            continue;
370
        }
371
        if (is_dir($base_path.$item)) {
372
            $files = array_merge($files, getAllPhpFiles($base_path.$item.'/', $includeStatic));
373
        } else {
374
            //only analyse php files
375
            $sub = substr($item, -4);
376
            if (in_array($sub, $extensionsArray)) {
377
                $files[] = $base_path.$item;
378
            }
379
        }
380
    }
381
    $list = null;
382
383
    return $files;
384
}