Browse Source

ZF-8646
Added patch support to Zend_Service_Amazon_S3 to allow moving and copying of objects in a bucket

git-svn-id: http://framework.zend.com/svn/framework/standard/trunk@22454 44c647ce-9c0f-0410-b52a-842ac1e357ba

ralph 15 years ago
parent
commit
34f2cc5165
2 changed files with 97 additions and 4 deletions
  1. 57 4
      library/Zend/Service/Amazon/S3.php
  2. 40 0
      tests/Zend/Service/Amazon/S3/OnlineTest.php

+ 57 - 4
library/Zend/Service/Amazon/S3.php

@@ -503,6 +503,57 @@ class Zend_Service_Amazon_S3 extends Zend_Service_Amazon_Abstract
     }
 
     /**
+     * Copy an object
+     *
+     * @param  string $sourceObject  Source object name
+     * @param  string $destObject    Destination object name
+     * @param  array  $meta          (OPTIONAL) Metadata to apply to desination object.
+     *                               Set to null to copy metadata from source object.
+     * @return boolean
+     */
+    public function copyObject($sourceObject, $destObject, $meta = null)
+    {
+        $sourceObject = $this->_fixupObjectName($sourceObject);
+        $destObject   = $this->_fixupObjectName($destObject);
+
+        $headers = (is_array($meta)) ? $meta : array();
+        $headers['x-amz-copy-source'] = $sourceObject;
+        $headers['x-amz-metadata-directive'] = is_null($meta) ? 'COPY' : 'REPLACE';
+
+        $response = $this->_makeRequest('PUT', $destObject, null, $headers);
+
+        if ($response->getStatus() == 200 && !stristr($response->getBody(), '<Error>')) {
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Move an object
+     *
+     * Performs a copy to dest + verify + remove source
+     *
+     * @param string $sourceObject  Source object name
+     * @param string $destObject    Destination object name
+     * @param array  $meta          (OPTIONAL) Metadata to apply to destination object.
+     *                              Set to null to retain existing metadata.
+     */
+    public function moveObject($sourceObject, $destObject, $meta = null)
+    {
+        $sourceInfo = $this->getInfo($sourceObject);
+
+        $this->copyObject($sourceObject, $destObject, $meta);
+        $destInfo = $this->getInfo($destObject);
+
+        if ($sourceInfo['etag'] === $destInfo['etag']) {
+            return $this->removeObject($sourceObject);
+        } else {
+            return false;
+        }
+    }
+
+    /**
      * Make a request to Amazon S3
      *
      * @param  string $method	Request method
@@ -556,10 +607,12 @@ class Zend_Service_Amazon_S3 extends Zend_Service_Amazon_Abstract
         $client->setAuth(false);
         // Work around buglet in HTTP client - it doesn't clean headers
         // Remove when ZHC is fixed
-        $client->setHeaders(array('Content-MD5' => null,
-                                  'Expect'      => null,
-                                  'Range'       => null,
-                                  'x-amz-acl'   => null));
+        $client->setHeaders(array('Content-MD5'              => null,
+                                  'Expect'                   => null,
+                                  'Range'                    => null,
+                                  'x-amz-acl'                => null,
+                                  'x-amz-copy-source'        => null,
+                                  'x-amz-metadata-directive' => null));
 
         $client->setHeaders($headers);
 

+ 40 - 0
tests/Zend/Service/Amazon/S3/OnlineTest.php

@@ -290,6 +290,46 @@ class Zend_Service_Amazon_S3_OnlineTest extends PHPUnit_Framework_TestCase
         $this->assertFalse($this->_amazon->isObjectAvailable($this->_bucket."/zftestfile"));
     }
 
+    /**
+     * @depends testCreateBucket
+     * @depends testCreateObject
+     */
+    public function testCopyObject()
+    {
+        $this->_amazon->createBucket($this->_bucket);
+        $data = "testdata";
+
+        $this->_amazon->putObject($this->_bucket."/zftest", $data);
+        $info1 = $this->_amazon->getInfo($this->_bucket."/zftest");
+
+        $this->_amazon->copyObject($this->_bucket."/zftest", $this->_bucket."/zftest2");
+        $this->assertTrue($this->_amazon->isObjectAvailable($this->_bucket."/zftest"));
+        $this->assertTrue($this->_amazon->isObjectAvailable($this->_bucket."/zftest2"));
+        $info2 = $this->_amazon->getInfo($this->_bucket."/zftest2");
+
+        $this->assertEquals($info1['etag'], $info2['etag']);
+    }
+
+    /**
+     * @depends testCopyObject
+     * @depends testRemoveObject
+     */
+    public function testMoveObject()
+    {
+        $this->_amazon->createBucket($this->_bucket);
+        $data = "testdata";
+
+        $this->_amazon->putObject($this->_bucket."/zftest", $data);
+        $info1 = $this->_amazon->getInfo($this->_bucket."/zftest");
+
+        $this->_amazon->moveObject($this->_bucket."/zftest", $this->_bucket."/zftest2");
+        $this->assertFalse($this->_amazon->isObjectAvailable($this->_bucket."/zftest"));
+        $this->assertTrue($this->_amazon->isObjectAvailable($this->_bucket."/zftest2"));
+        $info2 = $this->_amazon->getInfo($this->_bucket."/zftest2");
+
+        $this->assertEquals($info1['etag'], $info2['etag']);
+    }
+
     public function testObjectEncoding()
     {
         $this->_amazon->createBucket($this->_bucket);