/src/Nucleus/Library/FileSystem/FileSystem.php
https://bitbucket.org/jonbiard/nucleus · PHP · 723 lines · 332 code · 109 blank · 282 comment · 88 complexity · cab3c7da76d1473b19031414fadf217b MD5 · raw file
- <?php
- /**
- * Class FileSystem
- *
- * @package Nucleus\Library
- * @subpackage FileSystem
- *
- * @author Martin Biard <info@martinbiard.com>
- */
- namespace Nucleus\Library\FileSystem;
- use Nucleus\Library\Exception\IOException;
- /**
- * Class FileSystem
- *
- * @package Nucleus\Library
- * @subpackage FileSystem
- *
- * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
- */
- class FileSystem
- {
- /**
- * Constructor
- */
- public function __construct()
- {
- }
- /**
- * Changes the group of a file or directory
- *
- * @param string $path The file or directory path
- * @param string|int $group The group name or number
- *
- * @throws IOException When the group cannot be changed
- */
- public function changeGroup($path, $group)
- {
- if (!@chgrp($path, $group)) {
- throw new IOException("Failed to change group of: $path");
- }
- }
- /**
- * Changes the owner of a file or directory
- *
- * @param string $path The file or directory path
- * @param string|int $user The user name or number
- *
- * @throws IOException When the owner cannot be changed
- */
- public function changeOwner($path, $user)
- {
- if (!@chown($path, $user)) {
- throw new IOException("Failed to change owner of: $path");
- }
- }
- /**
- * Changes the permissions on a file or directory
- *
- * @param string $path The file or directory path
- * @param int $mode The file mode (see PHP's chmod())
- *
- * @throws IOException When the permissions cannot be changed
- */
- public function changePermissions($path, $mode)
- {
- if (!@chmod($path, $mode)) {
- throw new IOException("Failed to change permissions of: $path");
- }
- }
- /**
- * Copies a file or directory recursively
- *
- * @param string $path The source path
- * @param string $dest The destination path
- * @param bool $overwrite Whether to overwrite if destination already exists
- *
- * @throws IOException Whenever an error occurs during copy
- *
- * @SuppressWarnings(PHPMD.CyclomaticComplexity)
- * @SuppressWarnings(PHPMD.NPathComplexity)
- */
- public function copy($path, $dest, $overwrite = true)
- {
- if (@is_dir($path)) {
- if (!$overwrite && @file_exists($dest)) {
- throw new IOException("Not allowed to overwrite: $dest");
- }
- if (($perms = @fileperms($path)) === false) {
- throw new IOException("Failed to get permissions of: $path");
- }
- $perms = $perms & 511;
- @mkdir($dest);
- if (!@is_dir($dest)) {
- throw new IOException("Failed to create directory: $dest");
- }
- if (!@chmod($dest, $perms)) {
- throw new IOException("Failed to change mode of: $dest");
- }
- if (($dh = @opendir($path)) === false) {
- throw new IOException("Failed to open directory: $path");
- }
- while (($item = @readdir($dh)) !== false) {
- if ($item == '.' || $item == '..') {
- continue;
- }
- $this->copy("$path/$item", "$dest/$item", $overwrite);
- }
- @closedir($dh);
- } else {
- if (!$overwrite && @file_exists($dest)) {
- throw new IOException("Not allowed to overwrite: $dest");
- }
- if (($perms = @fileperms($path)) === false) {
- throw new IOException("Failed to get permissions of: $path");
- }
- $perms = $perms & 511;
- if (!@copy($path, $dest)) {
- throw new IOException("Failed to copy: $path to $dest");
- }
- if (!@chmod($dest, $perms)) {
- throw new IOException("Failed to change mode of: $path");
- }
- }
- }
- /**
- * Creates a directory
- *
- * @param string $path The file or directory path
- * @param int $chmod The permissions
- *
- * @throws IOException When the directory cannot be created
- */
- public function createDirectory($path, $chmod = 0777)
- {
- if (@file_exists($path) && @is_dir($path)) {
- return;
- }
- $old = umask(0);
- if (!@mkdir($path, $chmod, true)) {
- throw new IOException("Failed to create directory: $path");
- }
- umask($old);
- }
- /**
- * Deletes a file or directory recursively
- *
- * @param string $path The file or directory path
- *
- * @throws IOException When the file or directory cannot be deleted
- */
- public function delete($path)
- {
- if (!@file_exists($path)) {
- return;
- }
- if (@is_dir($path)) {
- if (($dh = @opendir($path)) === false) {
- throw new IOException("Failed to open directory: $path");
- }
- while (($item = @readdir($dh)) !== false) {
- if ($item == '.' || $item == '..') {
- continue;
- }
- $this->delete("$path/$item");
- }
- @closedir($dh);
- if (!@rmdir($path)) {
- throw new IOException("Failed to delete: $path");
- }
- } else {
- if (!@unlink($path)) {
- throw new IOException("Failed to delete: $path");
- }
- }
- }
- /**
- * Checks if a file or directory exists
- *
- * @param string $path The file or directory path
- *
- * @return bool True if the file or directory exists
- */
- public function exists($path)
- {
- return @file_exists($path);
- }
- /**
- * Gets the byte size of the file or directory contents
- *
- * @param string $path The file or directory path
- *
- * @return int The total amount of bytes
- *
- * @throws IOException When an error occurs during the process
- */
- public function getByteSize($path)
- {
- $bytes = 0;
- if (@file_exists($path)) {
- if (@is_dir($path)) {
- if (($dh = @opendir($path)) === false) {
- throw new IOException("Failed to open directory: $path");
- }
- while (($item = @readdir($dh)) !== false) {
- if ($item == '.' || $item == '..') {
- continue;
- }
- $bytes += $this->getByteSize("$path/$item");
- }
- @closedir($dh);
- } else {
- if (($bytes = @filesize($path)) === false) {
- throw new IOException("Failed to get byte size of: $path");
- }
- }
- }
- return $bytes;
- }
- /**
- * Gets the file's group
- *
- * @param string $path The file or directory path
- *
- * @return int The file's group ID
- *
- * @throws IOException When the file's group cannot be fetched
- */
- public function getGroup($path)
- {
- if (($filegroup = @filegroup($path)) === false) {
- throw new IOException("Failed to get group of: $path");
- }
- return $filegroup;
- }
- /**
- * Gets the inode of a file or directory
- *
- * @param string $path The file or directory path
- *
- * @return int The file's inode
- *
- * @throws IOException When the inode cannot be fetched
- */
- public function getInode($path)
- {
- if (($fileinode = @fileinode($path)) === false) {
- throw new IOException("Failed to get inode of: $path");
- }
- return $fileinode;
- }
- /**
- * Gets the owner of a file or directory
- *
- * @param string $path The file or directory path
- *
- * @return int The user ID of the owner of the file
- *
- * @throws IOException When the owner ID cannot be fetched
- */
- public function getOwner($path)
- {
- if (($fileowner = @fileowner($path)) === false) {
- throw new IOException("Failed to get owner of: $path");
- }
- return $fileowner;
- }
- /**
- * Gets the permissions of a file or directory
- *
- * @param string $path The file or directory path
- *
- * @return int The permissions of the file
- *
- * @throws IOException When the permissions cannot be fetched
- */
- public function getPermissions($path)
- {
- if (($fileperms = @fileperms($path)) === false) {
- throw new IOException("Failed to get permissions of: $path");
- }
- return $fileperms;
- }
- /**
- * Gets the last access time of a file or directory
- *
- * @param string $path The file or directory path
- *
- * @return int The last access time as a Unix timestamp
- *
- * @throws IOException When the time cannot be fetched
- */
- public function getTimeLastAccessed($path)
- {
- if (($fileatime = @fileatime($path)) === false) {
- throw new IOException("Failed to get last access time of: $path");
- }
- return $fileatime;
- }
- /**
- * Gets the last changed time of a file or directory
- *
- * @param string $path The file or directory path
- *
- * @return int The last changed time as a Unix timestamp
- *
- * @throws IOException When the time cannot be fetched
- */
- public function getTimeLastChanged($path)
- {
- if (($filectime = @filectime($path)) === false) {
- throw new IOException("Failed to get last changed time of: $path");
- }
- return $filectime;
- }
- /**
- * Gets the last modified time of a file or directory
- *
- * @param string $path The file or directory path
- *
- * @return int The last modified time as a Unix timestamp
- *
- * @throws IOException When the time cannot be fetched
- */
- public function getTimeLastModified($path)
- {
- if (($filemtime = @filemtime($path)) === false) {
- throw new IOException("Failed to get last modified time of: $path");
- }
- return $filemtime;
- }
- /**
- * Checks if the path is a directory
- *
- * @param string $path The directory path
- *
- * @return bool True if the path is a directory
- */
- public function isDirectory($path)
- {
- return @is_dir($path);
- }
- /**
- * Check if the file or directory is executable
- *
- * @param string $path The file or directory path
- *
- * @return bool True if the file or directory is executable
- */
- public function isExecutable($path)
- {
- return @is_executable($path);
- }
- /**
- * Checks if the path is a file
- *
- * @param string $path The file path
- *
- * @return bool True if the path is a file
- */
- public function isFile($path)
- {
- return @is_file($path);
- }
- /**
- * Check if the file or directory is readable
- *
- * @param string $path The file or directory path
- *
- * @return bool True if the file or directory is readable
- */
- public function isReadable($path)
- {
- return @is_readable($path);
- }
- /**
- * Check if the file is a symbolic link
- *
- * @param string $path The file or directory path
- *
- * @return bool True if the file is a symbolic link
- */
- public function isSymLink($path)
- {
- return @is_link($path);
- }
- /**
- * Check if the file is an uploaded file
- *
- * @param string $path The file or directory path
- *
- * @return bool True if the file is an uploaded file
- */
- public function isUploadedFile($path)
- {
- return @is_uploaded_file($path);
- }
- /**
- * Check if the file or directory is writeable
- *
- * @param string $path The file or directory path
- *
- * @return bool True if the file or directory is writeable
- */
- public function isWritable($path)
- {
- return @is_writable($path);
- }
- /**
- * Moves a file or directory
- *
- * @param string $path The source path
- * @param string $dest The destination path
- * @param bool $overwrite Whether to overwrite if destination exists
- *
- * @throws IOException When the move cannot be completed
- *
- * @SuppressWarnings(PHPMD.CyclomaticComplexity)
- * @SuppressWarnings(PHPMD.NPathComplexity)
- */
- public function move($path, $dest, $overwrite = true)
- {
- if (@is_dir($path)) {
- if (!$overwrite && @file_exists($dest)) {
- throw new IOException("Not allowed to overwrite: $dest");
- }
- if (($perms = @fileperms($path)) === false) {
- throw new IOException("Failed to get permissions of: $path");
- }
- $perms = $perms & 511;
- @mkdir($dest);
- if (!@is_dir($dest)) {
- throw new IOException("Failed to create directory: $dest");
- }
- if (!@chmod($dest, $perms)) {
- throw new IOException("Failed to change mode of: $dest");
- }
- if (($dh = @opendir($path)) === false) {
- throw new IOException("Failed to open directory: $path");
- }
- while (($item = @readdir($dh)) !== false) {
- if ($item == '.' || $item == '..') {
- continue;
- }
- $this->move("$path/$item", "$dest/$item", $overwrite);
- }
- @closedir($dh);
- if (!@rmdir($path)) {
- throw new IOException("Failed to delete: $path");
- }
- } else {
- if (!$overwrite && @file_exists($dest)) {
- throw new IOException("Not allowed to overwrite: $dest");
- }
- if (($perms = @fileperms($path)) === false) {
- throw new IOException("Failed to get permissions of: $path");
- }
- $perms = $perms & 511;
- if (!@rename($path, $dest)) {
- throw new IOException("Failed to move: $path to $dest");
- }
- if (!@chmod($dest, $perms)) {
- throw new IOException("Failed to change mode of: $dest");
- }
- }
- }
- /**
- * Opens a directory and returns a directory object
- *
- * @param string $path The directory path
- *
- * @return Directory New directory object
- */
- public function openDirectory($path)
- {
- return new Directory($path);
- }
- /**
- * Opens a file and returns a file object
- *
- * @param string $path The file path
- * @param int $mode The mode in which to open the file (see PHP's fopen())
- *
- * @return File New file object
- */
- public function openFile($path, $mode)
- {
- return new File($path, $mode);
- }
- /**
- * Reads a file and returns the contents as a string
- *
- * @param string $path The file or directory path
- * @param int $offset The offset to start the reading at
- * @param null|int $length The amount of characters to read
- *
- * @return string The contents of the file
- *
- * @throws IOException When the contents of the file cannot be fetched
- */
- public function readFile($path, $offset = -1, $length = null)
- {
- if ($length !== null) {
- $data = @file_get_contents($path, false, null, $offset, $length);
- } else {
- $data = @file_get_contents($path, false, null, $offset);
- }
- if ($data === false) {
- throw new IOException("Failed to read contents from file: $path");
- }
- return $data;
- }
- /**
- * Reads a file and returns the contents as an array of lines
- *
- * @param string $path The file or directory path
- * @param bool $stripNewLines Whether to strip the trailing newline character at the ends of each line or not
- * @param bool $skipEmptyLines Whether to skip empty lines or not
- *
- * @return array The array of lines
- *
- * @throws IOException When the contents of the file cannot be fetched
- */
- public function readFileLines($path, $stripNewLines = true, $skipEmptyLines = true)
- {
- $flags = 0;
- if ($stripNewLines) {
- $flags |= FILE_IGNORE_NEW_LINES;
- }
- if ($skipEmptyLines) {
- $flags |= FILE_SKIP_EMPTY_LINES;
- }
- if (($lines = @file($path, $flags)) === false) {
- throw new IOException("Failed to read lines from file: $path");
- }
- return $lines;
- }
- /**
- * Saves data to a file
- *
- * Note: Will also recursively create the directories if they do not yet exist
- *
- * @param string $path The file or directory path
- * @param mixed $data The file contents
- * @param bool $append Whether to append at the end of the file
- * @param bool $lock Whether to lock the file while saving
- *
- * @return int The amount of bytes saved
- *
- * @throws IOException When the directories cannot be created or writing to the file fails
- */
- public function saveFile($path, $data, $append = false, $lock = true)
- {
- $dir = dirname($path);
- if (!@is_dir($dir)) {
- if (!@mkdir($dir, 0777, true)) {
- throw new IOException("Failed to create directory: $dir");
- }
- }
- $flags = 0;
- if ($append) {
- $flags |= FILE_APPEND;
- }
- if ($lock) {
- $flags |= LOCK_EX;
- }
- if (($bytes = @file_put_contents($path, $data, $flags)) === false) {
- throw new IOException("Failed to save data to file: $path");
- }
- return $bytes;
- }
- /**
- * Scans a directory and returns the filenames it contains
- *
- * Valid sorting methods are: 'asc' and 'desc'
- *
- * @param string $path The file or directory path
- * @param string $sort The sorting method
- * @param string $pattern The matching pattern to filter filenames as a regular expression
- *
- * @return array The array of filenames
- *
- * @throws IOException When the contents of the directory cannot be fetched
- */
- public function scanDirectory($path, $sort = 'asc', $pattern = '.*')
- {
- $sort = strtolower($sort) === 'desc' ? SCANDIR_SORT_DESCENDING : SCANDIR_SORT_ASCENDING;
- if (($scan = @scandir($path, $sort)) === false) {
- throw new IOException("Failed to scan directory: $path");
- }
- foreach ($scan as $k => $v) {
- if ($v === '.' || $v === '..' || !preg_match($pattern, $v)) {
- unset($scan[$k]);
- }
- }
- return array_values($scan);
- }
- /**
- * Sets the access and modified time of the file or directory
- *
- * @param string $path The file or directory path
- * @param null|int $time The time as a Unix timestamp or null for current time
- *
- * @throws IOException When the file or directory cannot be touched
- */
- public function touch($path, $time = null)
- {
- if ($time === null) {
- $time = time();
- }
- if (!@touch($path, $time)) {
- throw new IOException("Failed to touch: $path");
- }
- }
- }