Git viewing holonet/common / master / src/FilesystemUtils.php


Filter

      <?php
/**
 * This file is part of the holonet common library
 * (c) Matthias Lantsch.
 *
 * @license http://opensource.org/licenses/gpl-license.php  GNU Public License
 * @author  Matthias Lantsch <[email protected]>
 */

namespace holonet\common;

use Exception;
use DirectoryIterator;

/**
 * FilesystemUtils utility class making interacting with the file system easier.
 */
class FilesystemUtils {
	/**
	 * @param string ...$parts variable number of path elements
	 * @return string system independent absolute directory path with a trailing separator
	 */
	public static function dirpath(...$parts): string {
		return static::filepath(...$parts).\DIRECTORY_SEPARATOR;
	}

	/**
	 * check if a directory exist and create it if it doesn't.
	 */
	public static function dirShouldExist(string $directory): void {
		if (!file_exists($directory) || !is_dir($directory)) {
			mkdir($directory, 0755, true);
		}
	}

	/**
	 * @param string ...$parts variable number of path elements
	 * @return string system independent absolute path using the given path parts
	 */
	public static function filepath(...$parts): string {
		$ret = implode(\DIRECTORY_SEPARATOR, $parts);
		//prepend a / on linux
		if ($ret[0] !== \DIRECTORY_SEPARATOR && \DIRECTORY_SEPARATOR === '/') {
			$ret = \DIRECTORY_SEPARATOR.$ret;
		}
		//make sure there's no double separators
		$double = \DIRECTORY_SEPARATOR.\DIRECTORY_SEPARATOR;
		if (mb_strpos($ret, $double) !== false) {
			$ret = str_replace($double, \DIRECTORY_SEPARATOR, $ret);
		}

		return $ret;
	}

	/**
	 * @param string ...$parts variable number of path elements
	 * @return string system independent directory path relative to the calling file with a trailing separator
	 */
	public static function reldirpath(...$parts): string {
		$bt = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 1);
		array_unshift($parts, dirname($bt[0]['file']));

		return static::dirpath(...$parts);
	}

	/**
	 * @param string ...$parts variable number of path elements
	 * @return string system independent file path relative to the calling file
	 */
	public static function relfilepath(...$parts): string {
		$bt = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 1);
		array_unshift($parts, dirname($bt[0]['file']));

		return static::filepath(...$parts);
	}

	/**
	 * Recursively move files from one directory to another.
	 * @param string $src Source of files being moved
	 * @param string $dest Destination of files being moved
	 */
	public static function rmove(string $src, string $dest): void {
		// If source is not a directory just simply move it
		if (!is_dir($src)) {
			rename($src, $dest);

			return;
		}

		// Open the source directory to read in files
		$i = new DirectoryIterator($src);
		foreach ($i as $f) {
			if ($f->isFile()) {
				static::dirShouldExist(dirname("{$dest}/".$f->getFilename()));
				rename($f->getRealPath(), "{$dest}/".$f->getFilename());
			} elseif (!$f->isDot() && $f->isDir()) {
				static::rmove($f->getRealPath(), "{$dest}/{$f}");
			}
		}
		rmdir($src);
	}

	/**
	 * @param string $directory The path to recursively delete
	 * @param bool $throw Boolean flag marking whether to throw an exception or not
	 * @throws Exception if a path could not be deleted and the throw flag is given
	 */
	public static function rrmdir(string $directory, bool $throw = false): void {
		if (!file_exists($directory)) {
			return;
		}

		if (is_dir($directory)) {
			$objects = scandir($directory);
			foreach ($objects as $object) {
				if ($object !== '.' && $object !== '..') {
					if (is_dir($directory.\DIRECTORY_SEPARATOR.$object)) {
						static::rrmdir($directory.\DIRECTORY_SEPARATOR.$object);
					} else {
						static::rrmdir($directory.\DIRECTORY_SEPARATOR.$object);
					}
				}
			}
			if (!@rmdir($directory) && $throw) {
				$err = error_get_last();
				$msg = ($err !== null ? $err['message'] : 'No Error');

				throw new Exception("Could not rmdir '{$directory}': {$msg}", 100);
			}
		} else {
			if ((!@unlink($directory) && $throw) || file_exists($directory)) {
				$err = error_get_last();
				$msg = ($err !== null ? $err['message'] : 'No Error');

				throw new Exception("Could not unlink '{$directory}': {$msg}", 100);
			}
		}
	}
}