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