ZF-12251: readdir() doesn't return expected results when using Zend_Service_Amazon_S3_Stream wrapper


When using the S3 stream wrapper:

Regardless of path passed to opendir(), readdir() iterates through all files in the bucket, and returns a full pathname for each file. Zend_Service_Amazon_S3_Stream should pass 'prefix' and 'delimiter' to $s3client->getObjectsByBucket() to restrict listing to path passed to $opendir.

Also normal behavior of readdir() is to return filename only. Having this consistency would enable more seamless switching between wrappers and local filesystem.


Fix would be in opendir(), something like the following. I'm using this successfully in a class that extends Zend_Service_Amazon_S3_Stream.

public function dir_opendir($path, $options)

    if (preg_match('@^([a-z0-9+.]|-)+://$@', $path)) {
        $this->_bucketList = $this->_getS3Client($path)->getBuckets();
    else {
        $host = parse_url($path, PHP_URL_HOST);

        // format $dir so it works correctly with S3 bucket
        $dir  = trim(parse_url($path, PHP_URL_PATH), '/') . '/';
        $this->_bucketList = $this->_getS3Client($path)->getObjectsByBucket($host, array( 'delimiter' => '/', 'prefix' => $dir ));

        // use basenames only so that values look like you would normally expect with readdir()
        if (is_array($this->_bucketList)) {
            for ($i = 0; $i < count($this->_bucketList); $i++) {
                $this->_bucketList[$i] = basename($this->_bucketList[$i]);

    return ($this->_bucketList !== false);