Issues (994)

src/Filemanager/file.php (9 issues)

1
<?php
2
3
namespace Filemanager;
4
5
use JSON\json;
6
use MVC\Exception;
7
8
class file
9
{
10
  public function __construct()
11
  {
12
  }
13
14
  public static function tmp()
15
  {
16
    $root = __DIR__;
17
    if (defined('ROOT')) {
18
      $root = ROOT;
19
    }
20
21
    return self::folder($root . '/tmp');
22
  }
23
24
  /**
25
   * Flush directory.
26
   *
27
   * @todo empty the directory, deleting all files except directory
28
   *
29
   * @param string $dir
30
   */
31
  public static function empty(string $dir)
32
  {
33
    if (!file_exists($dir)) {
34
      \MVC\alert::init()->error('empty folder', $dir . ' not exists');
35
      return;
36
    }
37
    $subdir = new \RecursiveDirectoryIterator($dir, \FilesystemIterator::SKIP_DOTS);
38
    /**
39
     * @var \SplFileInfo[]
40
     */
41
    $dirs = new \RecursiveIteratorIterator($subdir, \RecursiveIteratorIterator::CHILD_FIRST);
42
    foreach ($dirs as $file) {
43
      if (!$file->isDir() && $file->isWritable()) {
44
        unlink($file);
45
      }
46
    }
47
  }
48
49
  /**
50
   * Recursive delete.
51
   *
52
   * @param string $path files or folder
53
   */
54
  public static function delete(string $path)
55
  {
56
    if (file_exists($path)) {
57
      if (is_dir($path)) {
58
        self::deleteDirectory($path);
59
      } else {
60
        unlink($path);
61
      }
62
    }
63
  }
64
65
  public static function deleteDirectory($dir)
66
  {
67
    if ($dir = realpath($dir)) {
68
      if (!file_exists($dir)) {
69
        return true;
70
      }
71
72
      if (!is_dir($dir)) {
73
        return unlink($dir);
74
      }
75
76
      foreach (scandir($dir) as $item) {
77
        if ('.' == $item || '..' == $item) {
78
          continue;
79
        }
80
81
        if (!self::deleteDirectory($dir . DIRECTORY_SEPARATOR . $item)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression self::deleteDirectory($d...TORY_SEPARATOR . $item) of type boolean|null is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
82
          return false;
83
        }
84
      }
85
86
      return rmdir($dir);
87
    }
88
  }
89
90
  public static function folder(string $path)
91
  {
92
    //$fm = new file();
93
    if (!is_dir(dirname($path))) {
94
      mkdir(dirname($path), 0777, true);
95
    }
96
    if (!is_dir($path)) {
97
      mkdir($path, 0777, true);
98
    }
99
100
    return $path;
101
    //return $fm->_folder_($path);
102
  }
103
104
  /**
105
   * Create file nested.
106
   *
107
   * @param string $path
108
   * @param bool   $create
109
   * @param bool   $force
110
   * @param bool   $append
111
   * @param bool   $dump
112
   *
113
   * @return string
114
   */
115
  public static function file(string $path, $create = true, $force = false, $append = false, $dump = false)
0 ignored issues
show
The parameter $dump is not used and could be removed. ( Ignorable by Annotation )

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

115
  public static function file(string $path, $create = true, $force = false, $append = false, /** @scrutinizer ignore-unused */ $dump = false)

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

Loading history...
116
  {
117
    if ($real = realpath($path)) {
118
      $path = $real;
119
    }
120
    $fm = new file();
121
    // if directory not exists, create it
122
    if (!is_dir(dirname($path))) {
123
      mkdir(dirname($path), 0777, true);
124
    }
125
    // set option flag
126
    $option = 0;
127
    if ($append) {
128
      $option = FILE_APPEND;
129
    }
130
    // if forced or file exists, create it
131
    if ($force || !file_exists($path)) {
132
      $create = $fm->determineContent($create);
133
      if (is_writable(dirname($path))) {
134
      }
135
      file_put_contents($path, $create, $option);
136
    }
137
138
    return $path;
139
    //return $fm->_file_($path, $create, $force, $append, $dump);
140
  }
141
142
  public function determineContent($create)
143
  {
144
    if (is_numeric($create) || ctype_digit($create)) {
145
      $create = (int) $create;
146
    } elseif (is_string($create)) {
147
      $create = (string) $create;
148
    } elseif (is_array($create) || is_object($create)) {
149
      $create = json_encode($create, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
150
    } else {
151
      $create = '';
152
    }
153
154
    return $create;
155
  }
156
157
  public static function remove($str)
158
  {
159
    $fm = new file();
160
161
    return $fm->_unlink_($str);
0 ignored issues
show
Are you sure the usage of $fm->_unlink_($str) targeting Filemanager\file::_unlink_() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
162
  }
163
164
  public static function get(string $file, bool $parse_json = false)
165
  {
166
    resolve_dir(dirname($file));
167
    //self::cleanDump($file, realpath($file), file_exists($file), is_writable($file));
168
    $ret = null;
169
    if (realpath($file)) {
170
      $file = realpath($file);
171
    }
172
    if (file_exists($file)) {
173
      $ret = file_get_contents($file);
174
      if ($parse_json && json::is_json($ret)) {
175
        $ret = json_decode($ret, true);
176
      }
177
    }
178
179
    return $ret;
180
  }
181
182
  public function cleanDump($c, ...$_)
183
  {
184
    if (ob_get_level()) {
185
      ob_end_clean();
186
      ob_start();
187
    }
188
    ev($c, $_);
189
  }
190
191
  public function _unlink_($file)
192
  {
193
    if (file_exists($file)) {
194
      unlink($file);
195
    }
196
  }
197
198
  /**
199
   * Create folder recursively.
200
   *
201
   * @param string $d      pathname or dirname
202
   * @param mixed  $root   root directory
203
   *                       * default $_SERVER['DOCUMENT_ROOT']
204
   * @param bool   $noroot false will return begins with $root
205
   *
206
   * @return string
207
   */
208
  public function _folder_($d, $root = null, $noroot = null, $dump = false)
0 ignored issues
show
The parameter $dump is not used and could be removed. ( Ignorable by Annotation )

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

208
  public function _folder_($d, $root = null, $noroot = null, /** @scrutinizer ignore-unused */ $dump = false)

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

Loading history...
209
  {
210
    if (!$root) {
211
      $root = $_SERVER['DOCUMENT_ROOT'];
212
    }
213
    if (preg_match('/(\/admin\/assets\/data\/.*)/m', $d, $cmatch)) {
214
      $d = $cmatch[1];
215
    } else {
216
      $d = str_replace($root, '', $d);
217
    }
218
    $explode = explode('/', rtrim($d, '/'));
219
    $explode = array_filter((array) $explode);
220
221
    //$ready = ('WIN' == strtoupper(substr(PHP_OS, 0, 3)) ? '' : '/');
222
    $ready = '';
223
    if ('WIN' != strtoupper(substr(PHP_OS, 0, 3))) {
224
      $ready .= '/';
225
    }
226
    foreach ($explode as $x) {
227
      if (!empty($ready)) {
228
        $ready .= '/' . $x;
229
      } else {
230
        $ready .= $x;
231
      }
232
      $status = file_exists($ready);
233
      if (!$status) {
234
        $this->mdir($ready);
235
      }
236
    }
237
238
    if (!file_exists($d)) {
239
      if (file_exists($root . $d) && !$noroot) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $noroot of type boolean|null is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
240
        $d = $root . $d;
241
      }
242
    }
243
244
    return $d;
245
  }
246
247
  public function _folder_x($dest, $permissions = 0755, $create = true)
248
  {
249
    if (empty($dest)) {
250
      return $dest;
251
    }
252
    if (!is_dir(dirname($dest))) {
253
      $this->_folder_(dirname($dest), $permissions, $create);
254
    } elseif (!is_dir($dest)) {
255
      mkdir($dest, $permissions, $create);
256
    } else {
257
      return true;
258
    }
259
  }
260
261
  public function is_win()
262
  {
263
    return 'WIN' === strtoupper(substr(PHP_OS, 0, 3));
264
  }
265
266
  /**
267
   * Create file and directory recursively.
268
   *
269
   * @todo mkdir if not exists then file_put_contents
270
   *
271
   * @param string $path   File Path
272
   * @param bool   $create
273
   *                       * true to create
274
   *                       * false to abort create
275
   * @param bool   $force
276
   *                       * true force overwrite
277
   *                       * false not create if exists
278
   * @param bool   $append append to file
279
   *
280
   * @return string filepath
281
   */
282
  public function _file_($path, $create = true, $force = false, $append = false, $dump = false)
283
  {
284
    $path = $this->smartFilePath($path);
285
    //$this->_folder_(dirname($path));
286
287
    if (false !== $create) {
288
      $create = $this->determineContent($create);
289
      //ev(basename($path), dirname($path), $path, $create);
290
      $root = $this->smartFilePath($_SERVER['DOCUMENT_ROOT']);
291
      //ev(strpos($path, $root), $path, $root);
292
      if (false === strpos($path, $root)) {
293
        $path = $root . $path;
294
      }
295
      //ev(file_exists(dirname($path)));
296
      if (!file_exists(dirname($path))) {
297
        $this->_folder_(dirname($path), null, null, $dump);
298
      }
299
      if ((!file_exists($path) || false !== $force) && $create) {
300
        try {
301
          if (!$append) {
302
            file_put_contents($path, $create, LOCK_EX);
303
          } else {
304
            file_put_contents($path, $create, FILE_APPEND | LOCK_EX);
305
          }
306
        } catch (\Exception $e) {
307
          if (ob_get_level()) {
308
            ob_end_clean();
309
          }
310
          exit(json_encode(['error' => $e->getMessage()]));
0 ignored issues
show
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
311
        }
312
      }
313
    }
314
315
    return $path;
316
  }
317
318
  public function __istatic()
319
  {
320
    $static = !(isset($this) && __CLASS__ == get_class($this));
321
322
    return $static;
323
  }
324
325
  /**
326
   * Smart __DIR__.
327
   *
328
   * @param string $dir
329
   *
330
   * @return string $dir
331
   */
332
  public function _dir_($dir = __DIR__)
333
  {
334
    if ('WIN' === strtoupper(substr(PHP_OS, 0, 3))) {
335
      return str_replace('\\', '/', $dir);
336
    }
337
338
    return $dir;
339
  }
340
341
  /**
342
   * Smart file path.
343
   **/
344
  public function smartFilePath($path)
345
  {
346
    if ('WIN' === strtoupper(substr(PHP_OS, 0, 3))) {
347
      return str_replace('\\', '/', $path);
348
    }
349
350
    return $path;
351
  }
352
353
  /**
354
   * Create folder 777.
355
   */
356
  public function mdir($x)
357
  {
358
    //ev($x);
359
    try {
360
      $oldmask = umask(0);
361
      mkdir($x, 0777);
362
      umask($oldmask);
363
    } catch (\Throwable $th) {
364
      echo "{$th->getMessage()} => {$x}";
365
    }
366
  }
367
368
  public function destroy_old_files($dir, $sec = 3600, $prefix = null)
369
  {
370
    if (!is_numeric($sec)) {
371
      throw new \MVC\Exception('Seconds must be instance of number', 1);
372
    }
373
    $mydir = opendir($dir);
374
    while ($file = readdir($mydir)) {
375
      if ('.' != $file && '..' != $file) {
376
        chmod($dir . $file, 0777);
377
        if (is_dir($dir . $file)) {
378
          chdir('.');
379
          while ($dir . $file) {
380
            if (date('U', filectime($file) >= time() - $sec)) {
0 ignored issues
show
filectime($file) >= time() - $sec of type boolean is incompatible with the type integer|null expected by parameter $timestamp of date(). ( Ignorable by Annotation )

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

380
            if (date('U', /** @scrutinizer ignore-type */ filectime($file) >= time() - $sec)) {
Loading history...
381
              if ($prefix && false !== strpos($file, $prefix)) {
382
                continue;
383
              }
384
              if (is_dir($file)) {
385
                continue;
386
              }
387
              unlink($dir . $file) or die("couldn't delete $dir$file<br />");
0 ignored issues
show
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
388
            }
389
          }
390
        } else {
391
          unlink($dir . $file) or die("couldn't delete $dir$file<br />");
0 ignored issues
show
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
392
        }
393
      }
394
    }
395
    closedir($mydir);
396
  }
397
}
398