PHP Classes

File: src/helpers/File.php

Recommend this page to a friend!
  Classes of Corné de Jong   SouthCoast PHP Helpers Classes   src/helpers/File.php   Download  
File: src/helpers/File.php
Role: Auxiliary script
Content type: text/plain
Description: Auxiliary script
Class: SouthCoast PHP Helpers Classes
General purpose classes to help PHP development
Author: By
Last change: updates!
fixes and documentation
Added methods and more comments

- added getExtension
- added changeExtension
- added rename
- added move
Woop Woop, bunch of improvements
Shhit Ton Of Stuff!
further development of file helper
Updates To Env
Date: 19 hours ago
Size: 24,929 bytes
 

Contents

Class file image Download
<?php namespace SouthCoast\Helpers; use SouthCoast\Helpers\Error\FileError; class File { const BASE_DIRECTORY = 'base_directory'; const DIRECTORY_MAP_IDENTIFIER = '$'; const NOTHING = ''; const Minified = 'minify_contents'; /** * Holds the path to the base directory * * @var string */ protected static $base_directory = null; /** * Holds the directory mapping * * @var array */ protected static $directory_map = []; /** * Sets the base directory * * @param string $path */ public static function setBaseDirectory(string $path) { /* Check if the path is valid */ if (!Validate::path($path)) { throw new FileError(FileError::NOT_VALID_PATH, $path); } /* Check if the path leads to a directory */ if (!Validate::isDirectory($path)) { throw new FileError(FileError::NOT_A_DIRECTORY, $path); } /* Define the directory */ self::defineDirectory(File::BASE_DIRECTORY, $path); } /** * Lists all files and directories in the provided path * * @param string $path * @param string $extension * @param boolean $files_only * @param boolean $subtract_base_path * @return array * @throws FileError */ function list(string $path, string $extension = null, bool $files_only = true, bool $subtract_base_path = true): array { /* First get the full path */ $path = self::getPath($path); /* We can only list directories so check if this is one */ if (!Validate::isDirectory($path)) { throw new FileError(FileError::NOT_A_DIRECTORY, $path); } /* Build the query for the file listing */ if (is_null($extension)) { $query = $path . (($files_only) ? DIRECTORY_SEPARATOR . '*.*' : '*'); } else { $query = $path . DIRECTORY_SEPARATOR . '*' . ($extension ? '.' . $extension : ''); } /* Get the list */ $list = glob($query); /* Check if there was anything found */ if ($list === false) { /* if not, just return an empty array */ return []; } /* Check if we need to clean up the paths */ if ($subtract_base_path) { /* If so, strip the path from the list results */ $list = self::stripEachBasePath($path, $list); } /* Finally return the list */ return $list; } /** * Strips the base path from the full path * * @param string $path * @param array $list * @return array */ public static function stripEachBasePath(string $path, array $list): array { /* Loop over the provided list */ foreach ($list as &$subject) { /* Strip the base path from the item */ $subject = self::stripBasePath($path, $subject); } /* return the list */ return $list; } /** * Strips the base path from the full path * * @param string $base_path * @param string $subject */ public static function stripBasePath(string $base_path, string $subject): string { /* replace the base path by nothing in the to be striped value */ return str_replace($base_path . DIRECTORY_SEPARATOR, self::NOTHING, $subject); } /** * Checks if the directory identifier is known * * @param string $path * @return bool */ public static function isKnownDirectory(string $path): bool { /* Check if the path starts with the identifier token */ if (!StringHelper::startsWith(self::DIRECTORY_MAP_IDENTIFIER, $path)) { /* if not, simple, its not. return false */ return false; } /* Extract the identifier from the path */ $identifier = self::extractIdentifier($path); /* Check if the identifier is in the directory map, return a boolean */ return array_key_exists($identifier, self::$directory_map) ? true : false; } /** * Extracts the directory identifier from the provided path * * @param string $path * @return string */ public static function extractIdentifier(string $path): string { /* Get the first element in the provided path */ $identifier = explode(DIRECTORY_SEPARATOR, $path)[0]; /* Remove the identifier token */ $identifier = ltrim($identifier, self::DIRECTORY_MAP_IDENTIFIER); /* return the identifier */ return $identifier; } /** * Returns te full existing path to the file * Converts the identifier based paths into real paths * * @param string $path * @return string * @throws FileError */ public static function getPath(string $path): string { if (!StringHelper::startsWith(DIRECTORY_SEPARATOR, $path) && !StringHelper::startsWith(self::DIRECTORY_MAP_IDENTIFIER, $path)) { $path = '$' . self::BASE_DIRECTORY . DIRECTORY_SEPARATOR . $path; } /* Check if this is a predefined directory */ if (self::isKnownDirectory($path)) { /* get the real path to the directory */ $path = self::getRealPath($path); } /* Check if this is a valid path */ if (!Validate::path($path)) { throw new FileError(FileError::NOT_VALID_PATH, $path); } /* return the path */ return $path; } /** * Returns the real path to the identifier path * * Example: * File::getRealPath('$cache/some_cached_file.tmp') = '/path/to/cache/directory/some_cached_file.tmp'; * File::getRealPath('$cache') = '/path/to/cache/directory'; * * @param string $path The file or directory path based on the identifier * @return string The full actual path to the file or directory * @throws FileError If: UNKNOWN_DIRECTORY_IDENTIFIER */ public static function getRealPath(string $path): string { /* get the identifier */ $identifier = self::extractIdentifier($path); /* Check if this is a known identifier */ if (!self::isKnownIdentifier($identifier)) { throw new FileError(FileError::UNKNOWN_DIRECTORY_IDENTIFIER, $identifier); } /* Get the directory path from the identifier */ $directory_path = self::getPathFromIdentifier($identifier); /* Explode the provided path */ $path_array = explode(DIRECTORY_SEPARATOR, $path); /* Remove the Identifier */ array_shift($path_array); if (count($path_array) === 1) { return $directory_path . DIRECTORY_SEPARATOR . $path_array[0]; } /* Build and return the new Path from the directory path and the provided path */ return $directory_path . implode(DIRECTORY_SEPARATOR, $path_array); } /** * Checks if the identifier is known * * @param string $identifier * @return bool */ public static function isKnownIdentifier(string $identifier): bool { return array_key_exists($identifier, self::$directory_map); } /** * Cleans up the path to get a consistent format * * Example: * File::cleanUpPath('/foo/bar/foobar/') = '/foo/bar/foobar'; * * @param string $path The to-be cleaned path * @return string The cleaned path */ public static function cleanUpPath(string $path): string { if (StringHelper::endsWith(DIRECTORY_SEPARATOR, $path)) { $path = rtrim($path, DIRECTORY_SEPARATOR); } return $path; } /** * Returns the path associated with the identifier * * @param string $identifier The directory identifier * @return string The full path to the directory * @throws FileError If: UNKNOWN_DIRECTORY_IDENTIFIER */ public static function getPathFromIdentifier(string $identifier): string { /* Lets make sure its a known directory */ if (!self::isKnownIdentifier($identifier)) { throw new FileError(FileError::UNKNOWN_DIRECTORY_IDENTIFIER, $identifier); } /* Get the path associated with this identifier */ return self::$directory_map[$identifier]; } /** * Defines a directory by its identifier * * Example: * File::defineDirectory('$cache', '/the/full/path/to/the/dir'); * * @param string $identifier The directory identifier * @param string $path The full path to the directory * @return void * @throws FileError If: NOT_VALID_PATH, NOT_A_DIRECTORY, IDENTIFIER_ALREADY_IN_USE */ public static function defineDirectory(string $identifier, string $path) { /* First clean up the path */ $path = self::cleanUpPath($path); /* Check if the path is valid */ if (!Validate::path($path)) { throw new FileError(FileError::NOT_VALID_PATH, $path); } /* Check if the path is a directory */ if (!Validate::isDirectory($path)) { throw new FileError(FileError::NOT_A_DIRECTORY, $path); } /* Check if this is an already known identifier */ if (self::isKnownIdentifier($identifier)) { throw new FileError(FileError::IDENTIFIER_ALREADY_IN_USE, $identifier); } /* If the identifier is the base directory */ if ($identifier === File::BASE_DIRECTORY) { /* Add it to the base directory */ self::$base_directory = $path; } /* Add it to the directory map */ self::$directory_map[$identifier] = $path; } /** * Loads a directory map from array * * @param array $map * @return void */ public static function loadDirectoryMap(array $map) { /* Loop over all the entries */ foreach ($map as $identifier => $path) { /* Define each directory */ self::defineDirectory($identifier, $path); } } /** * Removes all defined paths * * @param bool $removeBasePath * @return void */ public static function clearDirectoryMap(bool $removeBasePath = false) { /* Save the base path */ $base_directory_path = self::$directory_map[self::BASE_DIRECTORY]; /* Empty the mapping */ self::$directory_map = []; /* Check if we need to keep the base directory */ if (!$removeBasePath) { /* Set the base path again */ self::defineDirectory(self::BASE_DIRECTORY, $base_directory_path); } } /** * Recursively removed a directory. * * @param string $directory The to-be removed directory * @return bool */ private static function recursiveRemoveDirectory(string $directory) { /* Fist get the actual path */ $directory = self::getPath($directory); /* If it's not a directory */ if (!Validate::isDirectory($directory)) { return false; } /* Loop over all the items in the directory */ foreach (self::list($directory, null, false, false) as $path) { /* Check if it's a directory */ if (Validate::isDirectory($path)) { /* Recursively call this method */ File::recursiveRemoveDirectory($path); } else { /* Else, unlink the file */ File::delete($path); } } /* Finally remove the directory itself */ return @rmdir($directory); } /** * Performs a recursive listing. * Returns a list of all files in the provided directory and sub directories. * * @param string $directory The to be scanned directory * @param string $pattern The REGEX search pattern * @return array The list of all directories and files. */ protected static function recursiveList(string $directory, string $pattern = '/.*$/'): array { /* Get the real path to the directory */ $path = self::getPath($directory); /* Create a new Recursive directory object */ $recursive_directory = new RecursiveDirectoryIterator($path); /* Create a new Recursive Iterator object */ $iterator_object = new RecursiveIteratorIterator($recursive_directory); /* Setup the filter pattern and perform it on all the files in the provided directory */ $expression_result = new RegexIterator($iterator_object, $pattern, RegexIterator::GET_MATCH); /* Initialize the list variable */ $list = []; /* Loop over all the directories */ foreach ($expression_result as $files) { /* add the files to the file list */ $list = array_merge($list, $files); } /* Garbage Collection */ unset($recursive_directory, $iterator_object, $expression_result); /* Return the list */ return $list; } /** * Get the extension of a file * * Example: * File::getExtension('$base_directory/myAwesomeFile.txt') = 'txt'; * File::getExtension('$cache_directory/some_cached_file') = null; * * @param string $file The file for which you want the extension * @return string|null Returns a string with the extension, null if non found */ public function getExtension(string $file) { /* Get the real path to the directory */ $path = self::getPath($file); /* Get the path info */ $pathinfo = pathinfo($path); /* Return the filename or null if not present */ return $pathinfo['extension'] ?? null; } /** * Change the extension of an existing file * * Example: * File::changeExtension('$base_directory/LOG_1234.log', 'txt'); * * @param string $file The to be changed file * @param string $new_extension The new file extension * @return bool Returns true is all went good, false if not */ public function changeExtension(string $file, string $new_extension): bool { /* Get the real path to the directory */ $path = self::getPath($file); /* Get the file extension */ $extension = self::getExtension($path); /* Add the new extension */ $new_path = (!is_null($extension) ? rtrim($path, $extension) : $path . '.') . $new_extension; /* rename the file to reflect the new extension and return the result */ return rename($path, $new_path); } /** * @param string $file */ public static function getFilename(string $file) { /* Get the real path to the directory */ $path = self::getPath($file); /* Get the path info */ $pathinfo = pathinfo($path); /* Return the filename */ return $pathinfo['filename']; } /** * Rename an existing file * * Example: * File::rename('$base_directory/myAwesomeFile.md', 'myNotSoAwesomeFile'); * * @param string $file The to-be renamed file * @param string $new_name The new file name (no extension) * @return bool Returns true is all went good, false if not */ public static function rename(string $file, string $new_name): bool { /* Get the real path to the directory */ $path = self::getPath($file); /* Get the file extension */ $extension = self::getExtension($path); /* Get the base path to the file */ $base_path = str_replace(basename($path), '', $path); /* Rename the file and return the result */ return rename($path, $base_path . $new_name . ($extension ? '.' . $extension : '')); } /** * Move an existing file to a new location * * Example: * File::move('$base_directory/myAwesomeFile.txt', '$some_other_directory'); * * @param string $file The to-be moved file * @param string $new_location The new directory (no file name should be present) * @return bool Returns true is all went good, false if not */ public static function move(string $file, string $new_location): bool { /* Get the real path to the original directory */ $path = self::getPath($file); /* Get the real path to the new directory and append the filename */ $new_path = self::getPath($new_location) . basename($path); /* move the file to the new location and return the result */ return rename($path, $new_path); } /** * Deletes a file or directory. * Directories will be removed recursively. * All files and sub directories wil also be deleted! * * @param string $path The to-be deleted path * @return bool The status of the deletion * @throws FileError If: NEITHER_FILE_NOR_DIRECTORY */ public static function delete(string $path): bool { /* Get the real path to the directory or file */ $path = self::getPath($path); if (Validate::isDirectory($path)) { return self::recursiveRemoveDirectory($path); } if (Validate::isFile($path)) { return self::deleteFile($path); } throw new FileError(FileError::NEITHER_FILE_NOR_DIRECTORY, $path); } /** * @param string $path */ public static function deleteFile(string $path): bool { /* Get the real path to the directory or file */ $path = self::getPath($path); /* Check if the path leads to a file */ if (!Validate::isFile($path)) { throw new FileError(FileError::NOT_A_FILE, $path); } /* unlink the file */ return unlink($path); } /** * Returns an array that describes the file * * @param string $file The file that's need to be described * @return array An array with the file description */ public static function describe(string $file): array { /* Get the real path to the file */ $path = self::getPath($file); if (!Validate::isFile($path)) { throw new FileError(FileError::NOT_A_FILE, $path); } return [ 'filename' => self::getFilename($path), 'extension' => self::getExtension($path), 'type' => filetype($path) ?? 'unknown', 'size' => filesize($path), 'last_access' => fileatime($path), 'last_change' => filectime($path), 'last_modified' => filemtime($path), 'permissions' => substr(sprintf('%o', fileperms($path)), -4), 'owner' => fileowner($path), 'group' => filegroup($path), ]; } /** * SETTERS */ /** * Returns an instantiated stream object with read permissions to the file. * * @param string $file The to-be read file * @param string $mode The mode which you want to open the file in * @return Objects\Stream The instantiated file stream */ public static function stream(string $file, $mode = 'r'): Objects\Stream { return new Objects\Stream($file, $mode); } /** * Returns an instantiated stream object with read permissions to the file. * * @param string $file The to-be read file * @return Objects\Stream The instantiated file stream */ public static function readStream(string $file): Objects\Stream { return new Objects\Stream($file); } /** * Returns an instantiated stream object with write permissions to the file. * * @param string $file The to-be written file * @param string $mode The mode which you want to open the file in * @return Objects\Stream The instantiated file stream */ public static function writeStream(string $file, string $mode = 'w+'): Objects\Stream { return new Objects\Stream($file, $mode); } /** * @param $path */ public static function get($path) { /* Get the real path to the original directory */ $path = self::getPath($path); /* Get the contents from the file */ $content = file_get_contents($path); /* Return the contents or null if there was an error */ return $content === false ? null : $content; } /** * @param $path */ public static function getAsArray($path, $flags = null, $context = null) { /* Get the real path to the original directory */ $path = self::getPath($path); /* Read the file into an array */ return file($path, $flags, $context); } /** * @param string $path * @param bool $returnObject */ public static function getJson(string $path, bool $returnObject = true) { return Json::parse(self::get($path), ($returnObject) ? false : true); } /** * Reads the content of a file and parses it as CSV. * * @param string $path The path to the csv file * @param bool|array $hasHeaders If the file contains headers. Or pass an array with the headers. * @param string $delimiter The delimiter that is used in the file * @param string $enclosure The enclosing character * @return array The parsed csv file */ public static function getCsv(string $path, $hasHeaders = true, string $delimiter = ',', string $enclosure = null) { /* Get the real path to the original directory */ $path = self::getPath($path); $content = File::getAsArray($path); if (is_array($hasHeaders)) { $headers = $hasHeaders; $hasHeaders = true; } if (is_bool($hasHeaders) && $hasHeaders) { $headers = self::parseCsvLine(array_shift($content), $delimiter, $enclosure); } $array = []; foreach ($content as $line) { if ($hasHeaders) { $array[] = ArrayHelper::combineAndFill($headers, self::parseCsvLine($line, $delimiter, $enclosure)); } if (!$hasHeaders) { $array[] = self::parseCsvLine($line, $delimiter, $enclosure); } } return $array; } /** * @param string $line * @param string $delimiter * @param string $enclosure */ public static function parseCsvLine(string $line, string $delimiter = ',', string $enclosure = null): array { /* Explode the line by the delimiter */ $line_array = explode($delimiter, $line); /* Loop over all the fields in the line */ foreach ($line_array as &$value) { if ($enclosure !== null || $enclosure !== '') /* Trim the enclosure */ { $value = trim($value, $enclosure); } if (Number::isFloat($value)) { $value = (float) $value; } if (Number::isInteger($value)) { $value = (int) $value; } if (strtolower($value) === 'true') { $value = true; } if (strtolower($value) === 'false') { $value = false; } if (strtolower($value) === 'null') { $value = null; } } return $line_array; } public static function getBasePath() { return self::getPathFromIdentifier(self::BASE_DIRECTORY); } /** * @param string $path * @param string $directory */ public function makeDirectory(string $path, string $directory) { /* Get the real path to the original directory */ $path = self::getPath($path); /* Format the new path */ $directory_path = $path . DIRECTORY_SEPARATOR . $directory; /* Create the directory */ mkdir($directory_path); /* Check if it now is there and return the result */ return Validate::path($directory_path) && Validate::isDirectory($directory_path) ? true : false; } /** * @param $path * @param $structure */ public function makeDirectoryStructure(string $path, array $structure) { $directory = ArrayHelper::firstKey($structure); } /** * GETTERS */ }