Completed
Push — 2.x ( ac4a9a...73370d )
by Frank
01:12
created

AwsS3V3AdapterTest::moving_with_updated_metadata()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.8333
c 0
b 0
f 0
cc 1
nc 1
nop 0
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
Bug introduced by
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
Bug introduced by
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
Bug introduced by
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
Bug introduced by
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
Bug introduced by
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
Bug introduced by
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
Bug introduced by
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
Bug introduced by
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
Bug introduced by
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
Bug introduced by
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
Bug introduced by
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
    /**
248
     * @test
249
     */
250
    public function moving_with_updated_metadata(): void
251
    {
252
        $adapter = $this->adapter();
253
        $adapter->write('source.txt', 'contents to be moved', new Config(['ContentType' => 'text/plain']));
254
        $mimeTypeSource = $adapter->mimeType('source.txt')->mimeType();
255
        $this->assertSame('text/plain', $mimeTypeSource);
256
257
        $adapter->move('source.txt', 'destination.txt', new Config(
258
            ['ContentType' => 'text/plain+special', 'MetadataDirective' => 'REPLACE']
259
        ));
260
        $mimeTypeDestination = $adapter->mimeType('destination.txt')->mimeType();
261
        $this->assertSame('text/plain+special', $mimeTypeDestination);
262
    }
263
264
    protected static function createFilesystemAdapter(bool $streaming = true, array $options = []): FilesystemAdapter
265
    {
266
        static::$stubS3Client = new S3ClientStub(static::s3Client());
0 ignored issues
show
Bug introduced by
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...
Bug introduced by
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...
267
        /** @var string $bucket */
268
        $bucket = getenv('FLYSYSTEM_AWS_S3_BUCKET');
269
        $prefix = getenv('FLYSYSTEM_AWS_S3_PREFIX') ?: static::$adapterPrefix;
0 ignored issues
show
Bug introduced by
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...
270
271
        return new AwsS3V3Adapter(static::$stubS3Client, $bucket, $prefix, null, null, $options, $streaming);
0 ignored issues
show
Bug introduced by
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...
272
    }
273
}
274