Forráskód Böngészése

ZF-6205 Serializer doesn't support cyclic reference. Test cases and patch to handle cyclic references in the As3 serializer.

git-svn-id: http://framework.zend.com/svn/framework/standard/trunk@16092 44c647ce-9c0f-0410-b52a-842ac1e357ba
wadearnold 16 éve
szülő
commit
065ff1a7b0

+ 40 - 0
library/Zend/Amf/Parse/Amf3/Serializer.php

@@ -36,6 +36,12 @@ require_once 'Zend/Amf/Parse/TypeLoader.php';
 class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer
 {
     /**
+     * reference key to objects that have already been encountered. 
+     * @var array
+     */
+	private $_references = array();
+	
+    /**
      * Serialize PHP types to AMF3 and write to stream
      *
      * Checks to see if the type was declared and then either
@@ -223,6 +229,8 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer
      */
     public function writeArray(array $array)
     {
+    	$this->_references[] = $array;
+    	
         // have to seperate mixed from numberic keys.
         $numeric = array();
         $string  = array();
@@ -254,6 +262,33 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer
     }
 
     /**
+     * Create a reference to an existing object. 
+     * @param $key
+     * @return Zend_Amf_Parse_Amf3_Serializer
+     */
+	public function writeReference($key)
+	{
+		$this->writeInteger($key << 1);
+		return $this;
+	}
+
+	/**
+	 * Check to see if the reference already exists in the lookup table. 
+	 * @param $object
+	 * @return object reference | false if it is not found. 
+	 */
+	private function referenceExist($object)
+	{
+		$key = array_search($object, $this->_references, true);
+		if($key !== false) {
+			return $key;
+		} else { 
+			$this->_references[] = $object;
+			return false;
+		}
+	}
+
+    /**
      * Write object to ouput stream
      *
      * @param  mixed $data
@@ -261,6 +296,11 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer
      */
     public function writeObject($object)
     {
+    	if(($key = $this->referenceExist($object)) !== false) {
+    		 $this->writeReference($key); 
+    		 return $this;
+    	}
+    	
         $encoding  = Zend_Amf_Constants::ET_PROPLIST;
         $className = '';
 

BIN
tests/Zend/Amf/Response/mock/referenceObjectAmf3Response.bin


+ 54 - 0
tests/Zend/Amf/ResponseTest.php

@@ -566,6 +566,41 @@ class Zend_Amf_ResponseTest extends PHPUnit_Framework_TestCase
         $this->assertEquals($mockResponse, $testResponse);
     }
     
+    /**
+     * Check to make sure that cyclic references work inside of the AMF3 serializer
+     * @group ZF-6205
+     */
+    public function testReferenceObjectsToAmf3()
+    {
+        $data = new ReferenceTest();
+        $data = $data->getReference();
+        
+        // Create an acknowlege message for a response to a RemotingMessage
+        $acknowledgeMessage = new Zend_Amf_Value_Messaging_AcknowledgeMessage(null);
+        $acknowledgeMessage->correlationId = '839B091C-8DDF-F6DD-2FF1-EAA82AE39608';
+        $acknowledgeMessage->clientId = '21CC629C-58AF-2D68-A292-000006F8D883';
+        $acknowledgeMessage->messageId = '05E70A68-FF7F-D289-1A94-00004CCECA98';
+        $acknowledgeMessage->destination = null;
+        $acknowledgeMessage->timeToLive = 0;
+        $acknowledgeMessage->timestamp = '124518243200';
+        $acknowledgeMessage->body = $data;
+        
+        $newBody = new Zend_Amf_Value_MessageBody($this->responseURI,null,$acknowledgeMessage);
+
+        // serialize the data to an AMF output stream
+        $this->_response->setObjectEncoding(0x03);
+        $this->_response->addAmfBody($newBody);
+        $this->_response->finalize();
+        $testResponse = $this->_response->getResponse();
+
+        // Load the expected response.
+        $mockResponse = file_get_contents(dirname(__FILE__) .'/Response/mock/referenceObjectAmf3Response.bin');
+        
+        // Check that the response matches the expected serialized value
+        $this->assertEquals($mockResponse, $testResponse);
+        
+    }
+    
     
 
     /**
@@ -984,6 +1019,25 @@ class Zend_Amf_ResponseTest extends PHPUnit_Framework_TestCase
     }
 }
 
+/*
+ * Used to test recursive cyclic references in the serializer. 
+ *@group ZF-6205
+ */
+class ReferenceTest {
+    public function getReference() { 
+        $o = new TestObject(); 
+        $o->recursive = new TestObject(); 
+        $o->recursive->recursive = $o; 
+        return $o; 
+    }
+}
+/**
+ * @see ReferenceTest
+ */
+class TestObject {
+    public $recursive;
+}
+
 if (PHPUnit_MAIN_METHOD == 'Zend_Amf_ResponseTest::main') {
     Zend_Amf_ResponseTest::main();
 }