isDir()) { rmdir($file->getRealPath()); } else { unlink($file->getRealPath()); } } return rmdir($folderPath); } /** * @param string $folderPath * @throws IOException */ public static function createFolder(string $folderPath){ // We don't need to create a folder if it already exists. if(file_exists($folderPath) === true){ return; } self::checkWrite($folderPath); // Check if the data_directory exists or create one. if (!file_exists($folderPath) && !mkdir($folderPath, 0777, true) && !is_dir($folderPath)) { throw new IOException( 'Unable to create the a directory at ' . $folderPath ); } } /** * @param string $filePath * @param Closure $updateContentFunction Has to return a string or an array that will be encoded to json. * @return string * @throws IOException * @throws JsonException */ public static function updateFileContent(string $filePath, Closure $updateContentFunction): string { self::checkRead($filePath); self::checkWrite($filePath); $content = false; $fp = fopen($filePath, 'rb'); if(flock($fp, LOCK_SH)){ $content = stream_get_contents($fp); } flock($fp, LOCK_UN); fclose($fp); if($content === false){ throw new IOException("Could not get shared lock for file: $filePath"); } $content = $updateContentFunction($content); if(!is_string($content)){ $encodedContent = json_encode($content); if($encodedContent === false){ $content = (!is_object($content) && !is_array($content) && !is_null($content)) ? $content : gettype($content); throw new JsonException("Could not encode content with json_encode. Content: \"$content\"."); } $content = $encodedContent; } if(file_put_contents($filePath, $content, LOCK_EX) === false){ throw new IOException("Could not write content to file. Please check permissions at: $filePath"); } return $content; } /** * @param string $filePath * @return bool */ public static function deleteFile(string $filePath): bool { if(false === file_exists($filePath)){ return true; } try{ self::checkWrite($filePath); }catch(Exception $exception){ return false; } return (@unlink($filePath) && !file_exists($filePath)); } /** * @param array $filePaths * @return bool */ public static function deleteFiles(array $filePaths): bool { foreach ($filePaths as $filePath){ // if a file does not exist, we do not need to delete it. if(true === file_exists($filePath)){ try{ self::checkWrite($filePath); if(false === @unlink($filePath) || file_exists($filePath)){ return false; } } catch (Exception $exception){ // TODO trigger a warning or exception return false; } } } return true; } /** * Strip string for secure file access. * @param string $string * @return string */ public static function secureStringForFileAccess(string $string): string { return (str_replace(array(".", "/", "\\"), "", $string)); } /** * Appends a slash ("/") to the given directory path if there is none. * @param string $directory */ public static function normalizeDirectory(string &$directory){ if(!empty($directory) && substr($directory, -1) !== "/") { $directory .= "/"; } } /** * Returns the amount of files in folder. * @param string $folder * @return int * @throws IOException */ public static function countFolderContent(string $folder): int { self::checkRead($folder); $fi = new \FilesystemIterator($folder, \FilesystemIterator::SKIP_DOTS); return iterator_count($fi); } }