diff --git a/lib/PayPal/Common/PayPalModel.php b/lib/PayPal/Common/PayPalModel.php index 260ecb2..d90287a 100644 --- a/lib/PayPal/Common/PayPalModel.php +++ b/lib/PayPal/Common/PayPalModel.php @@ -106,7 +106,7 @@ class PayPalModel public function __set($key, $value) { ModelAccessorValidator::validate($this, $this->convertToCamelCase($key)); - if ($value == null) { + if (!is_array($value) && $value == null) { $this->__unset($key); } else { $this->_propMap[$key] = $value; @@ -157,6 +157,8 @@ class PayPalModel foreach ($param as $k => $v) { if ($v instanceof PayPalModel) { $ret[$k] = $v->toArray(); + } else if (sizeof($v) <= 0 && is_array($v)) { + $ret[$k] = array(); } else if (is_array($v)) { $ret[$k] = $this->_convertToArray($v); } else { @@ -188,7 +190,16 @@ class PayPalModel // Determine the class of the object if (($clazz = ReflectionUtil::getPropertyClass(get_class($this), $k)) != null){ // If the value is an associative array, it means, its an object. Just make recursive call to it. - if (ArrayUtil::isAssocArray($v)) { + if (empty($v)){ + if (ReflectionUtil::isPropertyClassArray(get_class($this), $k)) { + // It means, it is an array of objects. + $this->assignValue($k, array()); + continue; + } + $o = new $clazz(); + //$arr = array(); + $this->assignValue($k, $o); + } elseif (ArrayUtil::isAssocArray($v)) { /** @var self $o */ $o = new $clazz(); $o->fromArray($v); diff --git a/lib/PayPal/Common/ReflectionUtil.php b/lib/PayPal/Common/ReflectionUtil.php index 1af5618..0b92a5c 100644 --- a/lib/PayPal/Common/ReflectionUtil.php +++ b/lib/PayPal/Common/ReflectionUtil.php @@ -60,6 +60,32 @@ class ReflectionUtil } } + /** + * Checks if the Property is of type array or an object + * + * @param $class + * @param $propertyName + * @return null|boolean + * @throws PayPalConfigurationException + */ + public static function isPropertyClassArray($class, $propertyName) + { + // If the class doesn't exist, or the method doesn't exist, return null. + if (!class_exists($class) || !method_exists($class, self::getter($class, $propertyName))) { + return null; + } + + if (($annotations = self::propertyAnnotations($class, $propertyName)) && isset($annotations['return'])) { + $param = $annotations['return']; + } + + if (isset($param)) { + return substr($param, -strlen('[]'))==='[]'; + } else { + throw new PayPalConfigurationException("Getter function for '$propertyName' in '$class' class should have a proper return type."); + } + } + /** * Retrieves Annotations of each property * diff --git a/tests/PayPal/Test/Api/PaymentExecutionTest.php b/tests/PayPal/Test/Api/PaymentExecutionTest.php index ec5aa61..d378198 100644 --- a/tests/PayPal/Test/Api/PaymentExecutionTest.php +++ b/tests/PayPal/Test/Api/PaymentExecutionTest.php @@ -18,7 +18,7 @@ class PaymentExecutionTest extends \PHPUnit_Framework_TestCase */ public static function getJson() { - return '{"payer_id":"TestSample","transactions":' .TransactionTest::getJson() . '}'; + return '{"payer_id":"TestSample","transactions":[' .TransactionTest::getJson() . ']}'; } /** @@ -52,6 +52,6 @@ class PaymentExecutionTest extends \PHPUnit_Framework_TestCase public function testGetters($obj) { $this->assertEquals($obj->getPayerId(), "TestSample"); - $this->assertEquals($obj->getTransactions(), TransactionTest::getObject()); + $this->assertEquals($obj->getTransactions(), array(TransactionTest::getObject())); } } diff --git a/tests/PayPal/Test/Api/PaymentTest.php b/tests/PayPal/Test/Api/PaymentTest.php index b5d9642..2d19474 100644 --- a/tests/PayPal/Test/Api/PaymentTest.php +++ b/tests/PayPal/Test/Api/PaymentTest.php @@ -23,7 +23,7 @@ class PaymentTest extends \PHPUnit_Framework_TestCase */ public static function getJson() { - return '{"id":"TestSample","intent":"TestSample","payer":' .PayerTest::getJson() . ',"payee":' .PayeeTest::getJson() . ',"cart":"TestSample","transactions":' .TransactionTest::getJson() . ',"failed_transactions":' .ErrorTest::getJson() . ',"payment_instruction":' .PaymentInstructionTest::getJson() . ',"state":"TestSample","experience_profile_id":"TestSample","redirect_urls":' .RedirectUrlsTest::getJson() . ',"create_time":"TestSample","update_time":"TestSample","links":' .LinksTest::getJson() . '}'; + return '{"id":"TestSample","intent":"TestSample","payer":' .PayerTest::getJson() . ',"payee":' .PayeeTest::getJson() . ',"cart":"TestSample","transactions":[' .TransactionTest::getJson() . '],"failed_transactions":' .ErrorTest::getJson() . ',"payment_instruction":' .PaymentInstructionTest::getJson() . ',"state":"TestSample","experience_profile_id":"TestSample","redirect_urls":' .RedirectUrlsTest::getJson() . ',"create_time":"TestSample","update_time":"TestSample","links":' .LinksTest::getJson() . '}'; } /** @@ -73,7 +73,7 @@ class PaymentTest extends \PHPUnit_Framework_TestCase $this->assertEquals($obj->getPayer(), PayerTest::getObject()); $this->assertEquals($obj->getPayee(), PayeeTest::getObject()); $this->assertEquals($obj->getCart(), "TestSample"); - $this->assertEquals($obj->getTransactions(), TransactionTest::getObject()); + $this->assertEquals($obj->getTransactions(), array(TransactionTest::getObject())); $this->assertEquals($obj->getFailedTransactions(), ErrorTest::getObject()); $this->assertEquals($obj->getPaymentInstruction(), PaymentInstructionTest::getObject()); $this->assertEquals($obj->getState(), "TestSample"); diff --git a/tests/PayPal/Test/Common/ModelTest.php b/tests/PayPal/Test/Common/ModelTest.php index c5a5a98..ac90dde 100644 --- a/tests/PayPal/Test/Common/ModelTest.php +++ b/tests/PayPal/Test/Common/ModelTest.php @@ -1,6 +1,8 @@ addConfigs(array('validation.level' => 'strict')); } + /** + * Test Case to determine if the unknown object is returned, it would not add that object to the model. + */ + public function testUnknownArrayConversion() + { + PayPalConfigManager::getInstance()->addConfigs(array('validation.level' => 'disabled')); + $json = '{"name":"test","unknown":[{"object": { "id" : "123", "object": "456"}}, {"more": { "id" : "123", "object": "456"}}],"description":"description"}'; + + $obj = new SimpleClass(); + $obj->fromJson($json); + + $this->assertEquals("test", $obj->getName()); + $this->assertEquals("description", $obj->getDescription()); + $resultJson = $obj->toJSON(); + $this->assertContains("unknown", $resultJson); + $this->assertContains("id", $resultJson); + $this->assertContains("object", $resultJson); + $this->assertContains("123", $resultJson); + $this->assertContains("456", $resultJson); + PayPalConfigManager::getInstance()->addConfigs(array('validation.level' => 'strict')); + } + + public function testEmptyArrayConversion() + { + $json = '{"id":"PAY-5DW86196ER176274EKT3AEYA","transactions":[{"related_resources":[]}]}'; + $payment = new Payment($json); + $result = $payment->toJSON(); + $this->assertContains('"related_resources":[]', $result); + $this->assertNotNull($result); + } + + public function testMultipleEmptyArrayConversion() + { + $json = '{"id":"PAY-5DW86196ER176274EKT3AEYA","transactions":[{"related_resources":[{},{}]}]}'; + $payment = new Payment($json); + $result = $payment->toJSON(); + $this->assertContains('"related_resources":[{},{}]', $result); + $this->assertNotNull($result); + } + + public function testSetterMagicMethod() + { + $obj = new PayPalModel(); + $obj->something = "other"; + $obj->else = array(); + $obj->there = null; + $obj->obj = '{}'; + $obj->objs = array('{}'); + $this->assertEquals("other", $obj->something); + $this->assertTrue(is_array($obj->else)); + $this->assertNull($obj->there); + $this->assertEquals('{}', $obj->obj); + $this->assertTrue(is_array($obj->objs)); + $this->assertEquals('{}', $obj->objs[0]); + } + public function testInvalidMagicMethodWithDisabledValidation() { PayPalConfigManager::getInstance()->addConfigs(array('validation.level' => 'disabled'));