Changeset View
Changeset View
Standalone View
Standalone View
src/filesystem/TempFile.php
- This file was added.
| <?php | |||||
| /** | |||||
| * Simple wrapper to create a temporary file and guarantee it will be deleted on | |||||
| * object destruction. Used like a string to path: | |||||
| * | |||||
| * $temp = new TempFile(); | |||||
| * Filesystem::writeFile($temp, 'Hello World'); | |||||
| * echo "Wrote data to path: ".$temp; | |||||
| * | |||||
| * Throws Filesystem exceptions for errors. | |||||
| * | |||||
| * @task create Creating a Temporary File | |||||
| * @task config Configuration | |||||
| * @task internal Internals | |||||
| */ | |||||
| final class TempFile extends Phobject { | |||||
| private $dir; | |||||
| private $file; | |||||
| private $preserve; | |||||
| private $destroyed = false; | |||||
| /* -( Creating a Temporary File )------------------------------------------ */ | |||||
| /** | |||||
| * Create a new temporary file. | |||||
| * | |||||
| * @param string? Filename hint. This is useful if you intend to edit the | |||||
| * file with an interactive editor, so the user's editor shows | |||||
| * "commit-message" instead of "p3810hf-1z9b89bas". | |||||
| * @param string? Root directory to hold the file. If omitted, the system | |||||
| * temporary directory (often "/tmp") will be used by default. | |||||
| * @task create | |||||
| */ | |||||
| public function __construct($filename = null, $root_directory = null) { | |||||
| $this->dir = Filesystem::createTemporaryDirectory( | |||||
| '', | |||||
| 0700, | |||||
| $root_directory); | |||||
| if ($filename === null) { | |||||
| $this->file = tempnam($this->dir, getmypid().'-'); | |||||
| } else { | |||||
| $this->file = $this->dir.'/'.$filename; | |||||
| } | |||||
| // If we fatal (e.g., call a method on NULL), destructors are not called. | |||||
| // Make sure our destructor is invoked. | |||||
| register_shutdown_function(array($this, '__destruct')); | |||||
| Filesystem::writeFile($this, ''); | |||||
| } | |||||
| /* -( Configuration )------------------------------------------------------ */ | |||||
| /** | |||||
| * Normally, the file is deleted when this object passes out of scope. You | |||||
| * can set it to be preserved instead. | |||||
| * | |||||
| * @param bool True to preserve the file after object destruction. | |||||
| * @return this | |||||
| * @task config | |||||
| */ | |||||
| public function setPreserveFile($preserve) { | |||||
| $this->preserve = $preserve; | |||||
| return $this; | |||||
| } | |||||
| /* -( Internals )---------------------------------------------------------- */ | |||||
| /** | |||||
| * Get the path to the temporary file. Normally you can just use the object | |||||
| * in a string context. | |||||
| * | |||||
| * @return string Absolute path to the temporary file. | |||||
| * @task internal | |||||
| */ | |||||
| public function __toString() { | |||||
| return $this->file; | |||||
| } | |||||
| /** | |||||
| * When the object is destroyed, it destroys the temporary file. You can | |||||
| * change this behavior with @{method:setPreserveFile}. | |||||
| * | |||||
| * @task internal | |||||
| */ | |||||
| public function __destruct() { | |||||
| if ($this->destroyed) { | |||||
| return; | |||||
| } | |||||
| if ($this->preserve) { | |||||
| return; | |||||
| } | |||||
| Filesystem::remove($this->dir); | |||||
| // NOTE: tempnam() doesn't guarantee it will return a file inside the | |||||
| // directory you passed to the function, so we make sure to nuke the file | |||||
| // explicitly. | |||||
| Filesystem::remove($this->file); | |||||
| $this->file = null; | |||||
| $this->dir = null; | |||||
| $this->destroyed = true; | |||||
| } | |||||
| } | |||||