copyDirWithoutFilesTo()   A
last analyzed

Complexity

Conditions 6
Paths 9

Size

Total Lines 29
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 14
nc 9
nop 2
dl 0
loc 29
rs 9.2222
c 0
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
11
/**
12
 * Cheks a file or a directory actually exist at this location.
13
 *
14
 * @author Hugues Peeters <[email protected]>
15
 *
16
 * @param string $file_path Path of the presume existing file or dir
17
 *
18
 * @return bool TRUE if the file or the directory exists or FALSE otherwise
19
 */
20
function check_name_exist($file_path)
21
{
22
    clearstatcache();
23
    $save_dir = getcwd();
24
    if (!is_dir(dirname($file_path))) {
25
        return false;
26
    }
27
    chdir(dirname($file_path));
28
    $file_name = basename($file_path);
29
30
    if (file_exists($file_name)) {
31
        chdir($save_dir);
32
33
        return true;
34
    } else {
35
        chdir($save_dir);
36
37
        return false;
38
    }
39
}
40
41
/**
42
 * Deletes a file or a directory.
43
 *
44
 * @author - Hugues Peeters
45
 *
46
 * @param $file (String) - the path of file or directory to delete
47
 *
48
 * @return bool - true if the delete succeed, false otherwise
49
 *
50
 * @see    - delete() uses check_name_exist() and removeDir() functions
51
 */
52
function my_delete($file)
53
{
54
    if (check_name_exist($file)) {
55
        if (is_file($file)) { // FILE CASE
56
            unlink($file);
57
58
            return true;
59
        } elseif (is_dir($file)) { // DIRECTORY CASE
60
            removeDir($file);
61
62
            return true;
63
        }
64
    }
65
66
    return false; // no file or directory to delete
67
}
68
69
/**
70
 * Removes a directory recursively.
71
 *
72
 * @returns true if OK, otherwise false
73
 *
74
 * @author Amary <[email protected]> (from Nexen.net)
75
 * @author Olivier Brouckaert <[email protected]>
76
 *
77
 * @param string $dir directory to remove
78
 */
79
function removeDir($dir)
80
{
81
    if (!@$opendir = opendir($dir)) {
82
        return false;
83
    }
84
85
    while ($readdir = readdir($opendir)) {
86
        if ($readdir != '..' && $readdir != '.') {
87
            if (is_file($dir.'/'.$readdir)) {
88
                if (!@unlink($dir.'/'.$readdir)) {
89
                    return false;
90
                }
91
            } elseif (is_dir($dir.'/'.$readdir)) {
92
                if (!removeDir($dir.'/'.$readdir)) {
93
                    return false;
94
                }
95
            }
96
        }
97
    }
98
99
    closedir($opendir);
100
101
    if (!@rmdir($dir)) {
102
        return false;
103
    }
104
105
    return true;
106
}
107
108
/**
109
 * Return true if folder is empty.
110
 *
111
 * @author [email protected]
112
 *
113
 * @param string $in_folder folder path on disk
114
 *
115
 * @return int 1 if folder is empty, 0 otherwise
116
 */
117
function folder_is_empty($in_folder)
118
{
119
    $folder_is_empty = 0;
120
    if (is_dir($in_folder)) {
121
        $tab_folder_content = scandir($in_folder);
122
        if ((
123
            count($tab_folder_content) == 2 &&
124
            in_array(".", $tab_folder_content) &&
125
            in_array("..", $tab_folder_content)
126
            ) ||
127
            (count($tab_folder_content) < 2)
128
        ) {
129
            $folder_is_empty = 1;
130
        }
131
    }
132
133
    return $folder_is_empty;
134
}
135
136
/**
137
 * Renames a file or a directory.
138
 *
139
 * @author Hugues Peeters <[email protected]>
140
 *
141
 * @param string $file_path     complete path of the file or the directory
142
 * @param string $new_file_name new name for the file or the directory
143
 *
144
 * @return bool true if succeed, false otherwise
145
 *
146
 * @see rename() uses the check_name_exist() and php2phps() functions
147
 */
148
function my_rename($file_path, $new_file_name)
149
{
150
    $save_dir = getcwd();
151
    $path = dirname($file_path);
152
    $old_file_name = basename($file_path);
153
    $new_file_name = api_replace_dangerous_char($new_file_name);
154
155
    // If no extension, take the old one
156
    if ((strpos($new_file_name, '.') === false) && ($dotpos = strrpos($old_file_name, '.'))) {
157
        $new_file_name .= substr($old_file_name, $dotpos);
158
    }
159
160
    // Note: still possible: 'xx.yy' -rename-> '.yy' -rename-> 'zz'
161
    // This is useful for folder names, where otherwise '.' would be sticky
162
163
    // Extension PHP is not allowed, change to PHPS
164
    $new_file_name = php2phps($new_file_name);
165
166
    if ($new_file_name == $old_file_name) {
167
        return $old_file_name;
168
    }
169
170
    if (strtolower($new_file_name) != strtolower($old_file_name) && check_name_exist($path.'/'.$new_file_name)) {
171
        return false;
172
    }
173
    // On a Windows server, it would be better not to do the above check
174
    // because it succeeds for some new names resembling the old name.
175
    // But on Unix/Linux the check must be done because rename overwrites.
176
177
    chdir($path);
178
    $res = rename($old_file_name, $new_file_name) ? $new_file_name : false;
179
    chdir($save_dir);
180
181
    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...
182
}
183
184
/**
185
 * Moves a file or a directory to an other area.
186
 *
187
 * @author Hugues Peeters <[email protected]>
188
 *
189
 * @param string $source      the path of file or directory to move
190
 * @param string $target      the path of the new area
191
 * @param bool   $forceMove   Whether to force a move or to make a copy (safer but slower) and then delete the original
192
 * @param bool   $moveContent In some cases (including migrations), we need to move the *content* and not the folder itself
193
 *
194
 * @return bool true if the move succeed, false otherwise
195
 *
196
 * @see move() uses check_name_exist() and copyDirTo() functions
197
 */
198
function move($source, $target, $forceMove = true, $moveContent = false)
199
{
200
    $target = realpath($target); // remove trailing slash
201
    $source = realpath($source);
202
    if (check_name_exist($source)) {
203
        $file_name = basename($source);
204
        // move onto self illegal: mv a/b/c a/b/c or mv a/b/c a/b
205
        if (strcasecmp($target, dirname($source)) === 0) {
206
            return false;
207
        }
208
        $isWindowsOS = api_is_windows_os();
209
        $canExec = function_exists('exec');
210
211
        /* File case */
212
        if (is_file($source)) {
213
            if ($forceMove) {
214
                if (!$isWindowsOS && $canExec) {
215
                    exec('mv '.$source.' '.$target.'/'.$file_name);
216
                } else {
217
                    // Try copying
218
                    copy($source, $target.'/'.$file_name);
219
                    unlink($source);
220
                }
221
            } else {
222
                copy($source, $target.'/'.$file_name);
223
                unlink($source);
224
            }
225
226
            return true;
227
        } elseif (is_dir($source)) {
228
            // move dir down will cause loop: mv a/b/ a/b/c/ not legal
229
            if (strncasecmp($target, $source, strlen($source)) == 0) {
230
                return false;
231
            }
232
            /* Directory */
233
            if ($forceMove && !$isWindowsOS && $canExec) {
234
                if ($moveContent) {
235
                    $base = basename($source);
236
                    $out = [];
237
                    $retVal = -1;
238
                    exec('mv '.$source.'/* '.$target.'/'.$base, $out, $retVal);
239
                    if ($retVal !== 0) {
240
                        return false; // mv should return 0 on success
241
                    }
242
                    exec('rm -rf '.$source);
243
                } else {
244
                    $out = [];
245
                    $retVal = -1;
246
                    exec("mv $source $target", $out, $retVal);
247
                    if ($retVal !== 0) {
248
                        error_log("Chamilo error fileManage.lib.php: mv $source $target\n");
249
250
                        return false; // mv should return 0 on success
251
                    }
252
                }
253
            } else {
254
                $base = basename($source);
255
256
                return copyDirTo($source, $target.'/'.$base);
257
            }
258
259
            return true;
260
        }
261
    }
262
263
    return false;
264
}
265
266
/**
267
 * Moves a directory and its content to an other area.
268
 *
269
 * @author Hugues Peeters <[email protected]>
270
 *
271
 * @param string $source      the path of the directory to move
272
 * @param string $destination the path of the new area
273
 * @param bool   $move        Whether we want to remove the source at the end
274
 *
275
 * @return bool false on error
276
 */
277
function copyDirTo($source, $destination, $move = true)
278
{
279
    $fs = new Filesystem();
280
    if (is_dir($source)) {
281
        $fs->mkdir($destination);
282
        if (!is_dir($destination)) {
283
            error_log("Chamilo copyDirTo cannot mkdir $destination\n");
284
285
            return false; // could not create destination dir
286
        }
287
        $fs->mirror($source, $destination);
288
        if ($move) {
289
            $fs->remove($source);
290
        }
291
    }
292
293
    return true;
294
}
295
296
/**
297
 * Copy a directory and its directories (not files) to an other area.
298
 *
299
 * @param string $source      the path of the directory to move
300
 * @param string $destination the path of the new area
301
 *
302
 * @return bool false on error
303
 */
304
function copyDirWithoutFilesTo($source, $destination)
305
{
306
    $fs = new Filesystem();
307
308
    if (!is_dir($source)) {
309
        return false;
310
    }
311
312
    if (!$fs->exists($destination)) {
313
        $fs->mkdir($destination);
314
    }
315
316
    $dirIterator = new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS);
317
    $iterator = new RecursiveIteratorIterator($dirIterator, RecursiveIteratorIterator::SELF_FIRST);
318
319
    /** @var \SplFileInfo $item */
320
    foreach ($iterator as $item) {
321
        if ($item->isFile()) {
322
            continue;
323
        }
324
325
        $newDir = $destination.'/'.$item->getFilename();
326
327
        if (!$fs->exists($newDir)) {
328
            $fs->mkdir($destination.'/'.$item->getFilename());
329
        }
330
    }
331
332
    return true;
333
}
334
335
/**
336
 * Extracting extension of a filename.
337
 *
338
 * @returns array
339
 *
340
 * @param string $filename filename
341
 */
342
function getextension($filename)
343
{
344
    $bouts = explode('.', $filename);
345
346
    return [array_pop($bouts), implode('.', $bouts)];
347
}
348
349
/**
350
 * Get a list of all PHP (.php) files in a given directory. Includes .tpl files.
351
 *
352
 * @param string $base_path     The base path in which to find the corresponding files
353
 * @param bool   $includeStatic Include static .html, .htm and .css files
354
 *
355
 * @return array
356
 */
357
function getAllPhpFiles($base_path, $includeStatic = false)
358
{
359
    $list = scandir($base_path);
360
    $files = [];
361
    $extensionsArray = ['.php', '.tpl'];
362
    if ($includeStatic) {
363
        $extensionsArray[] = 'html';
364
        $extensionsArray[] = '.htm';
365
        $extensionsArray[] = '.css';
366
    }
367
    foreach ($list as $item) {
368
        if (substr($item, 0, 1) == '.') {
369
            continue;
370
        }
371
        $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)];
372
        if (in_array($base_path.$item.'/', $special_dirs)) {
373
            continue;
374
        }
375
        if (is_dir($base_path.$item)) {
376
            $files = array_merge($files, getAllPhpFiles($base_path.$item.'/', $includeStatic));
377
        } else {
378
            //only analyse php files
379
            $sub = substr($item, -4);
380
            if (in_array($sub, $extensionsArray)) {
381
                $files[] = $base_path.$item;
382
            }
383
        }
384
    }
385
    $list = null;
386
387
    return $files;
388
}
389