Completed
Pull Request — master (#8233)
by Robin
19:58
created
lib/private/Files/ObjectStore/Swift.php 1 patch
Indentation   +244 added lines, -244 removed lines patch added patch discarded remove patch
@@ -39,249 +39,249 @@
 block discarded – undo
39 39
 
40 40
 class Swift implements IObjectStore {
41 41
 
42
-	/**
43
-	 * @var \OpenCloud\OpenStack
44
-	 */
45
-	private $client;
46
-
47
-	/**
48
-	 * @var array
49
-	 */
50
-	private $params;
51
-
52
-	/**
53
-	 * @var \OpenCloud\ObjectStore\Service
54
-	 */
55
-	private $objectStoreService;
56
-
57
-	/**
58
-	 * @var \OpenCloud\ObjectStore\Resource\Container
59
-	 */
60
-	private $container;
61
-
62
-	private $memcache;
63
-
64
-	public function __construct($params) {
65
-		if (isset($params['bucket'])) {
66
-			$params['container'] = $params['bucket'];
67
-		}
68
-		if (!isset($params['container'])) {
69
-			$params['container'] = 'owncloud';
70
-		}
71
-		if (!isset($params['autocreate'])) {
72
-			// should only be true for tests
73
-			$params['autocreate'] = false;
74
-		}
75
-
76
-		if (isset($params['apiKey'])) {
77
-			$this->client = new Rackspace($params['url'], $params);
78
-			$cacheKey = $params['username'] . '@' . $params['url'] . '/' . $params['bucket'];
79
-		} else {
80
-			$this->client = new OpenStack($params['url'], $params);
81
-			$cacheKey = $params['username'] . '@' . $params['url'] . '/' . $params['bucket'];
82
-		}
83
-
84
-		$cacheFactory = \OC::$server->getMemCacheFactory();
85
-		$this->memcache = $cacheFactory->createDistributed('swift::' . $cacheKey);
86
-
87
-		$this->params = $params;
88
-	}
89
-
90
-	protected function init() {
91
-		if ($this->container) {
92
-			return;
93
-		}
94
-
95
-		$this->importToken();
96
-
97
-		/** @var Token $token */
98
-		$token = $this->client->getTokenObject();
99
-
100
-		if (!$token || $token->hasExpired()) {
101
-			try {
102
-				$this->client->authenticate();
103
-				$this->exportToken();
104
-			} catch (ClientErrorResponseException $e) {
105
-				$statusCode = $e->getResponse()->getStatusCode();
106
-				if ($statusCode == 412) {
107
-					throw new StorageAuthException('Precondition failed, verify the keystone url', $e);
108
-				} else if ($statusCode === 401) {
109
-					throw new StorageAuthException('Authentication failed, verify the username, password and possibly tenant', $e);
110
-				} else {
111
-					throw new StorageAuthException('Unknown error', $e);
112
-				}
113
-			}
114
-		}
115
-
116
-
117
-		/** @var Catalog $catalog */
118
-		$catalog = $this->client->getCatalog();
119
-
120
-		if (isset($this->params['serviceName'])) {
121
-			$serviceName = $this->params['serviceName'];
122
-		} else {
123
-			$serviceName = Service::DEFAULT_NAME;
124
-		}
125
-
126
-		if (isset($this->params['urlType'])) {
127
-			$urlType = $this->params['urlType'];
128
-			if ($urlType !== 'internalURL' && $urlType !== 'publicURL') {
129
-				throw new StorageNotAvailableException('Invalid url type');
130
-			}
131
-		} else {
132
-			$urlType = Service::DEFAULT_URL_TYPE;
133
-		}
134
-
135
-		$catalogItem = $this->getCatalogForService($catalog, $serviceName);
136
-		if (!$catalogItem) {
137
-			$available = implode(', ', $this->getAvailableServiceNames($catalog));
138
-			throw new StorageNotAvailableException(
139
-				"Service $serviceName not found in service catalog, available services: $available"
140
-			);
141
-		} else if (isset($this->params['region'])) {
142
-			$this->validateRegion($catalogItem, $this->params['region']);
143
-		}
144
-
145
-		$this->objectStoreService = $this->client->objectStoreService($serviceName, $this->params['region'], $urlType);
146
-
147
-		try {
148
-			$this->container = $this->objectStoreService->getContainer($this->params['container']);
149
-		} catch (ClientErrorResponseException $ex) {
150
-			// if the container does not exist and autocreate is true try to create the container on the fly
151
-			if (isset($this->params['autocreate']) && $this->params['autocreate'] === true) {
152
-				$this->container = $this->objectStoreService->createContainer($this->params['container']);
153
-			} else {
154
-				throw $ex;
155
-			}
156
-		}
157
-	}
158
-
159
-	private function exportToken() {
160
-		$export = $this->client->exportCredentials();
161
-		$export['catalog'] = array_map(function (CatalogItem $item) {
162
-			return [
163
-				'name' => $item->getName(),
164
-				'endpoints' => $item->getEndpoints(),
165
-				'type' => $item->getType()
166
-			];
167
-		}, $export['catalog']->getItems());
168
-		$this->memcache->set('token', json_encode($export));
169
-	}
170
-
171
-	private function importToken() {
172
-		$cachedTokenString = $this->memcache->get('token');
173
-		if ($cachedTokenString) {
174
-			$cachedToken = json_decode($cachedTokenString, true);
175
-			$cachedToken['catalog'] = array_map(function (array $item) {
176
-				$itemClass = new \stdClass();
177
-				$itemClass->name = $item['name'];
178
-				$itemClass->endpoints = array_map(function (array $endpoint) {
179
-					return (object) $endpoint;
180
-				}, $item['endpoints']);
181
-				$itemClass->type = $item['type'];
182
-
183
-				return $itemClass;
184
-			}, $cachedToken['catalog']);
185
-			try {
186
-				$this->client->importCredentials($cachedToken);
187
-			} catch (\Exception $e) {
188
-				$this->client->setTokenObject(new Token());
189
-			}
190
-		}
191
-	}
192
-
193
-	/**
194
-	 * @param Catalog $catalog
195
-	 * @param $name
196
-	 * @return null|CatalogItem
197
-	 */
198
-	private function getCatalogForService(Catalog $catalog, $name) {
199
-		foreach ($catalog->getItems() as $item) {
200
-			/** @var CatalogItem $item */
201
-			if ($item->hasType(Service::DEFAULT_TYPE) && $item->hasName($name)) {
202
-				return $item;
203
-			}
204
-		}
205
-
206
-		return null;
207
-	}
208
-
209
-	private function validateRegion(CatalogItem $item, $region) {
210
-		$endPoints = $item->getEndpoints();
211
-		foreach ($endPoints as $endPoint) {
212
-			if ($endPoint->region === $region) {
213
-				return;
214
-			}
215
-		}
216
-
217
-		$availableRegions = implode(', ', array_map(function ($endpoint) {
218
-			return $endpoint->region;
219
-		}, $endPoints));
220
-
221
-		throw new StorageNotAvailableException("Invalid region '$region', available regions: $availableRegions");
222
-	}
223
-
224
-	private function getAvailableServiceNames(Catalog $catalog) {
225
-		return array_map(function (CatalogItem $item) {
226
-			return $item->getName();
227
-		}, array_filter($catalog->getItems(), function (CatalogItem $item) {
228
-			return $item->hasType(Service::DEFAULT_TYPE);
229
-		}));
230
-	}
231
-
232
-	/**
233
-	 * @return string the container name where objects are stored
234
-	 */
235
-	public function getStorageId() {
236
-		return $this->params['container'];
237
-	}
238
-
239
-	/**
240
-	 * @param string $urn the unified resource name used to identify the object
241
-	 * @param resource $stream stream with the data to write
242
-	 * @throws Exception from openstack lib when something goes wrong
243
-	 */
244
-	public function writeObject($urn, $stream) {
245
-		$this->init();
246
-		$this->container->uploadObject($urn, $stream);
247
-	}
248
-
249
-	/**
250
-	 * @param string $urn the unified resource name used to identify the object
251
-	 * @return resource stream with the read data
252
-	 * @throws Exception from openstack lib when something goes wrong
253
-	 */
254
-	public function readObject($urn) {
255
-		$this->init();
256
-		$object = $this->container->getObject($urn);
257
-
258
-		// we need to keep a reference to objectContent or
259
-		// the stream will be closed before we can do anything with it
260
-		/** @var $objectContent \Guzzle\Http\EntityBody * */
261
-		$objectContent = $object->getContent();
262
-		$objectContent->rewind();
263
-
264
-		$stream = $objectContent->getStream();
265
-		// save the object content in the context of the stream to prevent it being gc'd until the stream is closed
266
-		stream_context_set_option($stream, 'swift', 'content', $objectContent);
267
-
268
-		return RetryWrapper::wrap($stream);
269
-	}
270
-
271
-	/**
272
-	 * @param string $urn Unified Resource Name
273
-	 * @return void
274
-	 * @throws Exception from openstack lib when something goes wrong
275
-	 */
276
-	public function deleteObject($urn) {
277
-		$this->init();
278
-		// see https://github.com/rackspace/php-opencloud/issues/243#issuecomment-30032242
279
-		$this->container->dataObject()->setName($urn)->delete();
280
-	}
281
-
282
-	public function deleteContainer($recursive = false) {
283
-		$this->init();
284
-		$this->container->delete($recursive);
285
-	}
42
+    /**
43
+     * @var \OpenCloud\OpenStack
44
+     */
45
+    private $client;
46
+
47
+    /**
48
+     * @var array
49
+     */
50
+    private $params;
51
+
52
+    /**
53
+     * @var \OpenCloud\ObjectStore\Service
54
+     */
55
+    private $objectStoreService;
56
+
57
+    /**
58
+     * @var \OpenCloud\ObjectStore\Resource\Container
59
+     */
60
+    private $container;
61
+
62
+    private $memcache;
63
+
64
+    public function __construct($params) {
65
+        if (isset($params['bucket'])) {
66
+            $params['container'] = $params['bucket'];
67
+        }
68
+        if (!isset($params['container'])) {
69
+            $params['container'] = 'owncloud';
70
+        }
71
+        if (!isset($params['autocreate'])) {
72
+            // should only be true for tests
73
+            $params['autocreate'] = false;
74
+        }
75
+
76
+        if (isset($params['apiKey'])) {
77
+            $this->client = new Rackspace($params['url'], $params);
78
+            $cacheKey = $params['username'] . '@' . $params['url'] . '/' . $params['bucket'];
79
+        } else {
80
+            $this->client = new OpenStack($params['url'], $params);
81
+            $cacheKey = $params['username'] . '@' . $params['url'] . '/' . $params['bucket'];
82
+        }
83
+
84
+        $cacheFactory = \OC::$server->getMemCacheFactory();
85
+        $this->memcache = $cacheFactory->createDistributed('swift::' . $cacheKey);
86
+
87
+        $this->params = $params;
88
+    }
89
+
90
+    protected function init() {
91
+        if ($this->container) {
92
+            return;
93
+        }
94
+
95
+        $this->importToken();
96
+
97
+        /** @var Token $token */
98
+        $token = $this->client->getTokenObject();
99
+
100
+        if (!$token || $token->hasExpired()) {
101
+            try {
102
+                $this->client->authenticate();
103
+                $this->exportToken();
104
+            } catch (ClientErrorResponseException $e) {
105
+                $statusCode = $e->getResponse()->getStatusCode();
106
+                if ($statusCode == 412) {
107
+                    throw new StorageAuthException('Precondition failed, verify the keystone url', $e);
108
+                } else if ($statusCode === 401) {
109
+                    throw new StorageAuthException('Authentication failed, verify the username, password and possibly tenant', $e);
110
+                } else {
111
+                    throw new StorageAuthException('Unknown error', $e);
112
+                }
113
+            }
114
+        }
115
+
116
+
117
+        /** @var Catalog $catalog */
118
+        $catalog = $this->client->getCatalog();
119
+
120
+        if (isset($this->params['serviceName'])) {
121
+            $serviceName = $this->params['serviceName'];
122
+        } else {
123
+            $serviceName = Service::DEFAULT_NAME;
124
+        }
125
+
126
+        if (isset($this->params['urlType'])) {
127
+            $urlType = $this->params['urlType'];
128
+            if ($urlType !== 'internalURL' && $urlType !== 'publicURL') {
129
+                throw new StorageNotAvailableException('Invalid url type');
130
+            }
131
+        } else {
132
+            $urlType = Service::DEFAULT_URL_TYPE;
133
+        }
134
+
135
+        $catalogItem = $this->getCatalogForService($catalog, $serviceName);
136
+        if (!$catalogItem) {
137
+            $available = implode(', ', $this->getAvailableServiceNames($catalog));
138
+            throw new StorageNotAvailableException(
139
+                "Service $serviceName not found in service catalog, available services: $available"
140
+            );
141
+        } else if (isset($this->params['region'])) {
142
+            $this->validateRegion($catalogItem, $this->params['region']);
143
+        }
144
+
145
+        $this->objectStoreService = $this->client->objectStoreService($serviceName, $this->params['region'], $urlType);
146
+
147
+        try {
148
+            $this->container = $this->objectStoreService->getContainer($this->params['container']);
149
+        } catch (ClientErrorResponseException $ex) {
150
+            // if the container does not exist and autocreate is true try to create the container on the fly
151
+            if (isset($this->params['autocreate']) && $this->params['autocreate'] === true) {
152
+                $this->container = $this->objectStoreService->createContainer($this->params['container']);
153
+            } else {
154
+                throw $ex;
155
+            }
156
+        }
157
+    }
158
+
159
+    private function exportToken() {
160
+        $export = $this->client->exportCredentials();
161
+        $export['catalog'] = array_map(function (CatalogItem $item) {
162
+            return [
163
+                'name' => $item->getName(),
164
+                'endpoints' => $item->getEndpoints(),
165
+                'type' => $item->getType()
166
+            ];
167
+        }, $export['catalog']->getItems());
168
+        $this->memcache->set('token', json_encode($export));
169
+    }
170
+
171
+    private function importToken() {
172
+        $cachedTokenString = $this->memcache->get('token');
173
+        if ($cachedTokenString) {
174
+            $cachedToken = json_decode($cachedTokenString, true);
175
+            $cachedToken['catalog'] = array_map(function (array $item) {
176
+                $itemClass = new \stdClass();
177
+                $itemClass->name = $item['name'];
178
+                $itemClass->endpoints = array_map(function (array $endpoint) {
179
+                    return (object) $endpoint;
180
+                }, $item['endpoints']);
181
+                $itemClass->type = $item['type'];
182
+
183
+                return $itemClass;
184
+            }, $cachedToken['catalog']);
185
+            try {
186
+                $this->client->importCredentials($cachedToken);
187
+            } catch (\Exception $e) {
188
+                $this->client->setTokenObject(new Token());
189
+            }
190
+        }
191
+    }
192
+
193
+    /**
194
+     * @param Catalog $catalog
195
+     * @param $name
196
+     * @return null|CatalogItem
197
+     */
198
+    private function getCatalogForService(Catalog $catalog, $name) {
199
+        foreach ($catalog->getItems() as $item) {
200
+            /** @var CatalogItem $item */
201
+            if ($item->hasType(Service::DEFAULT_TYPE) && $item->hasName($name)) {
202
+                return $item;
203
+            }
204
+        }
205
+
206
+        return null;
207
+    }
208
+
209
+    private function validateRegion(CatalogItem $item, $region) {
210
+        $endPoints = $item->getEndpoints();
211
+        foreach ($endPoints as $endPoint) {
212
+            if ($endPoint->region === $region) {
213
+                return;
214
+            }
215
+        }
216
+
217
+        $availableRegions = implode(', ', array_map(function ($endpoint) {
218
+            return $endpoint->region;
219
+        }, $endPoints));
220
+
221
+        throw new StorageNotAvailableException("Invalid region '$region', available regions: $availableRegions");
222
+    }
223
+
224
+    private function getAvailableServiceNames(Catalog $catalog) {
225
+        return array_map(function (CatalogItem $item) {
226
+            return $item->getName();
227
+        }, array_filter($catalog->getItems(), function (CatalogItem $item) {
228
+            return $item->hasType(Service::DEFAULT_TYPE);
229
+        }));
230
+    }
231
+
232
+    /**
233
+     * @return string the container name where objects are stored
234
+     */
235
+    public function getStorageId() {
236
+        return $this->params['container'];
237
+    }
238
+
239
+    /**
240
+     * @param string $urn the unified resource name used to identify the object
241
+     * @param resource $stream stream with the data to write
242
+     * @throws Exception from openstack lib when something goes wrong
243
+     */
244
+    public function writeObject($urn, $stream) {
245
+        $this->init();
246
+        $this->container->uploadObject($urn, $stream);
247
+    }
248
+
249
+    /**
250
+     * @param string $urn the unified resource name used to identify the object
251
+     * @return resource stream with the read data
252
+     * @throws Exception from openstack lib when something goes wrong
253
+     */
254
+    public function readObject($urn) {
255
+        $this->init();
256
+        $object = $this->container->getObject($urn);
257
+
258
+        // we need to keep a reference to objectContent or
259
+        // the stream will be closed before we can do anything with it
260
+        /** @var $objectContent \Guzzle\Http\EntityBody * */
261
+        $objectContent = $object->getContent();
262
+        $objectContent->rewind();
263
+
264
+        $stream = $objectContent->getStream();
265
+        // save the object content in the context of the stream to prevent it being gc'd until the stream is closed
266
+        stream_context_set_option($stream, 'swift', 'content', $objectContent);
267
+
268
+        return RetryWrapper::wrap($stream);
269
+    }
270
+
271
+    /**
272
+     * @param string $urn Unified Resource Name
273
+     * @return void
274
+     * @throws Exception from openstack lib when something goes wrong
275
+     */
276
+    public function deleteObject($urn) {
277
+        $this->init();
278
+        // see https://github.com/rackspace/php-opencloud/issues/243#issuecomment-30032242
279
+        $this->container->dataObject()->setName($urn)->delete();
280
+    }
281
+
282
+    public function deleteContainer($recursive = false) {
283
+        $this->init();
284
+        $this->container->delete($recursive);
285
+    }
286 286
 
287 287
 }
Please login to merge, or discard this patch.