1 | <?php |
||
10 | class AwsS3Resolver implements ResolverInterface |
||
11 | { |
||
12 | /** |
||
13 | * @var S3Client |
||
14 | */ |
||
15 | protected $storage; |
||
16 | |||
17 | /** |
||
18 | * @var string |
||
19 | */ |
||
20 | protected $bucket; |
||
21 | |||
22 | /** |
||
23 | * @var string |
||
24 | */ |
||
25 | protected $acl; |
||
26 | |||
27 | /** |
||
28 | * @var array |
||
29 | */ |
||
30 | protected $getOptions; |
||
31 | |||
32 | /** |
||
33 | * Object options added to PUT requests. |
||
34 | * |
||
35 | * @var array |
||
36 | */ |
||
37 | protected $putOptions; |
||
38 | |||
39 | /** |
||
40 | * @var LoggerInterface |
||
41 | */ |
||
42 | protected $logger; |
||
43 | |||
44 | /** |
||
45 | * @var string |
||
46 | */ |
||
47 | protected $cachePrefix; |
||
48 | |||
49 | /** |
||
50 | * Constructs a cache resolver storing images on Amazon S3. |
||
51 | * |
||
52 | * @param S3Client $storage The Amazon S3 storage API. It's required to know authentication information. |
||
53 | * @param string $bucket The bucket name to operate on. |
||
54 | * @param string $acl The ACL to use when storing new objects. Default: owner read/write, public read |
||
55 | * @param array $getOptions A list of options to be passed when retrieving the object url from Amazon S3. |
||
56 | * @param array $putOptions A list of options to be passed when saving the object to Amazon S3. |
||
57 | */ |
||
58 | public function __construct(S3Client $storage, $bucket, $acl = 'public-read', array $getOptions = array(), $putOptions = array()) |
||
59 | { |
||
60 | $this->storage = $storage; |
||
61 | $this->bucket = $bucket; |
||
62 | $this->acl = $acl; |
||
63 | $this->getOptions = $getOptions; |
||
64 | $this->putOptions = $putOptions; |
||
65 | } |
||
66 | |||
67 | /** |
||
68 | * @param LoggerInterface $logger |
||
69 | */ |
||
70 | public function setLogger(LoggerInterface $logger) |
||
74 | |||
75 | /** |
||
76 | * @param string $cachePrefix |
||
77 | */ |
||
78 | public function setCachePrefix($cachePrefix) |
||
82 | |||
83 | /** |
||
84 | * {@inheritdoc} |
||
85 | */ |
||
86 | public function isStored($path, $filter) |
||
90 | |||
91 | /** |
||
92 | * {@inheritdoc} |
||
93 | */ |
||
94 | public function resolve($path, $filter) |
||
98 | |||
99 | /** |
||
100 | * {@inheritdoc} |
||
101 | */ |
||
102 | public function store(BinaryInterface $binary, $path, $filter) |
||
103 | { |
||
104 | $objectPath = $this->getObjectPath($path, $filter); |
||
105 | |||
106 | try { |
||
107 | $this->storage->putObject( |
||
108 | array_merge( |
||
109 | $this->putOptions, |
||
110 | array( |
||
111 | 'ACL' => $this->acl, |
||
112 | 'Bucket' => $this->bucket, |
||
113 | 'Key' => $objectPath, |
||
114 | 'Body' => $binary->getContent(), |
||
115 | 'ContentType' => $binary->getMimeType(), |
||
116 | ) |
||
117 | ) |
||
118 | ); |
||
119 | } catch (\Exception $e) { |
||
120 | $this->logError('The object could not be created on Amazon S3.', array( |
||
121 | 'objectPath' => $objectPath, |
||
122 | 'filter' => $filter, |
||
123 | 'bucket' => $this->bucket, |
||
124 | 'exception' => $e, |
||
125 | )); |
||
126 | |||
127 | throw new NotStorableException('The object could not be created on Amazon S3.', null, $e); |
||
128 | } |
||
129 | } |
||
130 | |||
131 | /** |
||
132 | * {@inheritdoc} |
||
133 | */ |
||
134 | public function remove(array $paths, array $filters) |
||
135 | { |
||
136 | if (empty($paths) && empty($filters)) { |
||
137 | return; |
||
138 | } |
||
139 | |||
140 | if (empty($paths)) { |
||
141 | try { |
||
142 | $this->storage->deleteMatchingObjects($this->bucket, null, sprintf( |
||
143 | '/%s/i', |
||
144 | implode('|', $filters) |
||
145 | )); |
||
146 | } catch (\Exception $e) { |
||
147 | $this->logError('The objects could not be deleted from Amazon S3.', array( |
||
148 | 'filter' => implode(', ', $filters), |
||
149 | 'bucket' => $this->bucket, |
||
150 | 'exception' => $e, |
||
151 | )); |
||
152 | } |
||
153 | |||
154 | return; |
||
155 | } |
||
156 | |||
157 | foreach ($filters as $filter) { |
||
158 | foreach ($paths as $path) { |
||
159 | $objectPath = $this->getObjectPath($path, $filter); |
||
160 | if (!$this->objectExists($objectPath)) { |
||
161 | continue; |
||
162 | } |
||
163 | |||
164 | try { |
||
165 | $this->storage->deleteObject(array( |
||
166 | 'Bucket' => $this->bucket, |
||
167 | 'Key' => $objectPath, |
||
168 | )); |
||
169 | } catch (\Exception $e) { |
||
170 | $this->logError('The object could not be deleted from Amazon S3.', array( |
||
171 | 'objectPath' => $objectPath, |
||
172 | 'filter' => $filter, |
||
173 | 'bucket' => $this->bucket, |
||
174 | 'exception' => $e, |
||
175 | )); |
||
176 | } |
||
177 | } |
||
178 | } |
||
179 | } |
||
180 | |||
181 | /** |
||
182 | * Sets a single option to be passed when retrieving an objects URL. |
||
183 | * |
||
184 | * If the option is already set, it will be overwritten. |
||
185 | * |
||
186 | * @see Aws\S3\S3Client::getObjectUrl() for available options. |
||
187 | * |
||
188 | * @param string $key The name of the option. |
||
189 | * @param mixed $value The value to be set. |
||
190 | * |
||
191 | * @return AmazonS3Resolver $this |
||
192 | * |
||
193 | * @deprecated Use `setGetOption` instead |
||
194 | */ |
||
195 | public function setObjectUrlOption($key, $value) |
||
196 | { |
||
197 | return $this->setGetOption($key, $value); |
||
198 | } |
||
199 | |||
200 | /** |
||
201 | * Sets a single option to be passed when retrieving an objects URL. |
||
202 | * |
||
203 | * If the option is already set, it will be overwritten. |
||
204 | * |
||
205 | * @see Aws\S3\S3Client::getObjectUrl() for available options. |
||
206 | * |
||
207 | * @param string $key The name of the option. |
||
208 | * @param mixed $value The value to be set. |
||
209 | * |
||
210 | * @return AmazonS3Resolver $this |
||
211 | */ |
||
212 | public function setGetOption($key, $value) |
||
213 | { |
||
214 | $this->getOptions[$key] = $value; |
||
215 | |||
216 | return $this; |
||
217 | } |
||
218 | |||
219 | /** |
||
220 | * Sets a single option to be passed when saving an object. |
||
221 | * |
||
222 | * If the option is already set, it will be overwritten. |
||
223 | * |
||
224 | * @see Aws\S3\S3Client::putObject() for available options. |
||
225 | * |
||
226 | * @param string $key The name of the option. |
||
227 | * @param mixed $value The value to be set. |
||
228 | * |
||
229 | * @return AmazonS3Resolver $this |
||
230 | */ |
||
231 | public function setPutOption($key, $value) |
||
232 | { |
||
233 | $this->putOptions[$key] = $value; |
||
234 | |||
235 | return $this; |
||
236 | } |
||
237 | |||
238 | /** |
||
239 | * Returns the object path within the bucket. |
||
240 | * |
||
241 | * @param string $path The base path of the resource. |
||
242 | * @param string $filter The name of the imagine filter in effect. |
||
243 | * |
||
244 | * @return string The path of the object on S3. |
||
245 | */ |
||
246 | protected function getObjectPath($path, $filter) |
||
247 | { |
||
248 | $path = $this->cachePrefix |
||
249 | ? sprintf('%s/%s/%s', $this->cachePrefix, $filter, $path) |
||
250 | : sprintf('%s/%s', $filter, $path); |
||
251 | |||
252 | return str_replace('//', '/', $path); |
||
253 | } |
||
254 | |||
255 | /** |
||
256 | * Returns the URL for an object saved on Amazon S3. |
||
257 | * |
||
258 | * @param string $path |
||
259 | * |
||
260 | * @return string |
||
261 | */ |
||
262 | protected function getObjectUrl($path) |
||
263 | { |
||
264 | return $this->storage->getObjectUrl($this->bucket, $path, 0, $this->getOptions); |
||
265 | } |
||
266 | |||
267 | /** |
||
268 | * Checks whether an object exists. |
||
269 | * |
||
270 | * @param string $objectPath |
||
271 | * |
||
272 | * @return bool |
||
273 | */ |
||
274 | protected function objectExists($objectPath) |
||
278 | |||
279 | /** |
||
280 | * @param mixed $message |
||
281 | * @param array $context |
||
282 | */ |
||
283 | protected function logError($message, array $context = array()) |
||
284 | { |
||
285 | if ($this->logger) { |
||
286 | $this->logger->error($message, $context); |
||
289 | } |
||
290 |