Commit 57291a5c authored by alexpott's avatar alexpott

Issue #2213241 by fietserwin, sun: Fully conform to PHP5.4 streamwrapper class

parent 3ac9d4cc
......@@ -137,6 +137,14 @@ public function stream_metadata($uri, $option, $value) {
return FALSE;
}
/**
* {@inheritdoc}
*/
public function stream_truncate($new_size) {
trigger_error('stream_truncate() not supported for read-only stream wrappers', E_USER_WARNING);
return FALSE;
}
/**
* Support for unlink().
*
......
......@@ -235,19 +235,9 @@ public function stream_eof() {
}
/**
* Support for fseek().
*
* @param int $offset
* The byte offset to got to.
* @param int $whence
* SEEK_SET, SEEK_CUR, or SEEK_END.
*
* @return bool
* TRUE on success.
*
* @see http://php.net/manual/streamwrapper.stream-seek.php
* {@inheritdoc}
*/
public function stream_seek($offset, $whence) {
public function stream_seek($offset, $whence = SEEK_SET) {
// fseek returns 0 on success and -1 on a failure.
// stream_seek 1 on success and 0 on a failure.
return !fseek($this->handle, $offset, $whence);
......@@ -303,19 +293,10 @@ public function stream_close() {
}
/**
* Gets the underlying stream resource for stream_select().
*
* @param int $cast_as
* Can be STREAM_CAST_FOR_SELECT or STREAM_CAST_AS_STREAM.
*
* @return resource|false
* The underlying stream resource or FALSE if stream_select() is not
* supported.
*
* @see http://php.net/manual/streamwrapper.stream-cast.php
* {@inheritdoc}
*/
public function stream_cast($cast_as) {
return false;
return $this->handle ? $this->handle : FALSE;
}
/**
......@@ -334,6 +315,16 @@ public function stream_metadata($uri, $option, $value) {
}
break;
case STREAM_META_OWNER_NAME:
case STREAM_META_OWNER:
$return = chown($target, $value);
break;
case STREAM_META_GROUP_NAME:
case STREAM_META_GROUP:
$return = chgrp($target, $value);
break;
case STREAM_META_ACCESS:
$return = chmod($target, $value);
break;
......@@ -346,6 +337,26 @@ public function stream_metadata($uri, $option, $value) {
return $return;
}
/**
* {@inheritdoc}
*
* Since Windows systems do not allow it and it is not needed for most use
* cases anyway, this method is not supported on local files and will trigger
* an error and return false. If needed, custom subclasses can provide
* OS-specific implementations for advanced use cases.
*/
public function stream_set_option($option, $arg1, $arg2) {
trigger_error('stream_set_option() not supported for local file based stream wrappers', E_USER_WARNING);
return FALSE;
}
/**
* {@inheritdoc}
*/
public function stream_truncate($new_size) {
return ftruncate($this->handle, $new_size);
}
/**
* Support for unlink().
*
......
......@@ -13,21 +13,85 @@
* @see http://www.php.net/manual/class.streamwrapper.php
*/
interface PhpStreamWrapperInterface {
public function stream_open($uri, $mode, $options, &$opened_url);
/**
* @return bool
*/
public function dir_closedir();
/**
* @return bool
*/
public function dir_opendir($path, $options);
/**
* @return string
*/
public function dir_readdir();
/**
* @return bool
*/
public function dir_rewinddir();
/**
* @return bool
*/
public function mkdir($path, $mode, $options);
/**
* @return bool
*/
public function rename($path_from, $path_to);
/**
* @return bool
*/
public function rmdir($path, $options);
/**
* Retrieve the underlying stream resource.
*
* This method is called in response to stream_select().
*
* @param int $cast_as
* Can be STREAM_CAST_FOR_SELECT when stream_select() is calling
* stream_cast() or STREAM_CAST_AS_STREAM when stream_cast() is called for
* other uses.
*
* @return resource|false
* The underlying stream resource or FALSE if stream_select() is not
* supported.
*
* @see stream_select()
* @see http://php.net/manual/streamwrapper.stream-cast.php
*/
public function stream_cast($cast_as);
/**
* @return void
*/
public function stream_close();
public function stream_lock($operation);
public function stream_read($count);
public function stream_write($data);
/**
* @return bool
*/
public function stream_eof();
public function stream_seek($offset, $whence);
/**
* @return bool
*/
public function stream_flush();
public function stream_tell();
public function stream_stat();
/**
* @return bool
*/
public function stream_lock($operation);
/**
* Sets metadata on the stream.
*
* @param string $uri
* @param string $path
* A string containing the URI to the file to set metadata on.
* @param int $option
* One of:
......@@ -54,15 +118,111 @@ public function stream_stat();
*
* @see http://www.php.net/manual/streamwrapper.stream-metadata.php
*/
public function stream_metadata($uri, $option, $value);
public function stream_metadata($path, $option, $value);
/**
* @return bool
*/
public function stream_open($path, $mode, $options, &$opened_path);
/**
* @return string
*/
public function stream_read($count);
/**
* Seeks to specific location in a stream.
*
* This method is called in response to fseek().
*
* The read/write position of the stream should be updated according to the
* offset and whence.
*
* @param int $offset
* The byte offset to seek to.
* @param int $whence
* Possible values:
* - SEEK_SET: Set position equal to offset bytes.
* - SEEK_CUR: Set position to current location plus offset.
* - SEEK_END: Set position to end-of-file plus offset.
* Defaults to SEEK_SET.
*
* @return bool
* TRUE if the position was updated, FALSE otherwise.
*
* @see http://php.net/manual/streamwrapper.stream-seek.php
*/
public function stream_seek($offset, $whence = SEEK_SET);
/**
* Change stream options.
*
* This method is called to set options on the stream.
*
* @param int $option
* One of:
* - STREAM_OPTION_BLOCKING: The method was called in response to
* stream_set_blocking().
* - STREAM_OPTION_READ_TIMEOUT: The method was called in response to
* stream_set_timeout().
* - STREAM_OPTION_WRITE_BUFFER: The method was called in response to
* stream_set_write_buffer().
* @param int $arg1
* If option is:
* - STREAM_OPTION_BLOCKING: The requested blocking mode:
* - 1 means blocking.
* - 0 means not blocking.
* - STREAM_OPTION_READ_TIMEOUT: The timeout in seconds.
* - STREAM_OPTION_WRITE_BUFFER: The buffer mode, STREAM_BUFFER_NONE or
* STREAM_BUFFER_FULL.
* @param int $arg2
* If option is:
* - STREAM_OPTION_BLOCKING: This option is not set.
* - STREAM_OPTION_READ_TIMEOUT: The timeout in microseconds.
* - STREAM_OPTION_WRITE_BUFFER: The requested buffer size.
*
* @return bool
* TRUE on success, FALSE otherwise. If $option is not implemented, FALSE
* should be returned.
*/
public function stream_set_option($option, $arg1, $arg2);
/**
* @return array
*/
public function stream_stat();
/**
* @return int
*/
public function stream_tell();
/**
* Truncate stream.
*
* Will respond to truncation; e.g., through ftruncate().
*
* @param int $new_size
* The new size.
*
* @return bool
* TRUE on success, FALSE otherwise.
*/
public function stream_truncate($new_size);
/**
* @return int
*/
public function stream_write($data);
/**
* @return bool
*/
public function unlink($path);
/**
* @return array
*/
public function url_stat($path, $flags);
public function unlink($uri);
public function rename($from_uri, $to_uri);
public function mkdir($uri, $mode, $options);
public function rmdir($uri, $options);
public function url_stat($uri, $flags);
public function dir_opendir($uri, $options);
public function dir_readdir();
public function dir_rewinddir();
public function dir_closedir();
}
......@@ -171,6 +171,14 @@ public function stream_metadata($uri, $option, $value) {
return FALSE;
}
/**
* {@inheritdoc}
*/
public function stream_truncate($new_size) {
trigger_error('stream_truncate() not supported for read-only stream wrappers', E_USER_WARNING);
return FALSE;
}
/**
* Support for unlink().
*
......
......@@ -29,9 +29,9 @@ class ReadOnlyStreamWrapperTest extends FileTestBase {
protected $classname = 'Drupal\file_test\StreamWrapper\DummyReadOnlyStreamWrapper';
/**
* Test write functionality of the read-only stream wrapper.
* Test read-only specific behavior.
*/
function testWriteFunctions() {
function testReadOnlyBehavior() {
// Generate a test file
$filename = $this->randomMachineName();
$filepath = conf_path() . '/files/' . $filename;
......@@ -56,13 +56,15 @@ function testWriteFunctions() {
$handle = fopen($uri, 'r');
$this->assertTrue($handle, 'Able to open a file for reading with the read-only stream wrapper.');
// Attempt to change file permissions
$this->assertFalse(@drupal_chmod($uri, 0777), 'Unable to change file permissions when using read-only stream wrapper.');
$this->assertFalse(@chmod($uri, 0777), 'Unable to change file permissions when using read-only stream wrapper.');
// Attempt to acquire an exclusive lock for writing
$this->assertFalse(@flock($handle, LOCK_EX | LOCK_NB), 'Unable to acquire an exclusive lock using the read-only stream wrapper.');
// Attempt to obtain a shared lock
$this->assertTrue(flock($handle, LOCK_SH | LOCK_NB), 'Able to acquire a shared lock using the read-only stream wrapper.');
// Attempt to release a shared lock
$this->assertTrue(flock($handle, LOCK_UN | LOCK_NB), 'Able to release a shared lock using the read-only stream wrapper.');
// Attempt to truncate the file
$this->assertFalse(@ftruncate($handle, 0), 'Unable to truncate using the read-only stream wrapper.');
// Attempt to write to the file
$this->assertFalse(@fwrite($handle, $this->randomMachineName()), 'Unable to write to file using the read-only stream wrapper.');
// Attempt to flush output to the file
......
......@@ -109,6 +109,38 @@ function testUriFunctions() {
$this->assertTrue(strpos(file_create_url('private://test.txt'), 'system/files/test.txt'), 'Private external URL correctly built.');
}
/**
* Test some file handle functions.
*/
function testFileFunctions() {
$filename = 'public://'. $this->randomMachineName();
file_put_contents($filename, str_repeat('d', 1000));
// Open for rw and place pointer at beginning of file so select will return.
$handle = fopen($filename, 'c+');
$this->assertTrue($handle, 'Able to open a file for appending, reading and writing.');
// Attempt to change options on the file stream: should all fail.
$this->assertFalse(@stream_set_blocking($handle, 0), 'Unable to set to non blocking using a local stream wrapper.');
$this->assertFalse(@stream_set_blocking($handle, 1), 'Unable to set to blocking using a local stream wrapper.');
$this->assertFalse(@stream_set_timeout($handle, 1), 'Unable to set read time out using a local stream wrapper.');
$this->assertEqual(-1 /*EOF*/, @stream_set_write_buffer($handle, 512), 'Unable to set write buffer using a local stream wrapper.');
// This will test stream_cast().
$read = array($handle);
$write = NULL;
$except = NULL;
$this->assertEqual(1, stream_select($read, $write, $except, 0), 'Able to cast a stream via stream_select.');
// This will test stream_truncate().
$this->assertEqual(1, ftruncate($handle, 0), 'Able to truncate a stream via ftruncate().');
fclose($handle);
$this->assertEqual(0, filesize($filename), 'Able to truncate a stream.');
// Cleanup.
unlink($filename);
}
/**
* Test the scheme functions.
*/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment