Completed
Pull Request — 2.x (#239)
by
unknown
01:10
created

AwsS3V3AdapterTest.php (15 issues)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
declare(strict_types=1);
4
5
namespace League\Flysystem\AwsS3V3;
6
7
use Aws\Result;
8
use Aws\S3\S3Client;
9
use Aws\S3\S3ClientInterface;
10
use Exception;
11
use Generator;
12
use League\Flysystem\AdapterTestUtilities\FilesystemAdapterTestCase;
13
use League\Flysystem\Config;
14
use League\Flysystem\FileAttributes;
15
use League\Flysystem\FilesystemAdapter;
16
use League\Flysystem\StorageAttributes;
17
use League\Flysystem\UnableToCheckFileExistence;
18
use League\Flysystem\UnableToDeleteFile;
19
use League\Flysystem\UnableToMoveFile;
20
use League\Flysystem\UnableToRetrieveMetadata;
21
22
/**
23
 * @group aws
24
 */
25
class AwsS3V3AdapterTest extends FilesystemAdapterTestCase
26
{
27
    /**
28
     * @var bool
29
     */
30
    private $shouldCleanUp = false;
31
32
    /**
33
     * @var string
34
     */
35
    private static $adapterPrefix = 'test-prefix';
36
37
    /**
38
     * @var S3ClientInterface|null
39
     */
40
    private static $s3Client;
41
42
    /**
43
     * @var S3ClientStub
44
     */
45
    private static $stubS3Client;
46
47
    public static function setUpBeforeClass(): void
48
    {
49
        static::$adapterPrefix = 'ci/' . bin2hex(random_bytes(10));
0 ignored issues
show
Since $adapterPrefix is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $adapterPrefix to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
50
    }
51
52
    protected function tearDown(): void
53
    {
54
        if ( ! $this->shouldCleanUp) {
55
            return;
56
        }
57
58
        $adapter = $this->adapter();
59
        $adapter->deleteDirectory('/');
60
        /** @var StorageAttributes[] $listing */
61
        $listing = $adapter->listContents('', false);
62
63
        foreach ($listing as $item) {
64
            if ($item->isFile()) {
65
                $adapter->delete($item->path());
66
            } else {
67
                $adapter->deleteDirectory($item->path());
68
            }
69
        }
70
71
        self::$adapter = null;
72
    }
73
74
    private static function s3Client(): S3ClientInterface
75
    {
76
        if (static::$s3Client instanceof S3ClientInterface) {
0 ignored issues
show
Since $s3Client is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $s3Client to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
77
            return static::$s3Client;
0 ignored issues
show
Since $s3Client is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $s3Client to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
78
        }
79
80
        $key = getenv('FLYSYSTEM_AWS_S3_KEY');
81
        $secret = getenv('FLYSYSTEM_AWS_S3_SECRET');
82
        $bucket = getenv('FLYSYSTEM_AWS_S3_BUCKET');
83
        $region = getenv('FLYSYSTEM_AWS_S3_REGION') ?: 'eu-central-1';
84
85
        if ( ! $key || ! $secret || ! $bucket) {
86
            self::markTestSkipped('No AWS credentials present for testing.');
87
        }
88
89
        $options = ['version' => 'latest', 'credentials' => compact('key', 'secret'), 'region' => $region];
90
91
        return static::$s3Client = new S3Client($options);
0 ignored issues
show
Since $s3Client is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $s3Client to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
92
    }
93
94
    /**
95
     * @test
96
     */
97
    public function writing_with_a_specific_mime_type(): void
98
    {
99
        $adapter = $this->adapter();
100
        $adapter->write('some/path.txt', 'contents', new Config(['ContentType' => 'text/plain+special']));
101
        $mimeType = $adapter->mimeType('some/path.txt')->mimeType();
102
        $this->assertEquals('text/plain+special', $mimeType);
103
    }
104
105
    /**
106
     * @test
107
     */
108
    public function listing_contents_recursive(): void
109
    {
110
        $adapter = $this->adapter();
111
        $adapter->write('something/0/here.txt', 'contents', new Config());
112
        $adapter->write('something/1/also/here.txt', 'contents', new Config());
113
114
        $contents = iterator_to_array($adapter->listContents('', true));
115
116
        $this->assertCount(2, $contents);
117
        $this->assertContainsOnlyInstancesOf(FileAttributes::class, $contents);
118
        /** @var FileAttributes $file */
119
        $file = $contents[0];
120
        $this->assertEquals('something/0/here.txt', $file->path());
121
        /** @var FileAttributes $file */
122
        $file = $contents[1];
123
        $this->assertEquals('something/1/also/here.txt', $file->path());
124
    }
125
126
    /**
127
     * @test
128
     */
129
    public function failing_to_delete_while_moving(): void
130
    {
131
        $adapter = $this->adapter();
132
        $adapter->write('source.txt', 'contents to be copied', new Config());
133
        static::$stubS3Client->failOnNextCopy();
0 ignored issues
show
Since $stubS3Client is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $stubS3Client to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
134
135
        $this->expectException(UnableToMoveFile::class);
136
137
        $adapter->move('source.txt', 'destination.txt', new Config());
138
    }
139
140
    /**
141
     * @test
142
     */
143
    public function failing_to_delete_a_file(): void
144
    {
145
        $adapter = $this->adapter();
146
        static::$stubS3Client->throwExceptionWhenExecutingCommand('DeleteObject');
0 ignored issues
show
Since $stubS3Client is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $stubS3Client to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
147
148
        $this->expectException(UnableToDeleteFile::class);
149
150
        $adapter->delete('path.txt');
151
    }
152
153
    /**
154
     * @test
155
     */
156
    public function fetching_unknown_mime_type_of_a_file(): void
157
    {
158
        $this->adapter();
159
        $result = new Result([
160
            'Key' => static::$adapterPrefix . '/unknown-mime-type.md5',
0 ignored issues
show
Since $adapterPrefix is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $adapterPrefix to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
161
        ]);
162
        static::$stubS3Client->stageResultForCommand('HeadObject', $result);
0 ignored issues
show
Since $stubS3Client is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $stubS3Client to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
163
164
        parent::fetching_unknown_mime_type_of_a_file();
165
    }
166
167
    /**
168
     * @test
169
     * @dataProvider dpFailingMetadataGetters
170
     */
171
    public function failing_to_retrieve_metadata(Exception $exception, string $getterName): void
172
    {
173
        $adapter = $this->adapter();
174
        $result = new Result([
175
             'Key' => static::$adapterPrefix . '/filename.txt',
0 ignored issues
show
Since $adapterPrefix is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $adapterPrefix to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
176
        ]);
177
        static::$stubS3Client->stageResultForCommand('HeadObject', $result);
0 ignored issues
show
Since $stubS3Client is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $stubS3Client to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
178
179
        $this->expectExceptionObject($exception);
180
181
        $adapter->{$getterName}('filename.txt');
182
    }
183
184
    public function dpFailingMetadataGetters(): iterable
185
    {
186
        yield "mimeType" => [UnableToRetrieveMetadata::mimeType('filename.txt'), 'mimeType'];
187
        yield "lastModified" => [UnableToRetrieveMetadata::lastModified('filename.txt'), 'lastModified'];
188
        yield "fileSize" => [UnableToRetrieveMetadata::fileSize('filename.txt'), 'fileSize'];
189
    }
190
191
    /**
192
     * @test
193
     */
194
    public function failing_to_check_for_file_existence(): void
195
    {
196
        $adapter = $this->adapter();
197
198
        static::$stubS3Client->throw500ExceptionWhenExecutingCommand('HeadObject');
0 ignored issues
show
Since $stubS3Client is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $stubS3Client to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
199
200
        $this->expectException(UnableToCheckFileExistence::class);
201
202
        $adapter->fileExists('something-that-does-exist.txt');
203
    }
204
205
    /**
206
     * @test
207
     * @dataProvider casesWhereHttpStreamingInfluencesSeekability
208
     */
209
    public function streaming_reads_are_not_seekable_and_non_streaming_are(bool $streaming, bool $seekable): void
210
    {
211
        if (getenv('COMPOSER_OPTS') === '--prefer-lowest') {
212
            $this->markTestSkipped('The SDK does not support streaming in low versions.');
213
        }
214
215
        $adapter = $this->useAdapter($this->createFilesystemAdapter($streaming));
216
        $this->givenWeHaveAnExistingFile('path.txt');
217
218
        $resource = $adapter->readStream('path.txt');
219
        $metadata = stream_get_meta_data($resource);
220
        fclose($resource);
221
222
        $this->assertEquals($seekable, $metadata['seekable']);
223
    }
224
225
    public function casesWhereHttpStreamingInfluencesSeekability(): Generator
226
    {
227
        yield "not streaming reads have seekable stream" => [false, true];
228
        yield "streaming reads have non-seekable stream" => [true, false];
229
    }
230
231
    /**
232
     * @test
233
     * @dataProvider casesWhereHttpStreamingInfluencesSeekability
234
     */
235
    public function configuring_http_streaming_via_options(bool $streaming): void
236
    {
237
        $adapter = $this->useAdapter($this->createFilesystemAdapter($streaming, ['@http' => ['stream' => false]]));
238
        $this->givenWeHaveAnExistingFile('path.txt');
239
240
        $resource = $adapter->readStream('path.txt');
241
        $metadata = stream_get_meta_data($resource);
242
        fclose($resource);
243
244
        $this->assertTrue($metadata['seekable']);
245
    }
246
247
    protected static function createFilesystemAdapter(bool $streaming = true, array $options = []): FilesystemAdapter
248
    {
249
        static::$stubS3Client = new S3ClientStub(static::s3Client());
0 ignored issues
show
Since $stubS3Client is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $stubS3Client to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
Since s3Client() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of s3Client() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
250
        /** @var string $bucket */
251
        $bucket = getenv('FLYSYSTEM_AWS_S3_BUCKET');
252
        $prefix = getenv('FLYSYSTEM_AWS_S3_PREFIX') ?: static::$adapterPrefix;
0 ignored issues
show
Since $adapterPrefix is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $adapterPrefix to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
253
254
        return new AwsS3V3Adapter(static::$stubS3Client, $bucket, $prefix, null, null, $options, $streaming);
0 ignored issues
show
Since $stubS3Client is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $stubS3Client to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
255
    }
256
}
257