Completed
Push — master ( 62075d...fae35c )
by Nicolas
03:27 queued 19s
created

src/Gaufrette/File.php (1 issue)

strict.coding_against_concrete_implementation

Bug Minor

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
namespace Gaufrette;
4
5
use Gaufrette\Adapter\MetadataSupporter;
6
use Gaufrette\Exception\FileNotFound;
7
8
/**
9
 * Points to a file in a filesystem.
10
 *
11
 * @author Antoine Hérault <[email protected]>
12
 */
13
class File
14
{
15
    protected $key;
16
    protected $filesystem;
17
18
    /**
19
     * Content variable is lazy. It will not be read from filesystem until it's requested first time.
20
     *
21
     * @var mixed content
22
     */
23
    protected $content = null;
24
25
    /**
26
     * @var array metadata in associative array. Only for adapters that support metadata
27
     */
28
    protected $metadata = null;
29
30
    /**
31
     * Human readable filename (usually the end of the key).
32
     *
33
     * @var string name
34
     */
35
    protected $name = null;
36
37
    /**
38
     * File size in bytes.
39
     *
40
     * @var int size
41
     */
42
    protected $size = 0;
43
44
    /**
45
     * File date modified.
46
     *
47
     * @var int mtime
48
     */
49
    protected $mtime = null;
50
51
    /**
52
     * @param string     $key
53
     * @param Filesystem $filesystem
54
     */
55
    public function __construct($key, Filesystem $filesystem)
56
    {
57
        $this->key = $key;
58
        $this->name = $key;
59
        $this->filesystem = $filesystem;
60
    }
61
62
    /**
63
     * Returns the key.
64
     *
65
     * @return string
66
     */
67
    public function getKey()
68
    {
69
        return $this->key;
70
    }
71
72
    /**
73
     * Returns the content.
74
     *
75
     * @throws FileNotFound
76
     *
77
     * @param array $metadata optional metadata which should be set when read
78
     *
79
     * @return string
80
     */
81 View Code Duplication
    public function getContent($metadata = array())
82
    {
83
        if (isset($this->content)) {
84
            return $this->content;
85
        }
86
        $this->setMetadata($metadata);
87
88
        return $this->content = $this->filesystem->read($this->key);
89
    }
90
91
    /**
92
     * @return string name of the file
93
     */
94
    public function getName()
95
    {
96
        return $this->name;
97
    }
98
99
    /**
100
     * @return int size of the file
101
     */
102
    public function getSize()
103
    {
104
        if ($this->size) {
105
            return $this->size;
106
        }
107
108
        try {
109
            return $this->size = $this->filesystem->size($this->getKey());
110
        } catch (FileNotFound $exception) {
111
        }
112
113
        return 0;
114
    }
115
116
    /**
117
     * Returns the file modified time.
118
     *
119
     * @return int
120
     */
121
    public function getMtime()
122
    {
123
        return $this->mtime = $this->filesystem->mtime($this->key);
124
    }
125
126
    /**
127
     * @param int $size size of the file
128
     */
129
    public function setSize($size)
130
    {
131
        $this->size = $size;
132
    }
133
134
    /**
135
     * Sets the content.
136
     *
137
     * @param string $content
138
     * @param array  $metadata optional metadata which should be send when write
139
     *
140
     * @return int The number of bytes that were written into the file, or
141
     *             FALSE on failure
142
     */
143 View Code Duplication
    public function setContent($content, $metadata = array())
144
    {
145
        $this->content = $content;
146
        $this->setMetadata($metadata);
147
148
        return $this->size = $this->filesystem->write($this->key, $this->content, true);
149
    }
150
151
    /**
152
     * @param string $name name of the file
153
     */
154
    public function setName($name)
155
    {
156
        $this->name = $name;
157
    }
158
159
    /**
160
     * Indicates whether the file exists in the filesystem.
161
     *
162
     * @return bool
163
     */
164
    public function exists()
165
    {
166
        return $this->filesystem->has($this->key);
167
    }
168
169
    /**
170
     * Deletes the file from the filesystem.
171
     *
172
     * @throws FileNotFound
173
     * @throws \RuntimeException when cannot delete file
174
     *
175
     * @param array $metadata optional metadata which should be send when write
176
     *
177
     * @return bool TRUE on success
178
     */
179
    public function delete($metadata = array())
180
    {
181
        $this->setMetadata($metadata);
182
183
        return $this->filesystem->delete($this->key);
184
    }
185
186
    /**
187
     * Creates a new file stream instance of the file.
188
     *
189
     * @return Stream
190
     */
191
    public function createStream()
192
    {
193
        return $this->filesystem->createStream($this->key);
194
    }
195
196
    /**
197
     * Rename the file and move it to its new location.
198
     *
199
     * @param string $newKey
200
     */
201
    public function rename($newKey)
202
    {
203
        $this->filesystem->rename($this->key, $newKey);
204
205
        $this->key = $newKey;
206
    }
207
208
    /**
209
     * Sets the metadata array to be stored in adapters that can support it.
210
     *
211
     * @param array $metadata
212
     *
213
     * @return bool
214
     */
215
    protected function setMetadata(array $metadata)
216
    {
217
        if ($metadata && $this->supportsMetadata()) {
218
            $this->filesystem->getAdapter()->setMetadata($this->key, $metadata);
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Gaufrette\Adapter as the method setMetadata() does only exist in the following implementations of said interface: Gaufrette\Adapter\AclAwareAmazonS3, Gaufrette\Adapter\AmazonS3, Gaufrette\Adapter\AwsS3, Gaufrette\Adapter\AzureBlobStorage, Gaufrette\Adapter\Cache, Gaufrette\Adapter\GoogleCloudStorage, Gaufrette\Adapter\GridFS.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
219
220
            return true;
221
        }
222
223
        return false;
224
    }
225
226
    /**
227
     * @return bool
228
     */
229
    private function supportsMetadata()
230
    {
231
        return $this->filesystem->getAdapter() instanceof MetadataSupporter;
232
    }
233
}
234