From 62d00d276915c8bd14a8623794a26051b59e70ca Mon Sep 17 00:00:00 2001 From: Netkas Date: Sat, 25 Feb 2023 00:52:11 -0500 Subject: [PATCH] Added \TempFile\TempFile --- src/TempFile/TempFile.php | 207 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) diff --git a/src/TempFile/TempFile.php b/src/TempFile/TempFile.php index 7ad7c06..e7dad6e 100644 --- a/src/TempFile/TempFile.php +++ b/src/TempFile/TempFile.php @@ -1,8 +1,215 @@ extension = ltrim($extension, '.'); + $this->filename = $this->randomString() . '.' . $this->extension; + $this->filepath = $this->getTempDir() . DIRECTORY_SEPARATOR . $this->filename; + + if(!file_exists($this->filepath)) + { + touch($this->filepath); + } + + if(!is_writable($this->filepath)) + { + throw new Exception('Unable to create temporary file'); + } + + self::$temporary_files[] = $this->filepath; + + if(!self::$shutdown_handler_registered && function_exists('register_shutdown_function')) + { + register_shutdown_function([self::class, 'shutdownHandler']); + self::$shutdown_handler_registered = true; + } + } + + /** + * Generates a random string of a given length + * + * @return string + */ + private function randomString(): string + { + $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + $charactersLength = strlen($characters); + $randomString = ''; + for ($i = 0; $i < 32; $i++) + { + $randomString .= $characters[rand(0, $charactersLength - 1)]; + } + return $randomString; + } + + /** + * Attempts to get the temporary directory + * + * @return string + * @throws Exception + */ + private function getTempDir(): string + { + if(function_exists('sys_get_temp_dir')) + { + return sys_get_temp_dir(); + } + + $paths = [ + DIRECTORY_SEPARATOR . 'tmp', + DIRECTORY_SEPARATOR . 'var' . DIRECTORY_SEPARATOR . 'tmp' + ]; + + foreach($paths as $path) + { + if(is_dir($path) && is_writable($path)) + { + return $path; + } + } + + try + { + return Runtime::getDataPath('net.nosial.tempfile'); + } + catch(Exception $e) + { + unset($e); + } + + $local_tmp = getcwd() . DIRECTORY_SEPARATOR . 'temp'; + + if(is_writeable(getcwd())) + { + if(!is_dir($local_tmp)) + { + mkdir($local_tmp); + } + + return $local_tmp; + } + + throw new Exception('Unable to find a suitable temporary directory'); + } + + /** + * Returns the name of the temporary file + * + * @return string + */ + public function getFilename(): string + { + return $this->filename; + } + + /** + * Returns the absolute path to the temporary file + * + * @return string + */ + public function getFilepath(): string + { + return $this->filepath; + } + + /** + * Returns the filepath of the temporary file + * + * @return string + */ + public function __toString(): string + { + return $this->filepath; + } + + /** + * Handles the shutdown event by deleting all temporary files if the destructors have not been called + * + * @return void + */ + private static function shutdownHandler(): void + { + if(count(self::$temporary_files) == 0) + { + return; + } + + foreach(self::$temporary_files as $file) + { + if(file_exists($file) && is_writable($file)) + { + @unlink($file); + unset(self::$temporary_files[$file]); + } + } + } + + /** + * Deletes the temporary file + */ + public function __destruct() + { + if(file_exists($this->filepath)) + { + if(!is_writeable($this->filepath)) + { + trigger_error(sprintf('Unable to delete temporary file %s', $this->filepath), E_USER_WARNING); + return; + } + + unlink($this->filepath); + unset(self::$temporary_files[$this->filepath]); + } + } } \ No newline at end of file