- Patch #701358 by aaron, quicksketch, chx, pwolanin, aspilicious: the file API presumes a hiearchical file storage.
parent
45dc99c832
commit
d689318629
|
@ -165,6 +165,8 @@ function file_stream_wrapper_get_class($scheme) {
|
|||
* @return
|
||||
* A string containing the name of the scheme, or FALSE if none. For example,
|
||||
* the URI "public://example.txt" would return "public".
|
||||
*
|
||||
* @see file_uri_target()
|
||||
*/
|
||||
function file_uri_scheme($uri) {
|
||||
$data = explode('://', $uri, 2);
|
||||
|
@ -205,18 +207,14 @@ function file_stream_wrapper_valid_scheme($scheme) {
|
|||
* A string containing the target (path), or FALSE if none.
|
||||
* For example, the URI "public://sample/test.txt" would return
|
||||
* "sample/test.txt".
|
||||
*
|
||||
* @see file_uri_scheme()
|
||||
*/
|
||||
function file_uri_target($uri) {
|
||||
$data = explode('://', $uri, 2);
|
||||
|
||||
if (count($data) != 2) {
|
||||
return FALSE;
|
||||
if ($scheme = file_uri_scheme($uri)) {
|
||||
return file_stream_wrapper_get_instance_by_scheme($scheme)->getTarget($uri);
|
||||
}
|
||||
|
||||
// Remove erroneous beginning forward slash.
|
||||
$data[1] = ltrim($data[1], '\/');
|
||||
|
||||
return $data[1];
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -225,7 +223,6 @@ function file_uri_target($uri) {
|
|||
* A stream is referenced as "scheme://target".
|
||||
*
|
||||
* The following actions are taken:
|
||||
* - Remove all occurrences of the wrapper's directory path
|
||||
* - Remove trailing slashes from target
|
||||
* - Trim erroneous leading slashes from target. e.g. ":///" becomes "://".
|
||||
*
|
||||
|
@ -240,15 +237,9 @@ function file_stream_wrapper_uri_normalize($uri) {
|
|||
if ($scheme && file_stream_wrapper_valid_scheme($scheme)) {
|
||||
$target = file_uri_target($uri);
|
||||
|
||||
// Remove all occurrences of the wrapper's directory path.
|
||||
$directory_path = file_stream_wrapper_get_instance_by_scheme($scheme)->getDirectoryPath();
|
||||
$target = str_replace($directory_path, '', $target);
|
||||
|
||||
// Trim trailing slashes from target.
|
||||
$target = rtrim($target, '/');
|
||||
|
||||
// Trim erroneous leading slashes from target.
|
||||
$uri = $scheme . '://' . ltrim($target, '/');
|
||||
if ($target !== FALSE) {
|
||||
$uri = $scheme . '://' . $target;
|
||||
}
|
||||
}
|
||||
return $uri;
|
||||
}
|
||||
|
@ -1880,14 +1871,7 @@ function drupal_dirname($uri) {
|
|||
$scheme = file_uri_scheme($uri);
|
||||
|
||||
if ($scheme && file_stream_wrapper_valid_scheme($scheme)) {
|
||||
$target = file_uri_target($uri);
|
||||
$dirname = dirname($target);
|
||||
|
||||
if ($dirname == '.') {
|
||||
$dirname = '';
|
||||
}
|
||||
|
||||
return $scheme . '://' . $dirname;
|
||||
return file_stream_wrapper_get_instance_by_scheme($scheme)->dirname($uri);
|
||||
}
|
||||
else {
|
||||
return dirname($uri);
|
||||
|
|
|
@ -145,6 +145,24 @@ interface DrupalStreamWrapperInterface extends StreamWrapperInterface {
|
|||
*/
|
||||
public function getExternalUrl();
|
||||
|
||||
/**
|
||||
* Returns the local writable target of the resource within the stream.
|
||||
*
|
||||
* This function should be used in place of calls to realpath() or similar
|
||||
* functions when attempting to determine the location of a file. While
|
||||
* functions like realpath() may return the location of a read-only file, this
|
||||
* method may return a URI or path suitable for writing that is completely
|
||||
* separate from the URI used for reading.
|
||||
*
|
||||
* @param $uri
|
||||
* Optional URI.
|
||||
*
|
||||
* @return
|
||||
* Returns a string representing a location suitable for writing of a file,
|
||||
* or FALSE if unable to write to the file such as with read-only streams.
|
||||
*/
|
||||
public function getTarget($uri = NULL);
|
||||
|
||||
/**
|
||||
* Returns the MIME type of the resource.
|
||||
*
|
||||
|
@ -155,6 +173,7 @@ interface DrupalStreamWrapperInterface extends StreamWrapperInterface {
|
|||
* - 'mimetypes': a list of mimetypes, keyed by an identifier,
|
||||
* - 'extensions': the mapping itself, an associative array in which
|
||||
* the key is the extension and the value is the mimetype identifier.
|
||||
*
|
||||
* @return
|
||||
* Returns a string containing the MIME type of the resource.
|
||||
*/
|
||||
|
@ -169,6 +188,7 @@ interface DrupalStreamWrapperInterface extends StreamWrapperInterface {
|
|||
* @param $mode
|
||||
* Integer value for the permissions. Consult PHP chmod() documentation
|
||||
* for more information.
|
||||
*
|
||||
* @return
|
||||
* Returns TRUE on success or FALSE on failure.
|
||||
*/
|
||||
|
@ -187,6 +207,23 @@ interface DrupalStreamWrapperInterface extends StreamWrapperInterface {
|
|||
* wrapper does not provide an implementation.
|
||||
*/
|
||||
public function realpath();
|
||||
|
||||
/**
|
||||
* Gets the name of the directory from a given path.
|
||||
*
|
||||
* This method is usually accessed through drupal_dirname(), which wraps
|
||||
* around the normal PHP dirname() function, which does not support stream
|
||||
* wrappers.
|
||||
*
|
||||
* @param $uri
|
||||
* An optional URI.
|
||||
*
|
||||
* @return
|
||||
* A string containing the directory name, or FALSE if not applicable.
|
||||
*
|
||||
* @see drupal_dirname()
|
||||
*/
|
||||
public function dirname($uri = NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -227,6 +264,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
|||
|
||||
/**
|
||||
* Gets the path that the wrapper is responsible for.
|
||||
* @TODO: Review this method name in D8 per http://drupal.org/node/701358
|
||||
*
|
||||
* @return
|
||||
* String specifying the path.
|
||||
|
@ -247,6 +285,20 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
|||
return $this->uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Base implementation of getTarget().
|
||||
*/
|
||||
function getTarget($uri = NULL) {
|
||||
if (!isset($uri)) {
|
||||
$uri = $this->uri;
|
||||
}
|
||||
|
||||
list($scheme, $target) = explode('://', $uri, 2);
|
||||
|
||||
// Remove erroneous leading or trailing, forward-slashes and backslashes.
|
||||
return trim($target, '\/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Base implementation of getMimeType().
|
||||
*/
|
||||
|
@ -303,7 +355,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
|||
if (!isset($uri)) {
|
||||
$uri = $this->uri;
|
||||
}
|
||||
$path = $this->getDirectoryPath() . '/' . file_uri_target($uri);
|
||||
$path = $this->getDirectoryPath() . '/' . $this->getTarget($uri);
|
||||
$realpath = realpath($path);
|
||||
if (!$realpath) {
|
||||
// This file does not yet exist.
|
||||
|
@ -327,8 +379,10 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
|||
* A bit mask of STREAM_USE_PATH and STREAM_REPORT_ERRORS.
|
||||
* @param &$opened_path
|
||||
* A string containing the path actually opened.
|
||||
*
|
||||
* @return
|
||||
* Returns TRUE if file was opened successfully.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.stream-open.php
|
||||
*/
|
||||
public function stream_open($uri, $mode, $options, &$opened_path) {
|
||||
|
@ -353,8 +407,10 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
|||
* - LOCK_UN to release a lock (shared or exclusive).
|
||||
* - LOCK_NB if you don't want flock() to block while locking (not
|
||||
* supported on Windows).
|
||||
*
|
||||
* @return
|
||||
* Always returns TRUE at the present time.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.stream-lock.php
|
||||
*/
|
||||
public function stream_lock($operation) {
|
||||
|
@ -370,8 +426,10 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
|||
*
|
||||
* @param $count
|
||||
* Maximum number of bytes to be read.
|
||||
*
|
||||
* @return
|
||||
* The string that was read, or FALSE in case of an error.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.stream-read.php
|
||||
*/
|
||||
public function stream_read($count) {
|
||||
|
@ -383,8 +441,10 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
|||
*
|
||||
* @param $data
|
||||
* The string to be written.
|
||||
*
|
||||
* @return
|
||||
* The number of bytes written (integer).
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.stream-write.php
|
||||
*/
|
||||
public function stream_write($data) {
|
||||
|
@ -396,6 +456,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
|||
*
|
||||
* @return
|
||||
* TRUE if end-of-file has been reached.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.stream-eof.php
|
||||
*/
|
||||
public function stream_eof() {
|
||||
|
@ -409,8 +470,10 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
|||
* The byte offset to got to.
|
||||
* @param $whence
|
||||
* SEEK_SET, SEEK_CUR, or SEEK_END.
|
||||
*
|
||||
* @return
|
||||
* TRUE on success.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.stream-seek.php
|
||||
*/
|
||||
public function stream_seek($offset, $whence) {
|
||||
|
@ -422,6 +485,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
|||
*
|
||||
* @return
|
||||
* TRUE if data was successfully stored (or there was no data to store).
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.stream-flush.php
|
||||
*/
|
||||
public function stream_flush() {
|
||||
|
@ -433,6 +497,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
|||
*
|
||||
* @return
|
||||
* The current offset in bytes from the beginning of file.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.stream-tell.php
|
||||
*/
|
||||
public function stream_tell() {
|
||||
|
@ -445,6 +510,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
|||
* @return
|
||||
* An array with file status, or FALSE in case of an error - see fstat()
|
||||
* for a description of this array.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.stream-stat.php
|
||||
*/
|
||||
public function stream_stat() {
|
||||
|
@ -456,6 +522,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
|||
*
|
||||
* @return
|
||||
* TRUE if stream was successfully closed.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.stream-close.php
|
||||
*/
|
||||
public function stream_close() {
|
||||
|
@ -467,8 +534,10 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
|||
*
|
||||
* @param $uri
|
||||
* A string containing the uri to the resource to delete.
|
||||
*
|
||||
* @return
|
||||
* TRUE if resource was successfully deleted.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.unlink.php
|
||||
*/
|
||||
public function unlink($uri) {
|
||||
|
@ -483,14 +552,43 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
|||
* The uri to the file to rename.
|
||||
* @param $to_uri
|
||||
* The new uri for file.
|
||||
*
|
||||
* @return
|
||||
* TRUE if file was successfully renamed.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.rename.php
|
||||
*/
|
||||
public function rename($from_uri, $to_uri) {
|
||||
return rename($this->getLocalPath($from_uri), $this->getLocalPath($to_uri));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the directory from a given path.
|
||||
*
|
||||
* This method is usually accessed through drupal_dirname(), which wraps
|
||||
* around the PHP dirname() function because it does not support stream
|
||||
* wrappers.
|
||||
*
|
||||
* @param $uri
|
||||
* A URI or path.
|
||||
*
|
||||
* @return
|
||||
* A string containing the directory name.
|
||||
*
|
||||
* @see drupal_dirname()
|
||||
*/
|
||||
public function dirname($uri = NULL) {
|
||||
list($scheme, $target) = explode('://', $uri, 2);
|
||||
$target = $this->getTarget($uri);
|
||||
$dirname = dirname($target);
|
||||
|
||||
if ($dirname == '.') {
|
||||
$dirname = '';
|
||||
}
|
||||
|
||||
return $scheme . '://' . $dirname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Support for mkdir().
|
||||
*
|
||||
|
@ -500,8 +598,10 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
|||
* Permission flags - see mkdir().
|
||||
* @param $options
|
||||
* A bit mask of STREAM_REPORT_ERRORS and STREAM_MKDIR_RECURSIVE.
|
||||
*
|
||||
* @return
|
||||
* TRUE if directory was successfully created.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.mkdir.php
|
||||
*/
|
||||
public function mkdir($uri, $mode, $options) {
|
||||
|
@ -510,7 +610,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
|||
if ($recursive) {
|
||||
// $this->getLocalPath() fails if $uri has multiple levels of directories
|
||||
// that do not yet exist.
|
||||
$localpath = $this->getDirectoryPath() . '/' . file_uri_target($uri);
|
||||
$localpath = $this->getDirectoryPath() . '/' . $this->getTarget($uri);
|
||||
}
|
||||
else {
|
||||
$localpath = $this->getLocalPath($uri);
|
||||
|
@ -530,8 +630,10 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
|||
* A string containing the URI to the directory to delete.
|
||||
* @param $options
|
||||
* A bit mask of STREAM_REPORT_ERRORS.
|
||||
*
|
||||
* @return
|
||||
* TRUE if directory was successfully removed.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.rmdir.php
|
||||
*/
|
||||
public function rmdir($uri, $options) {
|
||||
|
@ -551,9 +653,11 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
|||
* A string containing the URI to get information about.
|
||||
* @param $flags
|
||||
* A bit mask of STREAM_URL_STAT_LINK and STREAM_URL_STAT_QUIET.
|
||||
*
|
||||
* @return
|
||||
* An array with file status, or FALSE in case of an error - see fstat()
|
||||
* for a description of this array.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.url-stat.php
|
||||
*/
|
||||
public function url_stat($uri, $flags) {
|
||||
|
@ -573,8 +677,10 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
|||
* A string containing the URI to the directory to open.
|
||||
* @param $options
|
||||
* Unknown (parameter is not documented in PHP Manual).
|
||||
*
|
||||
* @return
|
||||
* TRUE on success.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.dir-opendir.php
|
||||
*/
|
||||
public function dir_opendir($uri, $options) {
|
||||
|
@ -589,6 +695,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
|||
*
|
||||
* @return
|
||||
* The next filename, or FALSE if there are no more files in the directory.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.dir-readdir.php
|
||||
*/
|
||||
public function dir_readdir() {
|
||||
|
@ -600,6 +707,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
|||
*
|
||||
* @return
|
||||
* TRUE on success.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.dir-rewinddir.php
|
||||
*/
|
||||
public function dir_rewinddir() {
|
||||
|
@ -611,6 +719,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
|||
*
|
||||
* @return
|
||||
* TRUE on success.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.dir-closedir.php
|
||||
*/
|
||||
public function dir_closedir() {
|
||||
|
@ -638,7 +747,7 @@ class DrupalPublicStreamWrapper extends DrupalLocalStreamWrapper {
|
|||
* Return the HTML URI of a public file.
|
||||
*/
|
||||
function getExternalUrl() {
|
||||
$path = str_replace('\\', '/', file_uri_target($this->uri));
|
||||
$path = str_replace('\\', '/', $this->getTarget());
|
||||
return $GLOBALS['base_url'] . '/' . self::getDirectoryPath() . '/' . drupal_encode_path($path);
|
||||
}
|
||||
}
|
||||
|
@ -666,7 +775,7 @@ class DrupalPrivateStreamWrapper extends DrupalLocalStreamWrapper {
|
|||
* Return the HTML URI of a private file.
|
||||
*/
|
||||
function getExternalUrl() {
|
||||
$path = str_replace('\\', '/', file_uri_target($this->uri));
|
||||
$path = str_replace('\\', '/', $this->getTarget());
|
||||
return url('system/files/' . $path, array('absolute' => TRUE));
|
||||
}
|
||||
}
|
||||
|
@ -691,7 +800,7 @@ class DrupalTemporaryStreamWrapper extends DrupalLocalStreamWrapper {
|
|||
* Overrides getExternalUrl().
|
||||
*/
|
||||
public function getExternalUrl() {
|
||||
$path = str_replace('\\', '/', file_uri_target($this->uri));
|
||||
$path = str_replace('\\', '/', $this->getTarget());
|
||||
return url('system/temporary/' . $path, array('absolute' => TRUE));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2286,11 +2286,6 @@ class StreamWrapperTest extends DrupalWebTestCase {
|
|||
$instance = file_stream_wrapper_get_instance_by_uri('public://foo');
|
||||
$this->assertEqual('DrupalPublicStreamWrapper', get_class($instance), t('Got correct class type for public URI.'));
|
||||
|
||||
// Test file_stream_wrapper_uri_normalize().
|
||||
$uri = 'public:///' . file_directory_path() . '/foo/bar/';
|
||||
$uri = file_stream_wrapper_uri_normalize($uri);
|
||||
$this->assertEqual('public://foo/bar', $uri, t('Got a properly normalized URI @uri', array('@uri' => $uri)));
|
||||
|
||||
// Test file_uri_target().
|
||||
$this->assertEqual(file_uri_target('public://foo/bar.txt'), 'foo/bar.txt', t('Got a valid stream target from public://foo/bar.txt.'));
|
||||
$this->assertFalse(file_uri_target('foo/bar.txt'), t('foo/bar.txt is not a valid stream.'));
|
||||
|
|
Loading…
Reference in New Issue