Skip to content

Commit

Permalink
Better handling flags in stream wrapper errors
Browse files Browse the repository at this point in the history
PHP stream wrappers provide flags to url_stat that should be used to determine
the response of a call and whether or not it raises an error. I've updated the
Amazon S3 stream wrapper to utilize these combinations of flags to emulate the
error handling of the "http" protocol stream wrapper.

Closes #268
  • Loading branch information
mtdowling committed Apr 14, 2014
1 parent 2a4355c commit 40b700c
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 13 deletions.
21 changes: 10 additions & 11 deletions src/Aws/S3/StreamWrapper.php
Expand Up @@ -72,7 +72,6 @@
* Stream context options:
*
* - "seekable": Set to true to create a seekable "r" (read only) stream by using a php://temp stream buffer
* - "throw_exceptions": Set to true to throw exceptions instead of trigger_errors
* - For "unlink" only: Any option that can be passed to the DeleteObject operation
*/
class StreamWrapper
Expand Down Expand Up @@ -632,7 +631,6 @@ protected function getParams($path)

$params = $this->getOptions();
unset($params['seekable']);
unset($params['throw_exceptions']);

return array(
'Bucket' => $parts[0],
Expand Down Expand Up @@ -725,14 +723,17 @@ protected function openAppendStream(array $params, array &$errors)
*/
protected function triggerError($errors, $flags = null)
{
if ($flags != STREAM_URL_STAT_QUIET) {
if ($this->getOption('throw_exceptions')) {
throw new RuntimeException(implode("\n", (array) $errors));
} else {
trigger_error(implode("\n", (array) $errors), E_USER_WARNING);
}
if ($flags === STREAM_URL_STAT_QUIET) {
// This is triggered with things like file_exists()
return false;
} elseif ($flags === (STREAM_URL_STAT_QUIET | STREAM_URL_STAT_LINK)) {
// This is triggered for things like is_link()
return $this->formatUrlStat(false);
}

// This is triggered when doing things like lstat() or stat()
trigger_error(implode("\n", (array) $errors), E_USER_WARNING);

return false;
}

Expand Down Expand Up @@ -765,7 +766,7 @@ protected function formatUrlStat($result = null)
$type = gettype($result);

// Determine what type of data is being cached
if (!$result || $type == 'string') {
if ($type == 'NULL' || $type == 'string') {
// Directory with 0777 access - see "man 2 stat".
$stat['mode'] = $stat[2] = 0040777;
} elseif ($type == 'array' && isset($result['LastModified'])) {
Expand All @@ -774,8 +775,6 @@ protected function formatUrlStat($result = null)
$stat['size'] = $stat[7] = (isset($result['ContentLength']) ? $result['ContentLength'] : $result['Size']);
// Regular file with 0777 access - see "man 2 stat".
$stat['mode'] = $stat[2] = 0100777;
} else {
$stat['mode'] = $stat[2] = 0100777;
}

return $stat;
Expand Down
14 changes: 14 additions & 0 deletions tests/Aws/Tests/S3/Integration/StreamWrapperTest.php
Expand Up @@ -129,6 +129,20 @@ public function testOpensStreams()
fclose($h);
}

/**
* @depends testOpensStreams
*/
public function testDoesNotRaiseErrorForMissingFile()
{
self::log('Testing invalid file');
$this->assertFalse(is_file('s3://ewfwefwfeweff/' . uniqid('foo')));
$this->assertFalse(is_link('s3://ewfwefwfeweff/' . uniqid('foo')));
try {
lstat('s3://ewfwefwfeweff/' . uniqid('foo'));
$this->fail('Did not trigger a warning');
} catch (\PHPUnit_Framework_Error_Warning $e) {}
}

/**
* @depends testOpensStreams
*/
Expand Down
4 changes: 2 additions & 2 deletions tests/Aws/Tests/S3/StreamWrapperTest.php
Expand Up @@ -95,8 +95,8 @@ public function testSuccessfulXMode()
}

/**
* @expectedException RuntimeException
* @expectedExceptionMessage simultaneous reading and writing
* @expectedException \PHPUnit_Framework_Error_Warning
* @expectedExceptionMessage The Amazon S3 stream wrapper does not allow simultaneous reading and writing.
*/
public function testCanThrowExceptionsInsteadOfErrors()
{
Expand Down

0 comments on commit 40b700c

Please sign in to comment.