-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[2.8][Filesystem] Changed dumpFile to allow dumping to streams... #14970
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,11 @@ | ||
CHANGELOG | ||
========= | ||
|
||
2.8.0 | ||
----- | ||
|
||
* added tempnam() a stream aware version of PHP's native tempnam() | ||
|
||
2.6.0 | ||
----- | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -448,6 +448,53 @@ public function isAbsolutePath($file) | |
); | ||
} | ||
|
||
/** | ||
* Creates a temporary file with support for custom stream wrappers. | ||
* | ||
* @param string $dir The directory where the temporary filename will be created. | ||
* @param string $prefix The prefix of the generated temporary filename. | ||
* Note: Windows uses only the first three characters of prefix. | ||
* | ||
* @return string The new temporary filename (with path), or false on failure. | ||
*/ | ||
public function tempnam($dir, $prefix) | ||
{ | ||
$limit = 10; | ||
list($scheme, $hierarchy) = $this->getSchemeAndHierarchy($dir); | ||
|
||
// If no scheme or scheme is "file" create temp file in local filesystem | ||
if (null === $scheme || 'file' === $scheme) { | ||
$tmpFile = tempnam($hierarchy, $prefix); | ||
|
||
// If tempnam failed or no scheme return the filename otherwise prepend the scheme | ||
return false === $tmpFile || null === $scheme ? $tmpFile : $scheme.'://'.$tmpFile; | ||
} | ||
|
||
// Loop until we create a valid temp file or have reached $limit attempts | ||
for ($i = 0; $i < $limit; $i++) { | ||
|
||
// Create a unique filename | ||
$tmpFile = $dir.'/'.$prefix.uniqid(mt_rand(), true); | ||
|
||
// Use fopen instead of file_exists as some streams do not support stat | ||
// Use mode 'x' to atomically check existence and create to avoid a TOCTOU vulnerability | ||
$handle = @fopen($tmpFile, 'x'); | ||
|
||
// If unsuccessful restart the loop | ||
if (false === $handle) { | ||
continue; | ||
} | ||
|
||
// Close the file if it was successfully opened | ||
@fclose($handle); | ||
|
||
return $tmpFile; | ||
|
||
} | ||
|
||
return false; | ||
} | ||
|
||
/** | ||
* Atomically dumps content into a file. | ||
* | ||
|
@@ -468,7 +515,7 @@ public function dumpFile($filename, $content, $mode = 0666) | |
throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir); | ||
} | ||
|
||
$tmpFile = tempnam($dir, basename($filename)); | ||
$tmpFile = $this->tempnam($dir, basename($filename)); | ||
|
||
if (false === @file_put_contents($tmpFile, $content)) { | ||
throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename); | ||
|
@@ -497,4 +544,19 @@ private function toIterator($files) | |
|
||
return $files; | ||
} | ||
|
||
/** | ||
* Gets a 2-tuple of scheme (may be null) and hierarchical part of a filename (e.g. file:///tmp -> array(file, tmp)). | ||
* | ||
* @param string $filename The filename to be parsed. | ||
* | ||
* @return array The filename scheme and hierarchical part | ||
*/ | ||
private function getSchemeAndHierarchy($filename) | ||
{ | ||
$components = explode('://', $filename, 2); | ||
|
||
return count($components) >= 2 ? array($components[0], $components[1]) : array(null, $components[0]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you can compare using |
||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,11 +30,15 @@ $filesystem->rename($origin, $target); | |
|
||
$filesystem->symlink($originDir, $targetDir, $copyOnWindows = false); | ||
|
||
$filesystem->tempnam($dir, $prefix); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should be removed as we only document "major" features in READMEs. |
||
|
||
$filesystem->makePathRelative($endPath, $startPath); | ||
|
||
$filesystem->mirror($originDir, $targetDir, \Traversable $iterator = null, $options = array()); | ||
|
||
$filesystem->isAbsolutePath($file); | ||
|
||
$filesystem->dumpFile($file, $content); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same here |
||
``` | ||
|
||
Resources | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be better to throw an exception if an error occurred instead of silently fail and return a magic return value (same below).