forked from LiveCarta/PayPal-PHP-SDK
Ability to handle missing accesors for unknown objects in json
- JSON body that has objects who do not have Model Getter Setters are handled properly
This commit is contained in:
@@ -80,6 +80,7 @@ class PayPalModel
|
|||||||
}
|
}
|
||||||
return $list;
|
return $list;
|
||||||
}
|
}
|
||||||
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -180,26 +181,35 @@ class PayPalModel
|
|||||||
public function fromArray($arr)
|
public function fromArray($arr)
|
||||||
{
|
{
|
||||||
if (!empty($arr)) {
|
if (!empty($arr)) {
|
||||||
|
// Iterate over each element in array
|
||||||
foreach ($arr as $k => $v) {
|
foreach ($arr as $k => $v) {
|
||||||
|
// If the value is an array, it means, it is an object after conversion
|
||||||
if (is_array($v)) {
|
if (is_array($v)) {
|
||||||
$clazz = ReflectionUtil::getPropertyClass(get_class($this), $k);
|
// Determine the class of the object
|
||||||
if (ArrayUtil::isAssocArray($v)) {
|
if (($clazz = ReflectionUtil::getPropertyClass(get_class($this), $k)) != null){
|
||||||
/** @var self $o */
|
// If the value is an associative array, it means, its an object. Just make recursive call to it.
|
||||||
$o = new $clazz();
|
if (ArrayUtil::isAssocArray($v)) {
|
||||||
$o->fromArray($v);
|
/** @var self $o */
|
||||||
$this->assignValue($k, $o);
|
$o = new $clazz();
|
||||||
} else {
|
$o->fromArray($v);
|
||||||
$arr = array();
|
$this->assignValue($k, $o);
|
||||||
foreach ($v as $nk => $nv) {
|
} else {
|
||||||
if (is_array($nv)) {
|
// Else, value is an array of object/data
|
||||||
$o = new $clazz();
|
$arr = array();
|
||||||
$o->fromArray($nv);
|
// Iterate through each element in that array.
|
||||||
$arr[$nk] = $o;
|
foreach ($v as $nk => $nv) {
|
||||||
} else {
|
if (is_array($nv)) {
|
||||||
$arr[$nk] = $nv;
|
$o = new $clazz();
|
||||||
|
$o->fromArray($nv);
|
||||||
|
$arr[$nk] = $o;
|
||||||
|
} else {
|
||||||
|
$arr[$nk] = $nv;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
$this->assignValue($k, $arr);
|
||||||
}
|
}
|
||||||
$this->assignValue($k, $arr);
|
} else {
|
||||||
|
$this->assignValue($k, $v);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$this->assignValue($k, $v);
|
$this->assignValue($k, $v);
|
||||||
@@ -211,6 +221,7 @@ class PayPalModel
|
|||||||
|
|
||||||
private function assignValue($key, $value)
|
private function assignValue($key, $value)
|
||||||
{
|
{
|
||||||
|
// If we find the getter setter, use that, otherwise use magic method.
|
||||||
if (ModelAccessorValidator::validate($this, $this->convertToCamelCase($key))) {
|
if (ModelAccessorValidator::validate($this, $this->convertToCamelCase($key))) {
|
||||||
$setter = "set" . $this->convertToCamelCase($key);
|
$setter = "set" . $this->convertToCamelCase($key);
|
||||||
$this->$setter($value);
|
$this->$setter($value);
|
||||||
|
|||||||
@@ -27,11 +27,14 @@ class ReflectionUtil
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets Property Class
|
* Gets Property Class of the given property.
|
||||||
|
* If the class is null, it returns null.
|
||||||
|
* If the property is not found, it returns null.
|
||||||
*
|
*
|
||||||
* @param $class
|
* @param $class
|
||||||
* @param $propertyName
|
* @param $propertyName
|
||||||
* @return string
|
* @return null|string
|
||||||
|
* @throws PayPalConfigurationException
|
||||||
*/
|
*/
|
||||||
public static function getPropertyClass($class, $propertyName)
|
public static function getPropertyClass($class, $propertyName)
|
||||||
{
|
{
|
||||||
@@ -40,6 +43,11 @@ class ReflectionUtil
|
|||||||
return get_class(new PayPalModel());
|
return get_class(new PayPalModel());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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'])) {
|
if (($annotations = self::propertyAnnotations($class, $propertyName)) && isset($annotations['return'])) {
|
||||||
$param = $annotations['return'];
|
$param = $annotations['return'];
|
||||||
}
|
}
|
||||||
@@ -72,9 +80,7 @@ class ReflectionUtil
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!($refl =& self::$propertiesRefl[$class][$propertyName])) {
|
if (!($refl =& self::$propertiesRefl[$class][$propertyName])) {
|
||||||
$getter = method_exists($class, "get" . ucfirst($propertyName)) ?
|
$getter = self::getter($class, $propertyName);
|
||||||
"get" . ucfirst($propertyName) :
|
|
||||||
"get" . preg_replace_callback("/([_\-\s]?([a-z0-9]+))/", "self::replace_callback", $propertyName);
|
|
||||||
$refl = new \ReflectionMethod($class, $getter);
|
$refl = new \ReflectionMethod($class, $getter);
|
||||||
self::$propertiesRefl[$class][$propertyName] = $refl;
|
self::$propertiesRefl[$class][$propertyName] = $refl;
|
||||||
}
|
}
|
||||||
@@ -104,4 +110,19 @@ class ReflectionUtil
|
|||||||
{
|
{
|
||||||
return ucwords($match[2]);
|
return ucwords($match[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the properly formatted getter function name based on class name and property
|
||||||
|
* Formats the property name to a standard getter function
|
||||||
|
*
|
||||||
|
* @param string $class
|
||||||
|
* @param string $propertyName
|
||||||
|
* @return string getter function name
|
||||||
|
*/
|
||||||
|
public static function getter($class, $propertyName)
|
||||||
|
{
|
||||||
|
return method_exists($class, "get" . ucfirst($propertyName)) ?
|
||||||
|
"get" . ucfirst($propertyName) :
|
||||||
|
"get" . preg_replace_callback("/([_\-\s]?([a-z0-9]+))/", "self::replace_callback", $propertyName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,8 @@ class ModelAccessorValidator
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,6 +98,28 @@ class ModelTest extends \PHPUnit_Framework_TestCase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test Case to determine if the unknown object is returned, it would not add that object to the model.
|
||||||
|
*/
|
||||||
|
public function testUnknownObjectConversion()
|
||||||
|
{
|
||||||
|
PayPalConfigManager::getInstance()->addConfigs(array('validation.level' => 'disabled'));
|
||||||
|
$json = '{"name":"test","unknown":{ "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 testInvalidMagicMethodWithDisabledValidation()
|
public function testInvalidMagicMethodWithDisabledValidation()
|
||||||
{
|
{
|
||||||
PayPalConfigManager::getInstance()->addConfigs(array('validation.level' => 'disabled'));
|
PayPalConfigManager::getInstance()->addConfigs(array('validation.level' => 'disabled'));
|
||||||
|
|||||||
@@ -146,5 +146,3 @@ class PayPalCredentialManagerTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertAttributeEquals($this->config['acct1.ClientSecret'], 'clientSecret', $cred);
|
$this->assertAttributeEquals($this->config['acct1.ClientSecret'], 'clientSecret', $cred);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace PayPal\Test\Validation;
|
namespace PayPal\Test\Validation;
|
||||||
|
|
||||||
|
use PayPal\Core\PayPalConfigManager;
|
||||||
use PayPal\Test\Common\SimpleClass;
|
use PayPal\Test\Common\SimpleClass;
|
||||||
use PayPal\Validation\ModelAccessorValidator;
|
use PayPal\Validation\ModelAccessorValidator;
|
||||||
|
|
||||||
@@ -27,6 +28,16 @@ class ModelAccessValidatorTest extends \PHPUnit_Framework_TestCase
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
PayPalConfigManager::getInstance()->addConfigs(array('validation.level' => 'strict'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function tearDown()
|
||||||
|
{
|
||||||
|
PayPalConfigManager::getInstance()->addConfigs(array('validation.level' => 'strict'));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @dataProvider positiveProvider
|
* @dataProvider positiveProvider
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ log.FileName=PayPal.log
|
|||||||
; Logging level can be one of FINE, INFO, WARN or ERROR
|
; Logging level can be one of FINE, INFO, WARN or ERROR
|
||||||
; Logging is most verbose in the 'FINE' level and
|
; Logging is most verbose in the 'FINE' level and
|
||||||
; decreases as you proceed towards ERROR
|
; decreases as you proceed towards ERROR
|
||||||
log.LogLevel=FINE
|
log.LogLevel=DEBUG
|
||||||
|
|
||||||
;Validation Configuration
|
;Validation Configuration
|
||||||
[validation]
|
[validation]
|
||||||
|
|||||||
Reference in New Issue
Block a user