From 8c0e31edacf29f9dd9869c3a8f9a6649ab4eb280 Mon Sep 17 00:00:00 2001 From: Jeremy Pry Date: Wed, 14 Jan 2015 12:53:14 -0500 Subject: [PATCH 01/34] Update documentation Document the correct returned objects. --- lib/OpenCloud/Compute/Service.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/OpenCloud/Compute/Service.php b/lib/OpenCloud/Compute/Service.php index d34f6101a..bf8e4a571 100644 --- a/lib/OpenCloud/Compute/Service.php +++ b/lib/OpenCloud/Compute/Service.php @@ -102,7 +102,7 @@ public function server($id = null) * not having all the information you need. * @param array $filter - a set of key/value pairs that is passed to the * servers list for filtering - * @returns \OpenCloud\Common\Collection + * @returns \OpenCloud\Common\Collection\PaginatedIterator */ public function serverList($details = true, array $filter = array()) { @@ -128,7 +128,7 @@ public function network($id = null) * * @api * @param array $filter array of filter key/value pairs - * @return \OpenCloud\Common\Collection + * @return \OpenCloud\Common\Collection\PaginatedIterator */ public function networkList($filter = array()) { From 9f1f98dad7065ae18c9beef3657c7d6993811663 Mon Sep 17 00:00:00 2001 From: Jeremy Pry Date: Wed, 14 Jan 2015 13:01:54 -0500 Subject: [PATCH 02/34] Change @returns to @return --- lib/OpenCloud/Compute/Service.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/OpenCloud/Compute/Service.php b/lib/OpenCloud/Compute/Service.php index bf8e4a571..37d66a036 100644 --- a/lib/OpenCloud/Compute/Service.php +++ b/lib/OpenCloud/Compute/Service.php @@ -81,7 +81,7 @@ public function __construct(Client $client, $type = null, $name = null, $region * * @api * @param string $id - if specified, the server with the ID is retrieved - * @returns Resource\Server object + * @return Resource\Server object */ public function server($id = null) { @@ -102,7 +102,7 @@ public function server($id = null) * not having all the information you need. * @param array $filter - a set of key/value pairs that is passed to the * servers list for filtering - * @returns \OpenCloud\Common\Collection\PaginatedIterator + * @return \OpenCloud\Common\Collection\PaginatedIterator */ public function serverList($details = true, array $filter = array()) { From 76c72d283a2716ff4f391139e7c4b5234f1612b4 Mon Sep 17 00:00:00 2001 From: Shaunak Kashyap Date: Wed, 4 Mar 2015 05:04:24 -0800 Subject: [PATCH 03/34] Adding missing inline documentation in OpenCloud\ObjectStore classes. --- lib/OpenCloud/ObjectStore/AbstractService.php | 4 +- lib/OpenCloud/ObjectStore/CDNService.php | 14 ++++- .../Resource/AbstractContainer.php | 31 +++++++++- .../ObjectStore/Resource/AbstractResource.php | 62 +++++++++++++------ lib/OpenCloud/ObjectStore/Service.php | 55 +++++++++------- 5 files changed, 121 insertions(+), 45 deletions(-) diff --git a/lib/OpenCloud/ObjectStore/AbstractService.php b/lib/OpenCloud/ObjectStore/AbstractService.php index 8f92874f8..6094d7780 100644 --- a/lib/OpenCloud/ObjectStore/AbstractService.php +++ b/lib/OpenCloud/ObjectStore/AbstractService.php @@ -30,7 +30,9 @@ abstract class AbstractService extends CatalogService const MAX_OBJECT_SIZE = 5102410241025; /** - * @return Resource\Account + * Returns the Object Store account associated with the service. + * + * @return Resource\Account Object Store account */ public function getAccount() { diff --git a/lib/OpenCloud/ObjectStore/CDNService.php b/lib/OpenCloud/ObjectStore/CDNService.php index d45fc494d..0092941e0 100644 --- a/lib/OpenCloud/ObjectStore/CDNService.php +++ b/lib/OpenCloud/ObjectStore/CDNService.php @@ -31,8 +31,12 @@ class CDNService extends AbstractService /** * List CDN-enabled containers. * - * @param array $filter - * @return \OpenCloud\Common\Collection\PaginatedIterator + * @param array $filter Array of filter options such as: + * + * * `limit`: number of results to limit the list to. Optional. + * * `marker`: name of container after which to start the list. Optional. + * * `end_marker`: name of container before which to end the list. Optional. + * @return \OpenCloud\Common\Collection\PaginatedIterator Iterator to list of CDN-enabled containers */ public function listContainers(array $filter = array()) { @@ -40,6 +44,12 @@ public function listContainers(array $filter = array()) return $this->resourceList('CDNContainer', $this->getUrl(null, $filter), $this); } + /** + * Return an existing CDN-enabled container. + * + * @param \stdClass $data Data to initialize container. + * @return CDNContainer CDN-enabled Container + */ public function cdnContainer($data) { $container = new CDNContainer($this, $data); diff --git a/lib/OpenCloud/ObjectStore/Resource/AbstractContainer.php b/lib/OpenCloud/ObjectStore/Resource/AbstractContainer.php index a36320652..56cd1c2fa 100644 --- a/lib/OpenCloud/ObjectStore/Resource/AbstractContainer.php +++ b/lib/OpenCloud/ObjectStore/Resource/AbstractContainer.php @@ -50,13 +50,28 @@ public function __construct(ServiceInterface $service, $data = null) $this->populate($data); } + /** + * Return the transaction ID for an HTTP API operation. Useful for debugging. + * + * @return string Transaction ID + */ public function getTransId() { return $this->metadata->getProperty(HeaderConst::TRANS_ID); } + /** + * Returns whether this container is CDN-enabled or not. + * + * @return boolean true if this container is CDN-enabled; false, otherwise. + */ abstract public function isCdnEnabled(); + /** + * Returns whether this container has log retention enabled or not. + * + * @return boolean true if this container has log retention enabled; false, otherwise. + */ public function hasLogRetention() { if ($this instanceof CDNContainer) { @@ -66,11 +81,23 @@ public function hasLogRetention() } } + /** + * For internal use only + * + * @return string Name of the primary key field for this resource + */ public function primaryKeyField() { return 'name'; } + /** + * For internal use only + * + * @param string $path Path to add to URL. Optional. + * @param array $params Query parameters to add to URL. Optional. + * @return Url URL of this container + path + query parameters. + */ public function getUrl($path = null, array $params = array()) { if (strlen($this->getName()) == 0) { @@ -91,7 +118,7 @@ protected function createRefreshRequest() * This method will enable your CDN-enabled container to serve out HTML content like a website. * * @param $indexPage The data object name (i.e. a .html file) that will serve as the main index page. - * @return \Guzzle\Http\Message\Response + * @return \Guzzle\Http\Message\Response The HTTP response for this API operation. */ public function setStaticIndexPage($page) { @@ -110,7 +137,7 @@ public function setStaticIndexPage($page) * Set the default error page for your static site. * * @param $name The data object name (i.e. a .html file) that will serve as the main error page. - * @return \Guzzle\Http\Message\Response + * @return \Guzzle\Http\Message\Response The HTTP response for this operation. */ public function setStaticErrorPage($page) { diff --git a/lib/OpenCloud/ObjectStore/Resource/AbstractResource.php b/lib/OpenCloud/ObjectStore/Resource/AbstractResource.php index e2d494ede..8e16b30b3 100644 --- a/lib/OpenCloud/ObjectStore/Resource/AbstractResource.php +++ b/lib/OpenCloud/ObjectStore/Resource/AbstractResource.php @@ -45,16 +45,31 @@ public function __construct(ServiceInterface $service) $this->metadata = new $this->metadataClass; } + /** + * For internal use only. + * + * @return Service The ObjectStore service associated with this ObjectStore resource. + */ public function getService() { return $this->service; } + /** + * For internal use only. + * + * @return Service The CDN version of the ObjectStore service associated with this ObjectStore resource. + */ public function getCdnService() { return $this->service->getCDNService(); } + /** + * For internal use only. + * + * @return Client The HTTP client associated with the associated ObjectStore service. + */ public function getClient() { return $this->service->getClient(); @@ -62,10 +77,12 @@ public function getClient() /** * Factory method that allows for easy instantiation from a Response object. + * + * For internal use only. * - * @param Response $response - * @param ServiceInterface $service - * @return static + * @param Response $response HTTP response from an API operation. + * @param ServiceInterface $service The ObjectStore service to associate with this ObjectStore resource object. + * @return AbstractResource A concrete sub-class of `AbstractResource`. */ public static function fromResponse(Response $response, ServiceInterface $service) { @@ -81,8 +98,10 @@ public static function fromResponse(Response $response, ServiceInterface $servic /** * Trim headers of their resource-specific prefixes. * - * @param $headers - * @return array + * For internal use only. + * + * @param array $headers Headers as returned from an HTTP response + * @return array Trimmed headers */ public static function trimHeaders($headers) { @@ -121,8 +140,8 @@ protected static function stripPrefix($header) /** * Prepend/stock the header names with a resource-specific prefix. * - * @param array $headers - * @return array + * @param array $headers Headers to use on ObjectStore resource. + * @return array Headers returned with appropriate prefix as expected by ObjectStore service. */ public static function stockHeaders(array $headers) { @@ -147,11 +166,12 @@ public static function stockHeaders(array $headers) } /** - * Set the metadata (local-only) for this object. + * Set the metadata (local-only) for this object. You must call saveMetadata + * to actually persist the metadata using the ObjectStore service. * - * @param $data - * @param bool $constructFromResponse - * @return $this + * @param array $data Object/container metadata key/value pair array. + * @param bool $constructFromResponse Whether the metadata key/value pairs were obtiained from an HTTP response of an ObjectStore API operation. + * @return AbstractResource This object, with metadata set. */ public function setMetadata($data, $constructFromResponse = false) { @@ -167,7 +187,9 @@ public function setMetadata($data, $constructFromResponse = false) } /** - * @return \OpenCloud\Common\Metadata + * Returns metadata for this object. + * + * @return \OpenCloud\Common\Metadata Metadata set on this object. */ public function getMetadata() { @@ -180,7 +202,7 @@ public function getMetadata() * @param array $metadata The array of values you want to set as metadata * @param bool $stockPrefix Whether to prepend each array key with the metadata-specific prefix. For objects, this * would be X-Object-Meta-Foo => Bar - * @return mixed + * @return Response HTTP response from API operation. */ public function saveMetadata(array $metadata, $stockPrefix = true) { @@ -192,7 +214,7 @@ public function saveMetadata(array $metadata, $stockPrefix = true) /** * Retrieve metadata from the API. This method will then set and return this value. * - * @return \OpenCloud\Common\Metadata + * @return \OpenCloud\Common\Metadata Metadata returned from the ObjectStore service for this object/container. */ public function retrieveMetadata() { @@ -208,8 +230,8 @@ public function retrieveMetadata() /** * To delete or unset a particular metadata item. * - * @param $key - * @return mixed + * @param $key Metadata key to unset + * @return Response HTTP response returned from API operation to unset metadata item. */ public function unsetMetadataItem($key) { @@ -224,10 +246,12 @@ public function unsetMetadataItem($key) } /** - * Append a particular array of values to the existing metadata. Analogous to a merge. + * Append a particular array of values to the existing metadata. Analogous + * to a merge. You must call to actually persist the metadata using the + * ObjectStore service. * - * @param array $values - * @return array + * @param array $values The array of values you want to append to metadata. + * @return array Metadata, after `$values` are appended. */ public function appendToMetadata(array $values) { diff --git a/lib/OpenCloud/ObjectStore/Service.php b/lib/OpenCloud/ObjectStore/Service.php index f0e1c3dc9..babd764dd 100644 --- a/lib/OpenCloud/ObjectStore/Service.php +++ b/lib/OpenCloud/ObjectStore/Service.php @@ -59,7 +59,9 @@ public function __construct(Client $client, $type = null, $name = null, $region } /** - * @return CDNService + * Return the CDN version of the ObjectStore service. + * + * @return CDNService CDN version of the ObjectStore service */ public function getCdnService() { @@ -69,8 +71,12 @@ public function getCdnService() /** * List all available containers. * - * @param array $filter - * @return \OpenCloud\Common\Collection\PaginatedIterator + * @param array $filter Array of filter options such as: + * + * * `limit`: number of results to limit the list to. Optional. + * * `marker`: name of container after which to start the list. Optional. + * * `end_marker`: name of container before which to end the list. Optional. + * @return \OpenCloud\Common\Collection\PaginatedIterator Iterator to list of containers */ public function listContainers(array $filter = array()) { @@ -79,8 +85,10 @@ public function listContainers(array $filter = array()) } /** - * @param $data - * @return Container + * Return a new or existing (if name is specified) container. + * + * @param \stdClass $data Data to initialize container. Optional. + * @return Container Container */ public function getContainer($data = null) { @@ -90,9 +98,9 @@ public function getContainer($data = null) /** * Create a container for this service. * - * @param $name The name of the container + * @param string $name The name of the container * @param array $metadata Additional (optional) metadata to associate with the container - * @return bool|static + * @return bool|Container Newly-created Container upon success; false, otherwise */ public function createContainer($name, array $metadata = array()) { @@ -114,9 +122,9 @@ public function createContainer($name, array $metadata = array()) /** * Check the validity of a potential container name. * - * @param $name - * @return bool - * @throws \OpenCloud\Common\Exceptions\InvalidArgumentError + * @param string $name Name of container + * @return bool True if container name is valid + * @throws \OpenCloud\Common\Exceptions\InvalidArgumentError if container name is invalid */ public function checkContainerName($name) { @@ -145,12 +153,12 @@ public function checkContainerName($name) * will be ignored. You can create up to 1,000 new containers per extraction request. Also note that only regular * files will be uploaded. Empty directories, symlinks, and so on, will not be uploaded. * - * @param $path The path to the archive being extracted - * @param $archive The contents of the archive (either string or stream) + * @param string $path The path to the archive being extracted + * @param string|stream $archive The contents of the archive (either string or stream) * @param string $archiveType The type of archive you're using {@see \OpenCloud\ObjectStore\Constants\UrlType} - * @return \Guzzle\Http\Message\Response - * @throws Exception\BulkOperationException - * @throws \OpenCloud\Common\Exceptions\InvalidArgumentError + * @return \Guzzle\Http\Message\Response HTTP response from API + * @throws \OpenCloud\Common\Exceptions\InvalidArgumentError if specifed `$archiveType` is invalid + * @throws Exception\BulkOperationException if there are errors with the bulk extract */ public function bulkExtract($path = '', $archive, $archiveType = UrlType::TAR_GZ) { @@ -199,17 +207,17 @@ public function bulkDelete(array $paths) * and sent as individual requests. * * @param array $paths The objects you want to delete. Each path needs - * be formatted as /{containerName}/{objectName}. If - * you are deleting object_1 and object_2 from the - * photos_container, the array will be: + * be formatted as `/{containerName}/{objectName}`. If + * you are deleting `object_1` and `object_2` from the + * `photos_container`, the array will be: * * array( * '/photos_container/object_1', * '/photos_container/object_2' * ) * - * @return array The array of responses from the API - * @throws Exception\BulkOperationException + * @return array[Guzzle\Http\Message\Response] HTTP responses from the API + * @throws Exception\BulkOperationException if the bulk delete operation fails */ public function batchDelete(array $paths) { @@ -257,7 +265,12 @@ private function executeBatchDeleteRequest(array $paths) * * @param Container $old Where you're moving files from * @param Container $new Where you're moving files to - * @return array Of PUT responses + * @param array $options Options to configure the migration. Optional. Available options are: + * + * * `read.batchLimit`: Number of files to read at a time from `$old` container. Optional; default = 1000. + * * `write.batchLimit`: Number of files to write at a time to `$new` container. Optional; default = 1000. + * * `read.pageLimit`: Number of filenames to read at a time from `$old` container. Optional; default = 10000. + * @return array[Guzzle\Http\Message\Response] HTTP responses from the API */ public function migrateContainer(Container $old, Container $new, array $options = array()) { From f0fbce0ad750aa25147d6b38b9dab5185e644c64 Mon Sep 17 00:00:00 2001 From: Mark Challoner Date: Wed, 18 Mar 2015 14:50:43 +0000 Subject: [PATCH 04/34] Added symlink functionality via X-Object-Manifest header management --- lib/OpenCloud/Common/Constants/Header.php | 1 + .../ObjectStore/Resource/DataObject.php | 75 +++++++++++++++++-- .../ObjectStore/Resource/DataObjectTest.php | 17 +++++ 3 files changed, 88 insertions(+), 5 deletions(-) diff --git a/lib/OpenCloud/Common/Constants/Header.php b/lib/OpenCloud/Common/Constants/Header.php index c0246f71f..5de04bc2a 100644 --- a/lib/OpenCloud/Common/Constants/Header.php +++ b/lib/OpenCloud/Common/Constants/Header.php @@ -70,4 +70,5 @@ class Header const USER_AGENT = 'User-Agent'; const VARY = 'Vary'; const VIA = 'Via'; + const X_OBJECT_MANIFEST = 'X-Object-Manifest'; } diff --git a/lib/OpenCloud/ObjectStore/Resource/DataObject.php b/lib/OpenCloud/ObjectStore/Resource/DataObject.php index 5877431b8..ca74e4d66 100644 --- a/lib/OpenCloud/ObjectStore/Resource/DataObject.php +++ b/lib/OpenCloud/ObjectStore/Resource/DataObject.php @@ -76,6 +76,11 @@ class DataObject extends AbstractResource * @var string Etag. */ protected $etag; + + /** + * @var string Manifest. Can be null so we use false to mean unset. + */ + protected $manifest = false; /** * Also need to set Container parent and handle pseudo-directories. @@ -139,7 +144,9 @@ public function populateFromResponse(Response $response) ->setContentType((string) $headers[HeaderConst::CONTENT_TYPE]) ->setLastModified((string) $headers[HeaderConst::LAST_MODIFIED]) ->setContentLength((string) $headers[HeaderConst::CONTENT_LENGTH]) - ->setEtag((string) $headers[HeaderConst::ETAG]); + ->setEtag((string) $headers[HeaderConst::ETAG]) + // do not cast to a string to allow for null (i.e. no header) + ->setManifest($headers[HeaderConst::X_OBJECT_MANIFEST]); } public function refresh() @@ -293,6 +300,26 @@ public function getEtag() { return $this->etag ? : $this->content->getContentMd5(); } + + /** + * @param $manifest + * @return $this + */ + public function setManifest($manifest) + { + $this->manifest = $manifest; + + return $this; + } + + /** + * @return null|string + */ + public function getManifest() + { + // only make a request if manifest has not been set (is false) + return $this->manifest !== false ? $this->manifest : $this->getManifestHeader(); + } public function setLastModified($lastModified) { @@ -327,10 +354,11 @@ public function update($params = array()) // merge specific properties with metadata $metadata += array( - HeaderConst::CONTENT_TYPE => $this->contentType, - HeaderConst::LAST_MODIFIED => $this->lastModified, - HeaderConst::CONTENT_LENGTH => $this->contentLength, - HeaderConst::ETAG => $this->etag + HeaderConst::CONTENT_TYPE => $this->contentType, + HeaderConst::LAST_MODIFIED => $this->lastModified, + HeaderConst::CONTENT_LENGTH => $this->contentLength, + HeaderConst::ETAG => $this->etag, + HeaderConst::X_OBJECT_MANIFEST => $this->manifest ); return $this->container->uploadObject($this->name, $this->content, $metadata); @@ -354,6 +382,26 @@ public function delete($params = array()) { return $this->getService()->getClient()->delete($this->getUrl())->send(); } + + /** + * @param string $source Path (`container/object') of other object to symlink this object to + * @return \Guzzle\Http\Message\Response + */ + public function symlink($source) + { + $response = $this->getService() + ->getClient() + ->createRequest('PUT', $this->getUrl(), array( + HeaderConst::X_OBJECT_MANIFEST => (string) $source + )) + ->send(); + + if ($response->getStatusCode() == 201) { + $this->setManifest($source); + } + + return $response; + } /** * Get a temporary URL for this object. @@ -449,4 +497,21 @@ protected static function headerIsValidMetadata($header) return preg_match($pattern, $header); } + + /** + * @return null|string + */ + protected function getManifestHeader() + { + $response = $this->getService() + ->getClient() + ->head($this->getUrl()) + ->send(); + + $manifest = $response->getHeader(HeaderConst::X_OBJECT_MANIFEST); + + $this->setManifest($manifest); + + return $manifest; + } } diff --git a/tests/OpenCloud/Tests/ObjectStore/Resource/DataObjectTest.php b/tests/OpenCloud/Tests/ObjectStore/Resource/DataObjectTest.php index 8193c267d..fc67ad35d 100644 --- a/tests/OpenCloud/Tests/ObjectStore/Resource/DataObjectTest.php +++ b/tests/OpenCloud/Tests/ObjectStore/Resource/DataObjectTest.php @@ -101,4 +101,21 @@ public function test_Public_Urls() $this->assertNotNull($object->getPublicUrl(UrlType::STREAMING)); $this->assertNotNull($object->getPublicUrl(UrlType::IOS_STREAMING)); } + + public function test_Symlink() + { + $object = $this->container->dataObject('foobar'); + $this->assertInstanceOf( + 'Guzzle\Http\Message\Response', + $object->symlink('/new_container/new_object') + ); + } + + /** + * @expectedException OpenCloud\Common\Exceptions\NoNameError + */ + public function test_Symlink_Fails() + { + $this->container->dataObject()->symlink(null); + } } From 6ce77ce5adbdad7bfff439322c3400795ab13cfa Mon Sep 17 00:00:00 2001 From: Mark Challoner Date: Thu, 19 Mar 2015 18:28:25 +0000 Subject: [PATCH 05/34] Added createSymlinkFrom. Renamed symlink to createSymlinkTo. Made setManifest protected. Updated PHPDoc and tests. --- .../ObjectStore/Resource/DataObject.php | 69 ++++++++++++++----- .../ObjectStore/Resource/DataObjectTest.php | 34 ++++++--- 2 files changed, 78 insertions(+), 25 deletions(-) diff --git a/lib/OpenCloud/ObjectStore/Resource/DataObject.php b/lib/OpenCloud/ObjectStore/Resource/DataObject.php index ca74e4d66..ace797bd3 100644 --- a/lib/OpenCloud/ObjectStore/Resource/DataObject.php +++ b/lib/OpenCloud/ObjectStore/Resource/DataObject.php @@ -302,10 +302,10 @@ public function getEtag() } /** - * @param $manifest + * @param string $manifest Path (`container/object') to set as the value to X-Object-Manifest * @return $this */ - public function setManifest($manifest) + protected function setManifest($manifest) { $this->manifest = $manifest; @@ -313,7 +313,7 @@ public function setManifest($manifest) } /** - * @return null|string + * @return null|string Path (`container/object') from X-Object-Manifest header or null if the header does not exist */ public function getManifest() { @@ -384,23 +384,60 @@ public function delete($params = array()) } /** - * @param string $source Path (`container/object') of other object to symlink this object to - * @return \Guzzle\Http\Message\Response + * @param string $destination Path (`container/object') of other object to symlink this object to + * @return null|\Guzzle\Http\Message\Response The response or null if $this is not empty */ - public function symlink($source) + public function createSymlinkTo($destination) { - $response = $this->getService() - ->getClient() - ->createRequest('PUT', $this->getUrl(), array( - HeaderConst::X_OBJECT_MANIFEST => (string) $source - )) - ->send(); - - if ($response->getStatusCode() == 201) { - $this->setManifest($source); + if (!$this->name) { + throw new Exceptions\NoNameError(Lang::translate('Object has no name')); + } + + if ($this->getContentLength() == 0) { + $response = $this->getService() + ->getClient() + ->createRequest('PUT', $this->getUrl(), array( + HeaderConst::X_OBJECT_MANIFEST => (string) $destination + )) + ->send(); + + if ($response->getStatusCode() == 201) { + $this->setManifest($source); + } + + return $response; + } + + return null; + } + + /** + * @param string $source Path (`container/object') of other object to symlink this object from + * @return null|DataObject The symlinked object or null if object already exists and is not empty + */ + public function createSymlinkFrom($source) + { + if (!strlen($source)) { + throw new Exceptions\NoNameError(Lang::translate('Object has no name')); + } + + // Use ltrim to remove leading slash from source + list($containerName, $resourceName) = explode("/", ltrim($source, '/'), 2); + + $container = $this->getService()->getContainer($containerName); + + if ($unsafe = $container->objectExists($resourceName)) { + $object = $container->getPartialObject($source); + $unsafe = $object->getContentLength() > 0; + } + + if (!$unsafe) { + return $container->uploadObject($resourceName, 'data', array( + HeaderConst::X_OBJECT_MANIFEST => (string) $this->getUrl() + )); } - return $response; + return null; } /** diff --git a/tests/OpenCloud/Tests/ObjectStore/Resource/DataObjectTest.php b/tests/OpenCloud/Tests/ObjectStore/Resource/DataObjectTest.php index fc67ad35d..bac0ebebf 100644 --- a/tests/OpenCloud/Tests/ObjectStore/Resource/DataObjectTest.php +++ b/tests/OpenCloud/Tests/ObjectStore/Resource/DataObjectTest.php @@ -101,21 +101,37 @@ public function test_Public_Urls() $this->assertNotNull($object->getPublicUrl(UrlType::STREAMING)); $this->assertNotNull($object->getPublicUrl(UrlType::IOS_STREAMING)); } - - public function test_Symlink() + + public function test_Symlink_To() { $object = $this->container->dataObject('foobar'); - $this->assertInstanceOf( - 'Guzzle\Http\Message\Response', - $object->symlink('/new_container/new_object') - ); + $this->assertInstanceOf('Guzzle\Http\Message\Response', $object->createSymlinkTo('new_container/new_object')); + // @todo getManifest should return the manifest not null + //$this->assertEquals('new_container/new_object', $object->getManifest()); } - + + /** + * @expectedException OpenCloud\Common\Exceptions\NoNameError + */ + public function test_Symlink_To_Fails() + { + $object = $this->container->dataObject()->createSymlinkTo(null); + } + + public function test_Symlink_From() + { + $object = $this->container->dataObject('foobar'); + $symlink = $object->createSymlinkFrom('new_container/new_object'); + $this->assertInstanceOf('OpenCloud\ObjectStore\Resource\DataObject', $symlink); + // @todo getManifest should return the manifest not null + //$this->assertEquals('new_container/new_object', $symlink->getManifest()); + } + /** * @expectedException OpenCloud\Common\Exceptions\NoNameError */ - public function test_Symlink_Fails() + public function test_Symlink_From_Fails() { - $this->container->dataObject()->symlink(null); + $object = $this->container->dataObject()->createSymlinkFrom(null); } } From 78914cbf288e43b0dde15d9b0c4720b41e54b385 Mon Sep 17 00:00:00 2001 From: Jamie Hannaford Date: Fri, 20 Mar 2015 15:00:34 +0100 Subject: [PATCH 06/34] [ci skip] Add more links to our official docs --- README.md | 2 +- docs/README.md | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 docs/README.md diff --git a/README.md b/README.md index 6031cf4ac..8ddd9f1b5 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ PHP SDK for OpenStack/Rackspace APIs [![Latest Stable Version](https://poser.pugx.org/rackspace/php-opencloud/v/stable.png)](https://packagist.org/packages/rackspace/php-opencloud) [![Travis CI](https://secure.travis-ci.org/rackspace/php-opencloud.png)](https://travis-ci.org/rackspace/php-opencloud) [![Total Downloads](https://poser.pugx.org/rackspace/php-opencloud/downloads.png)](https://packagist.org/packages/rackspace/php-opencloud) -For SDKs in different languages, see http://developer.rackspace.com. +Our official documentation is now available on http://docs.php-opencloud.com. For SDKs in different languages, see http://developer.rackspace.com. The PHP SDK should work with most OpenStack-based cloud deployments, though it specifically targets the Rackspace public cloud. In diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..154fd158d --- /dev/null +++ b/docs/README.md @@ -0,0 +1,3 @@ +# Documentation + +Our official docs are hosted on http://docs.php-opencloud.com. From ceebd95ec570c671dc4dbe9e80eed64a38283a23 Mon Sep 17 00:00:00 2001 From: Mark Challoner Date: Fri, 20 Mar 2015 15:51:08 +0000 Subject: [PATCH 07/34] Added getManifest assertions to symlink tests --- .../ObjectStore/Resource/DataObjectTest.php | 36 ++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/tests/OpenCloud/Tests/ObjectStore/Resource/DataObjectTest.php b/tests/OpenCloud/Tests/ObjectStore/Resource/DataObjectTest.php index bac0ebebf..c7859649e 100644 --- a/tests/OpenCloud/Tests/ObjectStore/Resource/DataObjectTest.php +++ b/tests/OpenCloud/Tests/ObjectStore/Resource/DataObjectTest.php @@ -17,7 +17,10 @@ namespace OpenCloud\Tests\ObjectStore\Resource; +use Guzzle\Http\Message\Response; +use OpenCloud\Common\Constants\Header; use OpenCloud\ObjectStore\Constants\UrlType; +use OpenCloud\Tests\MockSubscriber; use OpenCloud\Tests\ObjectStore\ObjectStoreTestCase; class DataObjectTest extends ObjectStoreTestCase @@ -104,10 +107,11 @@ public function test_Public_Urls() public function test_Symlink_To() { + $targetName = 'new_container/new_object'; + $this->addMockSubscriber(new Response(200, array(Header::X_OBJECT_MANIFEST => $targetName))); $object = $this->container->dataObject('foobar'); - $this->assertInstanceOf('Guzzle\Http\Message\Response', $object->createSymlinkTo('new_container/new_object')); - // @todo getManifest should return the manifest not null - //$this->assertEquals('new_container/new_object', $object->getManifest()); + $this->assertInstanceOf('Guzzle\Http\Message\Response', $object->createSymlinkTo($targetName)); + $this->assertEquals($targetName, $object->getManifest()); } /** @@ -120,11 +124,27 @@ public function test_Symlink_To_Fails() public function test_Symlink_From() { - $object = $this->container->dataObject('foobar'); - $symlink = $object->createSymlinkFrom('new_container/new_object'); - $this->assertInstanceOf('OpenCloud\ObjectStore\Resource\DataObject', $symlink); - // @todo getManifest should return the manifest not null - //$this->assertEquals('new_container/new_object', $symlink->getManifest()); + $symlinkName = 'new_container/new_object'; + + // We have to fill the mock response queue to properly get the correct X-Object-Manifest header + // Container\dataObject( ) + // - Container\refresh( ) + $this->addMockSubscriber(new Response(200)); + // DataObject\createSymlinkFrom( ) + // - Container\createRefreshRequest( ) + $this->addMockSubscriber(new Response(200)); + // - CDNContainer\createRefreshRequest( ) + $this->addMockSubscriber(new Response(200)); + // - Container\objectExists( ) + $this->addMockSubscriber(new Response(200)); + // - Container\getPartialObject( ) + $this->addMockSubscriber(new Response(200)); + // - Container\uploadObject( ) + $this->addMockSubscriber(new Response(200, array(Header::X_OBJECT_MANIFEST => $symlinkName))); + + $object = $this->container->dataObject('foobar')->createSymlinkFrom($symlinkName); + $this->assertInstanceOf('OpenCloud\ObjectStore\Resource\DataObject', $object); + $this->assertEquals($symlinkName, $object->getManifest()); } /** From 32a4cf79b5f5c202535d8337d2ebf61054045c84 Mon Sep 17 00:00:00 2001 From: Jamie Hannaford Date: Fri, 20 Mar 2015 17:42:30 +0100 Subject: [PATCH 08/34] [ci skip] Fix incorrect method in docs --- doc/services/object-store/objects.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/services/object-store/objects.rst b/doc/services/object-store/objects.rst index 0eb0ea836..7d9b2120e 100644 --- a/doc/services/object-store/objects.rst +++ b/doc/services/object-store/objects.rst @@ -204,8 +204,8 @@ Get file name .. code-block:: php - /** @param $container OpenCloud\ObjectStore\Resource\Container */ - $container = $object->getContainer(); + /** @param $name string */ + $name = $object->getName(); Get file size From a5cba84be3c7362d74a3d93b97076f594ae92f36 Mon Sep 17 00:00:00 2001 From: Mark Challoner Date: Fri, 20 Mar 2015 17:25:06 +0000 Subject: [PATCH 09/34] Changed symlink failures from null to exceptions. Added tests. --- .../Exception/ObjectNotEmptyException.php | 35 ++++++++++++++++ .../ObjectStore/Resource/DataObject.php | 42 +++++++++---------- .../ObjectStore/Resource/DataObjectTest.php | 37 ++++++++++++++-- 3 files changed, 89 insertions(+), 25 deletions(-) create mode 100644 lib/OpenCloud/ObjectStore/Exception/ObjectNotEmptyException.php diff --git a/lib/OpenCloud/ObjectStore/Exception/ObjectNotEmptyException.php b/lib/OpenCloud/ObjectStore/Exception/ObjectNotEmptyException.php new file mode 100644 index 000000000..6bf75f2f9 --- /dev/null +++ b/lib/OpenCloud/ObjectStore/Exception/ObjectNotEmptyException.php @@ -0,0 +1,35 @@ +name = $name; + + return $e; + } +} diff --git a/lib/OpenCloud/ObjectStore/Resource/DataObject.php b/lib/OpenCloud/ObjectStore/Resource/DataObject.php index ace797bd3..12ab65d8b 100644 --- a/lib/OpenCloud/ObjectStore/Resource/DataObject.php +++ b/lib/OpenCloud/ObjectStore/Resource/DataObject.php @@ -24,6 +24,7 @@ use OpenCloud\Common\Exceptions; use OpenCloud\Common\Lang; use OpenCloud\ObjectStore\Constants\UrlType; +use OpenCloud\ObjectStore\Exception\ObjectNotEmptyException; /** * Objects are the basic storage entities in Cloud Files. They represent the @@ -393,22 +394,22 @@ public function createSymlinkTo($destination) throw new Exceptions\NoNameError(Lang::translate('Object has no name')); } - if ($this->getContentLength() == 0) { - $response = $this->getService() - ->getClient() - ->createRequest('PUT', $this->getUrl(), array( - HeaderConst::X_OBJECT_MANIFEST => (string) $destination - )) - ->send(); + if ($this->getContentLength()) { + throw new ObjectNotEmptyException($this->getContainer()->getName() . '/' . $this->getName()); + } - if ($response->getStatusCode() == 201) { - $this->setManifest($source); - } + $response = $this->getService() + ->getClient() + ->createRequest('PUT', $this->getUrl(), array( + HeaderConst::X_OBJECT_MANIFEST => (string) $destination + )) + ->send(); - return $response; + if ($response->getStatusCode() == 201) { + $this->setManifest($source); } - return null; + return $response; } /** @@ -423,21 +424,18 @@ public function createSymlinkFrom($source) // Use ltrim to remove leading slash from source list($containerName, $resourceName) = explode("/", ltrim($source, '/'), 2); - $container = $this->getService()->getContainer($containerName); - if ($unsafe = $container->objectExists($resourceName)) { + if ($container->objectExists($resourceName)) { $object = $container->getPartialObject($source); - $unsafe = $object->getContentLength() > 0; - } - - if (!$unsafe) { - return $container->uploadObject($resourceName, 'data', array( - HeaderConst::X_OBJECT_MANIFEST => (string) $this->getUrl() - )); + if ($object->getContentLength() > 0) { + throw new ObjectNotEmptyException($source); + } } - return null; + return $container->uploadObject($resourceName, 'data', array( + HeaderConst::X_OBJECT_MANIFEST => (string) $this->getUrl() + )); } /** diff --git a/tests/OpenCloud/Tests/ObjectStore/Resource/DataObjectTest.php b/tests/OpenCloud/Tests/ObjectStore/Resource/DataObjectTest.php index c7859649e..97af383a9 100644 --- a/tests/OpenCloud/Tests/ObjectStore/Resource/DataObjectTest.php +++ b/tests/OpenCloud/Tests/ObjectStore/Resource/DataObjectTest.php @@ -20,6 +20,7 @@ use Guzzle\Http\Message\Response; use OpenCloud\Common\Constants\Header; use OpenCloud\ObjectStore\Constants\UrlType; +use OpenCloud\ObjectStore\Exception\ObjectNotEmptyException; use OpenCloud\Tests\MockSubscriber; use OpenCloud\Tests\ObjectStore\ObjectStoreTestCase; @@ -117,11 +118,20 @@ public function test_Symlink_To() /** * @expectedException OpenCloud\Common\Exceptions\NoNameError */ - public function test_Symlink_To_Fails() + public function test_Symlink_To_Fails_With_NoName() { $object = $this->container->dataObject()->createSymlinkTo(null); } + /** + * @expectedException OpenCloud\ObjectStore\Exception\ObjectNotEmptyException + */ + public function test_Symlink_To_Fails_With_NotEmpty() + { + $this->addMockSubscriber(new Response(200, array(Header::CONTENT_LENGTH => 100))); + $object = $this->container->dataObject('foobar')->createSymlinkTo('new_container/new_object'); + } + public function test_Symlink_From() { $symlinkName = 'new_container/new_object'; @@ -144,14 +154,35 @@ public function test_Symlink_From() $object = $this->container->dataObject('foobar')->createSymlinkFrom($symlinkName); $this->assertInstanceOf('OpenCloud\ObjectStore\Resource\DataObject', $object); - $this->assertEquals($symlinkName, $object->getManifest()); } /** * @expectedException OpenCloud\Common\Exceptions\NoNameError */ - public function test_Symlink_From_Fails() + public function test_Symlink_From_Fails_With_NoName() { $object = $this->container->dataObject()->createSymlinkFrom(null); } + + /** + * @expectedException OpenCloud\ObjectStore\Exception\ObjectNotEmptyException + */ + public function test_Symlink_From_Fails_With_NotEmpty() + { + // We have to fill the mock response queue to properly get the correct Content-Length header + // Container\dataObject( ) + // - Container\refresh( ) + $this->addMockSubscriber(new Response(200)); + // DataObject\createSymlinkFrom( ) + // - Container\createRefreshRequest( ) + $this->addMockSubscriber(new Response(200)); + // - CDNContainer\createRefreshRequest( ) + $this->addMockSubscriber(new Response(200)); + // - Container\objectExists( ) + $this->addMockSubscriber(new Response(200)); + // - Container\getPartialObject( ) + $this->addMockSubscriber(new Response(200, array(Header::CONTENT_LENGTH => 100))); + + $object = $this->container->dataObject('foobar')->createSymlinkFrom('new_container/new_object'); + } } From f3a5658551004e0e88385ca48e9fdeddb0497c40 Mon Sep 17 00:00:00 2001 From: Mark Challoner Date: Fri, 20 Mar 2015 17:38:32 +0000 Subject: [PATCH 10/34] Added documentation --- doc/services/object-store/objects.rst | 35 ++++++++++++++++++++ samples/ObjectStore/symlink-object.php | 45 ++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 samples/ObjectStore/symlink-object.php diff --git a/doc/services/object-store/objects.rst b/doc/services/object-store/objects.rst index 0eb0ea836..107d7c584 100644 --- a/doc/services/object-store/objects.rst +++ b/doc/services/object-store/objects.rst @@ -326,6 +326,41 @@ the name of the object inside the container that does not exist yet. `Get the executable PHP script for this example `_ +Symlinking to this object from another location +----------------------------------------------- + +To create a symlink to this file in another location you need to specify +a string-based source + +.. code-block:: php + + $object->createSymlinkFrom('/container_2/new_object_name'); + +Where ``container_2`` is the name of the container, and ``new_object_name`` is +the name of the object inside the container that either does not exist yet or +is an empty file. + +`Get the executable PHP script for this example `_ + + +Setting this object to symlink to another location +-------------------------------------------------- + +To set this file to symlink to another location you need to specify +a string-based destination + +.. code-block:: php + + $object->createSymlinkTo('/container_2/new_object_name'); + +Where ``container_2`` is the name of the container, and ``new_object_name`` is +the name of the object inside the container. + +The object must be an empty file. + +`Get the executable PHP script for this example `_ + + Get object metadata ------------------- diff --git a/samples/ObjectStore/symlink-object.php b/samples/ObjectStore/symlink-object.php new file mode 100644 index 000000000..f5c4bc129 --- /dev/null +++ b/samples/ObjectStore/symlink-object.php @@ -0,0 +1,45 @@ + '{username}', + 'apiKey' => '{apiKey}', +)); + +// 2. Obtain an Object Store service object from the client. +$objectStoreService = $client->objectStoreService(null, '{region}'); + +// 3. Get container. +$container = $objectStoreService->getContainer('{sourceContainerName}'); + +// 4. Get object. +$object = $container->getObject('{objectName}'); + +// 5. Create another container for object's copy. +$objectStoreService->createContainer('{destinationContainerName}'); + +// 6. Symlink to object from another container object. {objectName} must either not exist or be an empty file. +$object->createSymlinkFrom('{destinationContainerName}/{objectName}'); + +// 7. Symlink from object to another container object. $object must be an empty file. +$object->createSymlinkTo('{destinationContainerName}/{objectName}'); From 27ed6104e7453ce75b42309cc8cf5d108b037993 Mon Sep 17 00:00:00 2001 From: justin Finkelstein Date: Sat, 21 Mar 2015 13:27:20 +0000 Subject: [PATCH 11/34] Added example of how to retrieve more than 10,000 objects --- doc/services/object-store/objects.rst | 36 +++++++++++ .../ObjectStore/list-objects-over-10000.php | 62 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 samples/ObjectStore/list-objects-over-10000.php diff --git a/doc/services/object-store/objects.rst b/doc/services/object-store/objects.rst index 0eb0ea836..50af7aff3 100644 --- a/doc/services/object-store/objects.rst +++ b/doc/services/object-store/objects.rst @@ -177,6 +177,42 @@ docs `_ +List over 10,000 objects +------------------------ + +To retrieve more than 10,000 objects (the default limit), you'll need to use +the built-in paging which uses a 'marker' parameter to fetch the next page of data. + +.. code-block:: php + + $containerObjects = array(); + $marker = ''; + + while ($marker !== null) { + $params = array( + 'marker' => $marker, + ); + + $objects = $container->objectList($params); + $total = $objects->count(); + $count = 0; + + if ($total == 0) { + break; + } + + while ($object = $objects->next()) { + /** @var $object OpenCloud\ObjectStore\Resource\DataObject **/ + $containerObjects[] = $object->getName(); + $count++; + + $marker = ($count == $total) ? $object->getName() : null; + } + } + +`Get the executable PHP script for this example `_ + + Get object ---------- diff --git a/samples/ObjectStore/list-objects-over-10000.php b/samples/ObjectStore/list-objects-over-10000.php new file mode 100644 index 000000000..364ebfdc7 --- /dev/null +++ b/samples/ObjectStore/list-objects-over-10000.php @@ -0,0 +1,62 @@ + '{username}', + 'apiKey' => '{apiKey}', +)); + +// 2. Obtain an Object Store service object from the client. +$objectStoreService = $client->objectStoreService(null, '{region}'); + +// 3. Get container. +$container = $objectStoreService->getContainer('{containerName}'); + +// 4. Get the list of objects +$objects = $container->objectList(); + +// 5. Create a list of all objects in the container +$containerObjects = array(); +$marker = ''; + +while ($marker !== null) { + $params = array( + 'marker' => $marker, + ); + + $objects = $container->objectList($params); + $total = $objects->count(); + $count = 0; + + if ($total == 0) { + break; + } + + while ($object = $objects->next()) { + /** @var $object OpenCloud\ObjectStore\Resource\DataObject **/ + $containerObjects[] = $object->getName(); + $count++; + + $marker = ($count == $total) ? $object->getName() : null; + } +} From 7d6a182d9904eaf48f8b80880eeb26f5cddc56ce Mon Sep 17 00:00:00 2001 From: justin Finkelstein Date: Sat, 21 Mar 2015 15:50:46 +0000 Subject: [PATCH 12/34] Updated to use foreach rather than while --- doc/services/object-store/objects.rst | 2 +- samples/ObjectStore/list-objects-over-10000.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/services/object-store/objects.rst b/doc/services/object-store/objects.rst index 50af7aff3..2f70be7e5 100644 --- a/doc/services/object-store/objects.rst +++ b/doc/services/object-store/objects.rst @@ -201,7 +201,7 @@ the built-in paging which uses a 'marker' parameter to fetch the next page of da break; } - while ($object = $objects->next()) { + foreach ($objects as $object) { /** @var $object OpenCloud\ObjectStore\Resource\DataObject **/ $containerObjects[] = $object->getName(); $count++; diff --git a/samples/ObjectStore/list-objects-over-10000.php b/samples/ObjectStore/list-objects-over-10000.php index 364ebfdc7..ec349e88d 100644 --- a/samples/ObjectStore/list-objects-over-10000.php +++ b/samples/ObjectStore/list-objects-over-10000.php @@ -52,7 +52,7 @@ break; } - while ($object = $objects->next()) { + foreach ($objects as $object) { /** @var $object OpenCloud\ObjectStore\Resource\DataObject **/ $containerObjects[] = $object->getName(); $count++; From 4e6b676ab4bfd314ac4fe1e8d0a90a73c826d755 Mon Sep 17 00:00:00 2001 From: Shaunak Kashyap Date: Sun, 22 Mar 2015 12:08:35 -0700 Subject: [PATCH 13/34] Fixing return type. --- lib/OpenCloud/DNS/Resource/Domain.php | 2 +- lib/OpenCloud/DNS/Service.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/OpenCloud/DNS/Resource/Domain.php b/lib/OpenCloud/DNS/Resource/Domain.php index cdd8ef28e..fc9bd89b8 100644 --- a/lib/OpenCloud/DNS/Resource/Domain.php +++ b/lib/OpenCloud/DNS/Resource/Domain.php @@ -76,7 +76,7 @@ public function record($info = null) * returns a Collection of Record objects * * @param array $filter query-string parameters - * @return \OpenCloud\Collection + * @return OpenCloud\DNS\Collection\DnsIterator */ public function recordList($filter = array()) { diff --git a/lib/OpenCloud/DNS/Service.php b/lib/OpenCloud/DNS/Service.php index cafb4ad94..cdee6dc48 100644 --- a/lib/OpenCloud/DNS/Service.php +++ b/lib/OpenCloud/DNS/Service.php @@ -59,7 +59,7 @@ public function domain($info = null) * Returns a collection of domains * * @param array $filter key/value pairs to use as query strings - * @return \OpenCloud\Common\Collection + * @return OpenCloud\DNS\Collection\DnsIterator */ public function domainList($filter = array()) { @@ -85,7 +85,7 @@ public function ptrRecord($info = null) * * @param \OpenCloud\Compute\Resource\Server $server the server for which to * retrieve the PTR records - * @return \OpenCloud\Common\Collection + * @return OpenCloud\DNS\Collection\DnsIterator */ public function ptrRecordList(HasPtrRecordsInterface $parent) { From 163b0358fecea3cc0069e75f53a4237024961a45 Mon Sep 17 00:00:00 2001 From: Shaunak Kashyap Date: Sun, 22 Mar 2015 12:08:46 -0700 Subject: [PATCH 14/34] Adding return type. --- lib/OpenCloud/DNS/Resource/Domain.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/OpenCloud/DNS/Resource/Domain.php b/lib/OpenCloud/DNS/Resource/Domain.php index fc9bd89b8..a103677f5 100644 --- a/lib/OpenCloud/DNS/Resource/Domain.php +++ b/lib/OpenCloud/DNS/Resource/Domain.php @@ -107,6 +107,7 @@ public function subdomain($info = array()) * * @param array $filter key/value pairs for query string parameters * return \OpenCloud\Collection + * @return OpenCloud\DNS\Collection\DnsIterator */ public function subdomainList($filter = array()) { From 1caf1d39f046b6f4da1c8a9572461c2058471711 Mon Sep 17 00:00:00 2001 From: Shaunak Kashyap Date: Sun, 22 Mar 2015 12:08:54 -0700 Subject: [PATCH 15/34] Adding docblock. --- lib/OpenCloud/DNS/Service.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/OpenCloud/DNS/Service.php b/lib/OpenCloud/DNS/Service.php index cdee6dc48..9d3bbc9dd 100644 --- a/lib/OpenCloud/DNS/Service.php +++ b/lib/OpenCloud/DNS/Service.php @@ -181,6 +181,13 @@ public function limitTypes() return $body->limitTypes; } + /** + * List asynchronous responses' statuses. + * @see http://docs.rackspace.com/cdns/api/v1.0/cdns-devguide/content/viewing_status_all_asynch_jobs.html + * + * @param array $query Any query parameters. Optional. + * @return OpenCloud\DNS\Collection\DnsIterator + */ public function listAsyncJobs(array $query = array()) { $url = clone $this->getUrl(); From 9958eb9b61dcff38b3a12e638451512539751ca7 Mon Sep 17 00:00:00 2001 From: Mark Challoner Date: Mon, 23 Mar 2015 15:09:51 +0000 Subject: [PATCH 16/34] Updated phpdoc for createSymlink functions --- lib/OpenCloud/ObjectStore/Resource/DataObject.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/OpenCloud/ObjectStore/Resource/DataObject.php b/lib/OpenCloud/ObjectStore/Resource/DataObject.php index 12ab65d8b..de302b4cd 100644 --- a/lib/OpenCloud/ObjectStore/Resource/DataObject.php +++ b/lib/OpenCloud/ObjectStore/Resource/DataObject.php @@ -385,8 +385,12 @@ public function delete($params = array()) } /** + * Create a symlink to another named object from this object. Requires this object to be empty. + * * @param string $destination Path (`container/object') of other object to symlink this object to - * @return null|\Guzzle\Http\Message\Response The response or null if $this is not empty + * @return \Guzzle\Http\Message\Response The response + * @throws \OpenCloud\Common\Exceptions\NoNameError if a destination name is not provided + * @throws \OpenCloud\ObjectStore\Exception\ObjectNotEmptyException if $this is not an empty object */ public function createSymlinkTo($destination) { @@ -413,8 +417,12 @@ public function createSymlinkTo($destination) } /** + * Create a symlink to this object from another named object. Requires the other object to either not exist or be empty. + * * @param string $source Path (`container/object') of other object to symlink this object from - * @return null|DataObject The symlinked object or null if object already exists and is not empty + * @return DataObject The symlinked object + * @throws \OpenCloud\Common\Exceptions\NoNameError if a source name is not provided + * @throws \OpenCloud\ObjectStore\Exception\ObjectNotEmptyException if object already exists and is not empty */ public function createSymlinkFrom($source) { From 450356387f84de00b8a485b5e64a18f466189bbe Mon Sep 17 00:00:00 2001 From: Shaunak Kashyap Date: Mon, 23 Mar 2015 10:41:16 -0700 Subject: [PATCH 17/34] Appeasing the PSR-2 linter. --- lib/OpenCloud/ObjectStore/Resource/AbstractResource.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/OpenCloud/ObjectStore/Resource/AbstractResource.php b/lib/OpenCloud/ObjectStore/Resource/AbstractResource.php index 8e16b30b3..37722e93d 100644 --- a/lib/OpenCloud/ObjectStore/Resource/AbstractResource.php +++ b/lib/OpenCloud/ObjectStore/Resource/AbstractResource.php @@ -77,7 +77,7 @@ public function getClient() /** * Factory method that allows for easy instantiation from a Response object. - * + * * For internal use only. * * @param Response $response HTTP response from an API operation. From 90dfc12c926c40c70289c599e17d1458f73abf38 Mon Sep 17 00:00:00 2001 From: Shaunak Kashyap Date: Mon, 23 Mar 2015 16:13:51 -0700 Subject: [PATCH 18/34] Lazily initialize CDN container object composed insider regular container object. --- .../ObjectStore/Resource/Container.php | 41 +++++++++++-------- .../Tests/ObjectStore/ObjectStoreTestCase.php | 11 +++-- .../ObjectStore/Resource/ContainerTest.php | 6 ++- .../ObjectStore/Resource/DataObjectTest.php | 2 + 4 files changed, 38 insertions(+), 22 deletions(-) diff --git a/lib/OpenCloud/ObjectStore/Resource/Container.php b/lib/OpenCloud/ObjectStore/Resource/Container.php index 0f7b0df08..57b8ce34a 100644 --- a/lib/OpenCloud/ObjectStore/Resource/Container.php +++ b/lib/OpenCloud/ObjectStore/Resource/Container.php @@ -323,23 +323,6 @@ public function refresh($id = null, $url = null) { $headers = $this->createRefreshRequest()->send()->getHeaders(); $this->setMetadata($headers, true); - - try { - if (null !== ($cdnService = $this->getService()->getCDNService())) { - $cdn = new CDNContainer($cdnService); - $cdn->setName($this->name); - - $response = $cdn->createRefreshRequest()->send(); - - if ($response->isSuccessful()) { - $this->cdn = $cdn; - $this->cdn->setMetadata($response->getHeaders(), true); - } - } else { - $this->cdn = null; - } - } catch (ClientErrorResponseException $e) { - } } /** @@ -597,6 +580,30 @@ public function uploadDirectory($path) public function isCdnEnabled() { + // If CDN object is not already populated, try to populate it. + if (null === $this->cdn) { + $this->refreshCdnObject(); + } return ($this->cdn instanceof CDNContainer) && $this->cdn->isCdnEnabled(); } + + protected function refreshCdnObject() + { + try { + if (null !== ($cdnService = $this->getService()->getCDNService())) { + $cdn = new CDNContainer($cdnService); + $cdn->setName($this->name); + + $response = $cdn->createRefreshRequest()->send(); + + if ($response->isSuccessful()) { + $this->cdn = $cdn; + $this->cdn->setMetadata($response->getHeaders(), true); + } + } else { + $this->cdn = null; + } + } catch (ClientErrorResponseException $e) { + } + } } diff --git a/tests/OpenCloud/Tests/ObjectStore/ObjectStoreTestCase.php b/tests/OpenCloud/Tests/ObjectStore/ObjectStoreTestCase.php index 985f7830c..3c3c995c4 100644 --- a/tests/OpenCloud/Tests/ObjectStore/ObjectStoreTestCase.php +++ b/tests/OpenCloud/Tests/ObjectStore/ObjectStoreTestCase.php @@ -42,7 +42,12 @@ public function setupObjects() $this->addMockSubscriber($response1); - $response2 = new Response(204, array( + $this->container = $this->service->getContainer('foo'); + } + + protected function setupCdnContainerMockResponse() + { + $response = new Response(204, array( 'X-Cdn-Ssl-Uri' => 'https://83c49b9a2f7ad18250b3-346eb45fd42c58ca13011d659bfc1ac1.ssl.cf0.rackcdn.com', 'X-Ttl' => '259200', 'X-Cdn-Uri' => 'http://081e40d3ee1cec5f77bf-346eb45fd42c58ca13011d659bfc1ac1.r49.cf0.rackcdn.com', @@ -52,8 +57,6 @@ public function setupObjects() 'X-Trans-Id' => 'tx82a6752e00424edb9c46fa2573132e2c' )); - $this->addMockSubscriber($response2); - - $this->container = $this->service->getContainer('foo'); + $this->addMockSubscriber($response); } } diff --git a/tests/OpenCloud/Tests/ObjectStore/Resource/ContainerTest.php b/tests/OpenCloud/Tests/ObjectStore/Resource/ContainerTest.php index b5d2bc602..c5b191249 100644 --- a/tests/OpenCloud/Tests/ObjectStore/Resource/ContainerTest.php +++ b/tests/OpenCloud/Tests/ObjectStore/Resource/ContainerTest.php @@ -51,6 +51,8 @@ public function test_Get_Container() $this->assertEquals('3846773', $container->getBytesUsed()); $this->assertFalse($container->hasLogRetention()); + $this->setupCdnContainerMockResponse(); + $cdn = $container->getCdn(); $this->assertInstanceOf('OpenCloud\ObjectStore\Resource\CDNContainer', $cdn); $this->assertEquals('tx82a6752e00424edb9c46fa2573132e2c', $cdn->getTransId()); @@ -115,13 +117,13 @@ public function test_Delete_NonEmpty_Container() $this->addMockSubscriber($this->makeResponse('[]', 409)); $container->delete(); } + public function test_Object_List() { $container = $this->container; $this->addMockSubscriber($this->makeResponse('[{"name":"test_obj_1","hash":"4281c348eaf83e70ddce0e07221c3d28","bytes":14,"content_type":"application\/octet-stream","last_modified":"2009-02-03T05:26:32.612278"},{"name":"test_obj_2","hash":"b039efe731ad111bc1b0ef221c3849d0","bytes":64,"content_type":"application\/octet-stream","last_modified":"2009-02-03T05:26:32.612278"}]', 200)); - $list = $container->objectList(); $this->assertInstanceOf(self::COLLECTION_CLASS, $list); $this->assertEquals('test_obj_1', $list->first()->getName()); @@ -141,6 +143,8 @@ public function test_Misc_Operations() $container->disableLogging() ); + $this->setupCdnContainerMockResponse(); + $this->assertInstanceOf( 'Guzzle\Http\Message\Response', $container->getCdn()->setStaticIndexPage('index.html') diff --git a/tests/OpenCloud/Tests/ObjectStore/Resource/DataObjectTest.php b/tests/OpenCloud/Tests/ObjectStore/Resource/DataObjectTest.php index 8193c267d..50a44d0ec 100644 --- a/tests/OpenCloud/Tests/ObjectStore/Resource/DataObjectTest.php +++ b/tests/OpenCloud/Tests/ObjectStore/Resource/DataObjectTest.php @@ -86,6 +86,7 @@ public function test_Temp_Url_Fails_With_Incorrect_Method() public function test_Purge() { $object = $this->container->dataObject('foobar'); + $this->setupCdnContainerMockResponse(); $this->assertInstanceOf( 'Guzzle\Http\Message\Response', $object->purge('test@example.com') @@ -96,6 +97,7 @@ public function test_Public_Urls() { $object = $this->container->dataObject('foobar'); + $this->setupCdnContainerMockResponse(); $this->assertNotNull($object->getPublicUrl()); $this->assertNotNull($object->getPublicUrl(UrlType::SSL)); $this->assertNotNull($object->getPublicUrl(UrlType::STREAMING)); From 7868606902b59f3ed5e2690b5445949aa81cd01e Mon Sep 17 00:00:00 2001 From: Shaunak Kashyap Date: Mon, 23 Mar 2015 16:28:30 -0700 Subject: [PATCH 19/34] Removing mocking for refreshing CDN container composed object. --- tests/OpenCloud/Tests/ObjectStore/Resource/DataObjectTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/OpenCloud/Tests/ObjectStore/Resource/DataObjectTest.php b/tests/OpenCloud/Tests/ObjectStore/Resource/DataObjectTest.php index cd35674d3..4bebaf346 100644 --- a/tests/OpenCloud/Tests/ObjectStore/Resource/DataObjectTest.php +++ b/tests/OpenCloud/Tests/ObjectStore/Resource/DataObjectTest.php @@ -178,8 +178,6 @@ public function test_Symlink_From_Fails_With_NotEmpty() // DataObject\createSymlinkFrom( ) // - Container\createRefreshRequest( ) $this->addMockSubscriber(new Response(200)); - // - CDNContainer\createRefreshRequest( ) - $this->addMockSubscriber(new Response(200)); // - Container\objectExists( ) $this->addMockSubscriber(new Response(200)); // - Container\getPartialObject( ) From 2bf6e0db9064d5f303cea2fba39fa77dc7d29334 Mon Sep 17 00:00:00 2001 From: Shaunak Kashyap Date: Fri, 27 Mar 2015 03:19:04 +0100 Subject: [PATCH 20/34] Fixing add, modify, and remove records links. --- doc/services/dns/domains.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/services/dns/domains.rst b/doc/services/dns/domains.rst index 0a7b83b96..b6c60290c 100644 --- a/doc/services/dns/domains.rst +++ b/doc/services/dns/domains.rst @@ -268,8 +268,8 @@ Modify domain Only the TTL, email address and comment attributes of a domain can be modified. Records cannot be added, modified, or removed through this API operation - you -will need to use the `add records `__, `modify records -`__ or `remove records `__ +will need to use the `add records `__, `modify records +`__ or `remove records `__ operations respectively. .. code-block:: php From 24b5e97e161a8f52438e5766ee6b1916a9fa2e99 Mon Sep 17 00:00:00 2001 From: Shaunak Kashyap Date: Fri, 27 Mar 2015 08:51:08 +0100 Subject: [PATCH 21/34] Adding convenience method to retrieve domain by name. --- .../Exceptions/DomainNotFoundException.php | 22 +++++++++++++++++++ lib/OpenCloud/DNS/Service.php | 19 ++++++++++++++++ tests/OpenCloud/Tests/DNS/ServiceTest.php | 9 ++++++++ 3 files changed, 50 insertions(+) create mode 100644 lib/OpenCloud/Common/Exceptions/DomainNotFoundException.php diff --git a/lib/OpenCloud/Common/Exceptions/DomainNotFoundException.php b/lib/OpenCloud/Common/Exceptions/DomainNotFoundException.php new file mode 100644 index 000000000..07ddfb608 --- /dev/null +++ b/lib/OpenCloud/Common/Exceptions/DomainNotFoundException.php @@ -0,0 +1,22 @@ +resource('Domain', $info); } + /** + * Returns a domain, given a domain name + * + * @param string $domainName Domain name + * @return Domain the domain object + */ + public function domainByName($domainName) + { + $domainList = $this->domainList(array("name" => $domainName)); + + if (count($domainList) != 1) { + throw new DomainNotFoundException(); + } + + return $this->resource('Domain', $domainList[0]); + } + + /** * Returns a collection of domains * diff --git a/tests/OpenCloud/Tests/DNS/ServiceTest.php b/tests/OpenCloud/Tests/DNS/ServiceTest.php index 73da7403e..5c299ff1c 100644 --- a/tests/OpenCloud/Tests/DNS/ServiceTest.php +++ b/tests/OpenCloud/Tests/DNS/ServiceTest.php @@ -40,6 +40,15 @@ public function testDomain() $this->assertInstanceOf('OpenCloud\DNS\Resource\Domain', $this->service->domain()); } + public function testDomainByName() + { + $this->addMockSubscriber($this->makeResponse('{"domains":[{"name":"region2.example.net","id":2725352,"updated":"2011-06-23T20:21:06.000+0000","created":"2011-06-23T19:24:27.000+0000"}],"totalEntries":114}', 200)); + $domain = $this->service->domainByName("region2.example.net"); + + $this->assertInstanceOf('OpenCloud\DNS\Resource\Domain', $domain); + $this->assertEquals("region2.example.net", $domain->getName()); + } + /** * @mockFile Domain_List */ From 920e1f3b14f6e54ce4146db11863e60afe5cfec5 Mon Sep 17 00:00:00 2001 From: Shaunak Kashyap Date: Fri, 27 Mar 2015 08:58:48 +0100 Subject: [PATCH 22/34] Adding test for domain not found, given domain name. --- tests/OpenCloud/Tests/DNS/ServiceTest.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/OpenCloud/Tests/DNS/ServiceTest.php b/tests/OpenCloud/Tests/DNS/ServiceTest.php index 5c299ff1c..9503e0409 100644 --- a/tests/OpenCloud/Tests/DNS/ServiceTest.php +++ b/tests/OpenCloud/Tests/DNS/ServiceTest.php @@ -49,6 +49,15 @@ public function testDomainByName() $this->assertEquals("region2.example.net", $domain->getName()); } + /** + * @expectedException OpenCloud\Common\Exceptions\DomainNotFoundException + */ + public function testDomainByNameWhenDomainNotFound() + { + $this->addMockSubscriber($this->makeResponse('{"domains":[],"totalEntries":114}', 200)); + $domain = $this->service->domainByName("region2.example.net"); + } + /** * @mockFile Domain_List */ From cebb5d5f517ee491345080e23699c0f2da71139f Mon Sep 17 00:00:00 2001 From: Shaunak Kashyap Date: Fri, 27 Mar 2015 09:40:29 +0100 Subject: [PATCH 23/34] Adding support for availability zones in Compute servers. --- lib/OpenCloud/Compute/Resource/Server.php | 13 +++++ .../create_server_with_availability_zone.php | 48 +++++++++++++++++++ .../Tests/Compute/Resource/ServerTest.php | 9 ++++ .../Tests/Compute/_response/Extensions.resp | 8 ++++ 4 files changed, 78 insertions(+) create mode 100644 samples/Compute/create_server_with_availability_zone.php diff --git a/lib/OpenCloud/Compute/Resource/Server.php b/lib/OpenCloud/Compute/Resource/Server.php index 11fb474ca..490c285e6 100644 --- a/lib/OpenCloud/Compute/Resource/Server.php +++ b/lib/OpenCloud/Compute/Resource/Server.php @@ -172,6 +172,12 @@ class Server extends NovaResource implements HasPtrRecordsInterface */ public $powerStatus; + /** + * @link http://developer.openstack.org/api-ref-compute-v2-ext.html#ext-os-ext-az + * @var string Availability zone of the VM + */ + public $availabilityZone; + protected static $json_name = 'server'; protected static $url_resource = 'servers'; @@ -206,6 +212,7 @@ class Server extends NovaResource implements HasPtrRecordsInterface 'OS-EXT-STS:vm_state' => 'extendedStatus', 'OS-EXT-STS:task_state' => 'taskStatus', 'OS-EXT-STS:power_state' => 'powerStatus', + 'OS-EXT-AZ:availability_zone' => 'availabilityZone' ); /** @@ -729,6 +736,12 @@ protected function createJson() $server->user_data = $this->user_data; } + // Availability zone + if (!empty($this->availabilityZone)) { + $this->checkExtension('OS-EXT-AZ'); + $server->availability_zone = $this->availabilityZone; + } + return (object) array('server' => $server); } diff --git a/samples/Compute/create_server_with_availability_zone.php b/samples/Compute/create_server_with_availability_zone.php new file mode 100644 index 000000000..cf4b1f4bc --- /dev/null +++ b/samples/Compute/create_server_with_availability_zone.php @@ -0,0 +1,48 @@ + '{username}', + 'password' => '{password}', +)); + +// 2. Create Compute service +$service = $client->computeService('nova', '{region}'); + +// 3. Get empty server +$server = $service->server(); + +// 4. Create the server. If you do not know what imageId or flavorId to use, +// please run the list_flavors.php and list_images.php scripts. +try { + $response = $server->create(array( + 'name' => '{serverName}', + 'imageId' => '{imageId}', + 'flavorId' => '{flavorId}', + 'availabilityZone' => '{availabilityZone}' + )); +} catch (BadResponseException $e) { + echo $e->getResponse(); +} diff --git a/tests/OpenCloud/Tests/Compute/Resource/ServerTest.php b/tests/OpenCloud/Tests/Compute/Resource/ServerTest.php index 580e77e65..13ed80a35 100644 --- a/tests/OpenCloud/Tests/Compute/Resource/ServerTest.php +++ b/tests/OpenCloud/Tests/Compute/Resource/ServerTest.php @@ -403,4 +403,13 @@ public function test_Stop() $this->addMockSubscriber(new \Guzzle\Http\Message\Response(202)); $this->assertEquals(202, $this->server->stop()->getStatusCode()); } + + public function test_Create_Availability_Zone() + { + $new = new PublicServer($this->service); + $new->setAvailabilityZone('AZ1'); + $obj = $new->CreateJson(); + + $this->assertEquals('AZ1', $obj->server->availability_zone); + } } diff --git a/tests/OpenCloud/Tests/Compute/_response/Extensions.resp b/tests/OpenCloud/Tests/Compute/_response/Extensions.resp index 68c63da10..8474a182c 100644 --- a/tests/OpenCloud/Tests/Compute/_response/Extensions.resp +++ b/tests/OpenCloud/Tests/Compute/_response/Extensions.resp @@ -15,6 +15,14 @@ Server: Jetty(8.0.y.z-SNAPSHOT) "alias": "OS-DCF", "description": "Disk Management Extension." }, + { + "updated": "2013-01-30T00:00:00Z", + "name": "ExtendedAvailabilityZone", + "links": [], + "namespace": "http://docs.openstack.org/compute/ext/extended_availability_zone/api/v2", + "alias": "OS-EXT-AZ", + "description": "Extended Availability Zone support." + }, { "updated": "2013-02-19T00:00:00Z", "name": "ImageSize", From d2d33299af505da2741e7b490b9cae487f9a6bef Mon Sep 17 00:00:00 2001 From: Shaunak Kashyap Date: Fri, 27 Mar 2015 09:49:09 +0100 Subject: [PATCH 24/34] Fixing indentation. --- lib/OpenCloud/Compute/Resource/Server.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/OpenCloud/Compute/Resource/Server.php b/lib/OpenCloud/Compute/Resource/Server.php index 490c285e6..0d47f5dec 100644 --- a/lib/OpenCloud/Compute/Resource/Server.php +++ b/lib/OpenCloud/Compute/Resource/Server.php @@ -738,8 +738,8 @@ protected function createJson() // Availability zone if (!empty($this->availabilityZone)) { - $this->checkExtension('OS-EXT-AZ'); - $server->availability_zone = $this->availabilityZone; + $this->checkExtension('OS-EXT-AZ'); + $server->availability_zone = $this->availabilityZone; } return (object) array('server' => $server); From a108d3165118a5913f24182b23c62cd5e72f52e5 Mon Sep 17 00:00:00 2001 From: AdamMerrifield Date: Wed, 1 Apr 2015 08:09:19 -0400 Subject: [PATCH 25/34] Changed 'privateURL' to 'internalURL' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Object store documentation is displaying the incorrect url type. It says 'privateURL’ but it should be ‘internalURL’. --- doc/services/object-store/migrating-containers.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/services/object-store/migrating-containers.rst b/doc/services/object-store/migrating-containers.rst index 22adb839b..da983af3e 100644 --- a/doc/services/object-store/migrating-containers.rst +++ b/doc/services/object-store/migrating-containers.rst @@ -68,12 +68,12 @@ You can access all this functionality by executing: It's advisable to do this process in a Cloud Server in one of the two -regions you're migrating to/from. This allows you to use ``privateURL`` +regions you're migrating to/from. This allows you to use ``internalURL`` as the third argument in the ``objectStoreService`` methods like this: .. code-block:: php - $client->objectStoreService('cloudFiles', 'IAD', 'privateURL'); + $client->objectStoreService('cloudFiles', 'IAD', 'internalURL'); This will ensure that traffic between your server and your new IAD From 14d0de842fc25cd69930dee3646ca69ee0986192 Mon Sep 17 00:00:00 2001 From: Jamie Hannaford Date: Thu, 2 Apr 2015 10:41:02 +0200 Subject: [PATCH 26/34] Fix dead links; fixes #579 --- doc/services/common/service-args.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/services/common/service-args.rst b/doc/services/common/service-args.rst index c1cc754b8..128986d91 100644 --- a/doc/services/common/service-args.rst +++ b/doc/services/common/service-args.rst @@ -3,9 +3,9 @@ default will be provided if you pass in ``null``. * ``{region}`` is the region the service will operate in. For Rackspace - users, you can select one of the following from the `supported regions page - `_. + users, you can select one of the following from the :doc:`supported regions page + `. -* ``{urlType}`` is the `type of URL `_ to use, depending on which +* ``{urlType}`` is the :doc:`type of URL ` to use, depending on which endpoints your catalog provides. If omitted, it will default to the public network. From 067cf97ea49b781052b614085dee42f389b1fc2e Mon Sep 17 00:00:00 2001 From: Jamie Hannaford Date: Thu, 2 Apr 2015 14:08:54 +0200 Subject: [PATCH 27/34] Bump versions for development packages --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 693e986ec..a0fa3b76a 100644 --- a/composer.json +++ b/composer.json @@ -31,10 +31,11 @@ "psr/log": "~1.0" }, "require-dev" : { + "php": ">=5.4", "phpunit/phpunit": "4.3.*", "satooshi/php-coveralls": "0.6.*@dev", "jakub-onderka/php-parallel-lint": "0.*", "fabpot/php-cs-fixer": "1.0.*@dev", - "apigen/apigen": "~2.8" + "apigen/apigen": "~4.0" } } From c099ce58bd5fc12ec2ef5c8388229f9e19d4d1cc Mon Sep 17 00:00:00 2001 From: Jamie Hannaford Date: Thu, 2 Apr 2015 15:06:34 +0200 Subject: [PATCH 28/34] Shift minimum PHP version to 5.4 --- README.md | 4 +++- composer.json | 3 +-- doc/using-php-5.4.rst | 20 ++++++++++++++++++++ 3 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 doc/using-php-5.4.rst diff --git a/README.md b/README.md index 8ddd9f1b5..5f4d75da5 100644 --- a/README.md +++ b/README.md @@ -16,9 +16,11 @@ so that you can still use the SDK with a pure OpenStack instance Requirements ------------ -* PHP >=5.3.3 +* PHP >=5.4 * cURL extension for PHP +**Note**: Since PHP 5.3 has reached [end of life](http://php.net/eol.php) and is no longer officially supported, we are moving to 5.4 as a minimum requirement. If upgrading is not an option and you still need a stable version of the SDK for 5.3, please follow [this guide](http://docs.php-opencloud.com/en/latest/using-php-5.3). + Installation ------------ You must install this library through Composer: diff --git a/composer.json b/composer.json index a0fa3b76a..d22c56524 100644 --- a/composer.json +++ b/composer.json @@ -26,12 +26,11 @@ } }, "require": { - "php" : ">=5.3.3", + "php" : ">=5.4", "guzzle/guzzle" : "~3.8", "psr/log": "~1.0" }, "require-dev" : { - "php": ">=5.4", "phpunit/phpunit": "4.3.*", "satooshi/php-coveralls": "0.6.*@dev", "jakub-onderka/php-parallel-lint": "0.*", diff --git a/doc/using-php-5.4.rst b/doc/using-php-5.4.rst new file mode 100644 index 000000000..8790710f2 --- /dev/null +++ b/doc/using-php-5.4.rst @@ -0,0 +1,20 @@ +Using the SDK with PHP v5.3 +=========================== + +Since PHP 5.3 has entered EOL and no longer receives security updates, we have bumped the minimum requirement to 5.4. Using 5.3 is still possible, however, but you will need to use an older stable version of the SDK. There are two ways to do this. + +The first way is by requiring it through the command line: + +.. code-block:: bash + + composer require rackspace/php-opencloud:1.12 + +The second way is by updating your composer.json file, and specifying the appropriate version of the SDK: + +.. code-block:: json + + "require": { + "rackspace/php-opencloud": "~1.12" + } + +Note that **1.12** is the last minor release supporting PHP 5.3. Version 1.13 and above has shifted to PHP 5.4. From cd838faa3a939e9ba63f931244bba8afc4cf119b Mon Sep 17 00:00:00 2001 From: Jamie Hannaford Date: Thu, 2 Apr 2015 15:07:03 +0200 Subject: [PATCH 29/34] Remove 5.3 from build matrix --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index bdd5f76af..78dd0003f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,6 @@ php: - "5.6" - "5.5" - "5.4" - - "5.3" - hhvm sudo: false @@ -33,4 +32,4 @@ notifications: - shaunak.kashyap@rackspace.com env: - - secure: "bdrUeYb3nSGgBB+QtDZxUHVPw6B/wjb3KXLm8TgonWrQm4GPeWKK29qhmDnFZmQjwQPfuebe7wAk1ZxGoZKbEiELVpJJ+8XYVOt6W/6V53H31JL6FqiIE5+7qBwDe+9ziveM6GcTXHT1GI5mUeACIbeBDPZaNubIJH3U6MPim64=" \ No newline at end of file + - secure: "bdrUeYb3nSGgBB+QtDZxUHVPw6B/wjb3KXLm8TgonWrQm4GPeWKK29qhmDnFZmQjwQPfuebe7wAk1ZxGoZKbEiELVpJJ+8XYVOt6W/6V53H31JL6FqiIE5+7qBwDe+9ziveM6GcTXHT1GI5mUeACIbeBDPZaNubIJH3U6MPim64=" From 6c084c6faefc28b76e7f3474c453a306cac0d784 Mon Sep 17 00:00:00 2001 From: Jamie Hannaford Date: Thu, 2 Apr 2015 15:07:58 +0200 Subject: [PATCH 30/34] Fix path --- doc/using-php-5.4.rst | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 doc/using-php-5.4.rst diff --git a/doc/using-php-5.4.rst b/doc/using-php-5.4.rst deleted file mode 100644 index 8790710f2..000000000 --- a/doc/using-php-5.4.rst +++ /dev/null @@ -1,20 +0,0 @@ -Using the SDK with PHP v5.3 -=========================== - -Since PHP 5.3 has entered EOL and no longer receives security updates, we have bumped the minimum requirement to 5.4. Using 5.3 is still possible, however, but you will need to use an older stable version of the SDK. There are two ways to do this. - -The first way is by requiring it through the command line: - -.. code-block:: bash - - composer require rackspace/php-opencloud:1.12 - -The second way is by updating your composer.json file, and specifying the appropriate version of the SDK: - -.. code-block:: json - - "require": { - "rackspace/php-opencloud": "~1.12" - } - -Note that **1.12** is the last minor release supporting PHP 5.3. Version 1.13 and above has shifted to PHP 5.4. From 78ef25d023807bda66c198d4a6ca347e58de7ac4 Mon Sep 17 00:00:00 2001 From: Jamie Hannaford Date: Thu, 2 Apr 2015 15:08:30 +0200 Subject: [PATCH 31/34] Fix path --- doc/using-php-5.3.rst | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 doc/using-php-5.3.rst diff --git a/doc/using-php-5.3.rst b/doc/using-php-5.3.rst new file mode 100644 index 000000000..8790710f2 --- /dev/null +++ b/doc/using-php-5.3.rst @@ -0,0 +1,20 @@ +Using the SDK with PHP v5.3 +=========================== + +Since PHP 5.3 has entered EOL and no longer receives security updates, we have bumped the minimum requirement to 5.4. Using 5.3 is still possible, however, but you will need to use an older stable version of the SDK. There are two ways to do this. + +The first way is by requiring it through the command line: + +.. code-block:: bash + + composer require rackspace/php-opencloud:1.12 + +The second way is by updating your composer.json file, and specifying the appropriate version of the SDK: + +.. code-block:: json + + "require": { + "rackspace/php-opencloud": "~1.12" + } + +Note that **1.12** is the last minor release supporting PHP 5.3. Version 1.13 and above has shifted to PHP 5.4. From 8545dda0f1cbda7125edea1ba9869964141f6637 Mon Sep 17 00:00:00 2001 From: Jamie Hannaford Date: Thu, 2 Apr 2015 16:55:23 +0200 Subject: [PATCH 32/34] Add note to main install guide --- doc/index.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/index.rst b/doc/index.rst index 4994f0efb..3c47091cc 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -30,6 +30,10 @@ Read the :doc:`getting-started-with-openstack` or :doc:`getting-started-with-rackspace` to help you get started with basic Compute operations. +.. note:: + + If you are running PHP 5.3, please see our :doc:`using-php-5.3` guide. + Services -------- From 9457407e387b67a43c7ade53d04a4a8ffb0f1b2d Mon Sep 17 00:00:00 2001 From: Jamie Hannaford Date: Thu, 2 Apr 2015 16:55:34 +0200 Subject: [PATCH 33/34] Bump library version --- lib/OpenCloud/Version.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/OpenCloud/Version.php b/lib/OpenCloud/Version.php index 47aafabf1..87afdd772 100644 --- a/lib/OpenCloud/Version.php +++ b/lib/OpenCloud/Version.php @@ -27,7 +27,7 @@ */ class Version { - const VERSION = '1.12.2'; + const VERSION = '1.13'; /** * @return string Indicate current SDK version. From 2b0a6961236a01155901e86d017e93b5154ca705 Mon Sep 17 00:00:00 2001 From: Jamie Hannaford Date: Thu, 2 Apr 2015 17:00:35 +0200 Subject: [PATCH 34/34] Use correct format --- lib/OpenCloud/Version.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/OpenCloud/Version.php b/lib/OpenCloud/Version.php index 87afdd772..b38917918 100644 --- a/lib/OpenCloud/Version.php +++ b/lib/OpenCloud/Version.php @@ -27,7 +27,7 @@ */ class Version { - const VERSION = '1.13'; + const VERSION = '1.13.0'; /** * @return string Indicate current SDK version.