PluginProbe ʕ •ᴥ•ʔ
VikAppointments Services Booking Calendar / 1.2.20
VikAppointments Services Booking Calendar v1.2.20
1.2.21 1.2.20 trunk 1.2.17 1.2.18 1.2.19
vikappointments / libraries / adapter / filesystem / folder.php
vikappointments / libraries / adapter / filesystem Last commit date
archive.php 1 month ago file.php 1 month ago folder.php 1 month ago path.php 1 month ago
folder.php
411 lines
1 <?php
2 /**
3 * @package VikWP - Libraries
4 * @subpackage adapter.filesystem
5 * @author E4J s.r.l.
6 * @copyright Copyright (C) 2023 E4J s.r.l. All Rights Reserved.
7 * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
8 * @link https://vikwp.com
9 */
10
11 // No direct access
12 defined('ABSPATH') or die('No script kiddies please!');
13
14 JLoader::import('adapter.filesystem.path');
15 JLoader::import('adapter.filesystem.file');
16
17 /**
18 * This class provides a common interface for
19 * Folder handling in the Wordpress CMS plugins.
20 *
21 * @since 10.0
22 */
23 class JFolder
24 {
25 /**
26 * Checks whether the given path exists and is a directory.
27 *
28 * @param string $path Folder name.
29 *
30 * @return boolean True if path is a folder.
31 */
32 public static function exists($path)
33 {
34 return is_dir(JPath::clean($path));
35 }
36
37 /**
38 * Create a folder and all necessary parent folders.
39 *
40 * @param string $path A path to create from the base path.
41 * @param integer $mode Directory permissions to set for folders created. 0755 by default.
42 *
43 * @return boolean True if successful.
44 */
45 public static function create($path = '', $mode = 0755)
46 {
47 static $nested = 0;
48
49 $path = JPath::clean($path);
50
51 // check if parent dir exists
52 $parent = dirname($path);
53
54 if (!self::exists($parent))
55 {
56 // prevent infinite loops
57 $nested++;
58
59 if (($nested > 20) || ($parent == $path))
60 {
61 $nested--;
62
63 return false;
64 }
65
66 // create the parent directory
67 if (self::create($parent, $mode) !== true)
68 {
69 $nested--;
70
71 return false;
72 }
73
74 // OK, parent directory has been created
75 $nested--;
76 }
77
78 // check if dir already exists
79 if (self::exists($path))
80 {
81 return true;
82 }
83
84 // first set umask (no permissions to revoke)
85 $origmask = @umask(0);
86
87 // try to create the path
88 $ret = @mkdir($path, $mode);
89
90 // reset original umask
91 @umask($origmask);
92
93 // return whether the folder has been created or not
94 return $ret;
95 }
96
97 /**
98 * Utility function to read the files in a folder.
99 *
100 * @param string $path The path of the folder to read.
101 * @param string $filter A filter for file names.
102 * @param mixed $recurse True to recursively search into sub-folders, or an integer to specify the maximum depth.
103 * @param boolean $full True to return the full path to the file.
104 * @param array $exclude Array with names of files which should not be shown in the result.
105 * @param array $excludefilter Array of filter to exclude.
106 * @param boolean $naturalSort False for asort, true for natsort.
107 *
108 * @return array Files in the given folder.
109 *
110 * @uses _items()
111 */
112 public static function files($path, $filter = '.', $recurse = false, $full = false, $exclude = array('.svn', 'CVS', '.DS_Store', '__MACOSX'),
113 $excludefilter = array('^\..*', '.*~'), $naturalSort = false)
114 {
115 // make sure the path is a folder
116 if (!static::exists($path))
117 {
118 return false;
119 }
120
121 // compute the excludefilter string
122 if (count($excludefilter))
123 {
124 $excludefilter_string = '/(' . implode('|', $excludefilter) . ')/';
125 }
126 else
127 {
128 $excludefilter_string = '';
129 }
130
131 // get the files
132 $arr = self::_items($path, $filter, $recurse, $full, $exclude, $excludefilter_string, true);
133
134 // sort the files based on either natural or alpha method
135 if ($naturalSort)
136 {
137 natsort($arr);
138 }
139 else
140 {
141 asort($arr);
142 }
143
144 return array_values($arr);
145 }
146
147 /**
148 * Utility function to read the folders in a folder.
149 *
150 * @param string $path The path of the folder to read.
151 * @param string $filter A filter for folder names.
152 * @param mixed $recurse True to recursively search into sub-folders, or an integer to specify the maximum depth.
153 * @param boolean $full True to return the full path to the folders.
154 * @param array $exclude Array with names of folders which should not be shown in the result.
155 * @param array $excludefilter Array with regular expressions matching folders which should not be shown in the result.
156 *
157 * @return array Folders in the given folder.
158 *
159 * @uses _items()
160 */
161 public static function folders($path, $filter = '.', $recurse = false, $full = false, $exclude = array('.svn', 'CVS', '.DS_Store', '__MACOSX'),
162 $excludefilter = array('^\..*'))
163 {
164 // make sure the path is a folder
165 if (!static::exists($path))
166 {
167 return false;
168 }
169
170 // Compute the excludefilter string
171 if (count($excludefilter))
172 {
173 $excludefilter_string = '/(' . implode('|', $excludefilter) . ')/';
174 }
175 else
176 {
177 $excludefilter_string = '';
178 }
179
180 // Get the folders
181 $arr = self::_items($path, $filter, $recurse, $full, $exclude, $excludefilter_string, false);
182
183 // Sort the folders
184 asort($arr);
185
186 return array_values($arr);
187 }
188
189 /**
190 * Function to read the files/folders in a folder.
191 *
192 * @param string $path The path of the folder to read.
193 * @param string $filter A filter for file names.
194 * @param mixed $recurse True to recursively search into sub-folders, or an integer to specify the maximum depth.
195 * @param boolean $full True to return the full path to the file.
196 * @param array $exclude Array with names of files which should not be shown in the result.
197 * @param string $excludefilter_string Regexp of files to exclude.
198 * @param boolean $findfiles True to read the files, false to read the folders.
199 *
200 * @return array Search for recursive files.
201 */
202 protected static function _items($path, $filter, $recurse, $full, $exclude, $excludefilter_string, $findfiles)
203 {
204 @set_time_limit(ini_get('max_execution_time'));
205
206 $path = JPath::clean($path);
207
208 $arr = array();
209
210 // Read the source directory
211 if (!($handle = @opendir($path)))
212 {
213 return $arr;
214 }
215
216 while (($file = readdir($handle)) !== false)
217 {
218 if ($file != '.' && $file != '..' && !in_array($file, $exclude)
219 && (empty($excludefilter_string) || !preg_match($excludefilter_string, $file)))
220 {
221 // Compute the fullpath
222 $fullpath = $path . '/' . $file;
223
224 // Compute the isDir flag
225 $isDir = is_dir($fullpath);
226
227 if (($isDir xor $findfiles) && preg_match("/$filter/", $file))
228 {
229 // (fullpath is dir and folders are searched or fullpath is not dir and files are searched) and file matches the filter
230 if ($full)
231 {
232 // Full path is requested
233 $arr[] = $fullpath;
234 }
235 else
236 {
237 // Filename is requested
238 $arr[] = $file;
239 }
240 }
241
242 if ($isDir && $recurse)
243 {
244 // Search recursively
245 if (is_int($recurse))
246 {
247 // Until depth 0 is reached
248 $arr = array_merge($arr, self::_items($fullpath, $filter, $recurse - 1, $full, $exclude, $excludefilter_string, $findfiles));
249 }
250 else
251 {
252 $arr = array_merge($arr, self::_items($fullpath, $filter, $recurse, $full, $exclude, $excludefilter_string, $findfiles));
253 }
254 }
255 }
256 }
257
258 closedir($handle);
259
260 return $arr;
261 }
262
263 /**
264 * Copy a source folder to a destination.
265 *
266 * @param string $src The full folder path.
267 * @param string $dest The full destination path.
268 * @param string $path An optional base path to use as prefix.
269 * @param boolean $force Copy the folder even if it exists.
270 *
271 * @return boolean True on success.
272 *
273 * @uses exists()
274 * @uses create()
275 */
276 public static function copy($src, $dest, $path = '', $force = false)
277 {
278 @set_time_limit(ini_get('max_execution_time'));
279
280 if ($path)
281 {
282 $src = $path . '/' . $src;
283 $dest = $path . '/' . $dest;
284 }
285
286 $src = JPath::clean($src);
287 $dest = JPath::clean($dest);
288
289 // Get rid of trailing directory separators, if any
290 $src = rtrim($src, DIRECTORY_SEPARATOR);
291 $dest = rtrim($dest, DIRECTORY_SEPARATOR);
292
293 if (!self::exists($src))
294 {
295 return false;
296 }
297
298 if (self::exists($dest) && !$force)
299 {
300 return false;
301 }
302
303 // Make sure the destination exists
304 if (!self::create($dest))
305 {
306 return false;
307 }
308
309 if (!($dh = @opendir($src)))
310 {
311 return false;
312 }
313 // Walk through the directory copying files and recursing into folders.
314 while (($file = readdir($dh)) !== false)
315 {
316 $sfid = $src . '/' . $file;
317 $dfid = $dest . '/' . $file;
318
319 switch (filetype($sfid))
320 {
321 case 'dir':
322 if ($file != '.' && $file != '..')
323 {
324 $ret = self::copy($sfid, $dfid, null, $force);
325
326 if ($ret !== true)
327 {
328 return $ret;
329 }
330 }
331 break;
332
333 case 'file':
334 if (!JFile::copy($sfid, $dfid))
335 {
336 return false;
337 }
338 break;
339 }
340 }
341
342 return true;
343 }
344
345 /**
346 * Delete a folder with all its sub-folders and files.
347 *
348 * @param string $path The path to the folder to remove.
349 *
350 * @return boolean true on success.
351 *
352 * @uses files()
353 * @uses folders()
354 */
355 public static function delete($path)
356 {
357 @set_time_limit(ini_get('max_execution_time'));
358
359 if (!$path)
360 {
361 return false;
362 }
363
364 // ensure path gets cleaned and is valid
365 $path = JPath::clean($path);
366
367 if (!static::exists($path))
368 {
369 return false;
370 }
371
372 // remove all the files in the current folder
373 $files = self::files($path, '.', false, true, array(), array());
374
375 if (!empty($files))
376 {
377 if (JFile::delete($files) !== true)
378 {
379 return false;
380 }
381 }
382
383 // remove sub-folders of the current folder
384 $folders = self::folders($path, '.', false, true, array(), array());
385
386 foreach ($folders as $folder)
387 {
388 if (is_link($folder))
389 {
390 // we don't follow links
391 if (JFile::delete($folder) !== true)
392 {
393 return false;
394 }
395 }
396 else if (self::delete($folder) !== true)
397 {
398 return false;
399 }
400 }
401
402 // folder should now be removed as long as the owner is www-data
403 if (@rmdir($path))
404 {
405 return true;
406 }
407
408 return false;
409 }
410 }
411