Skip to content
This repository has been archived by the owner on Jan 30, 2020. It is now read-only.

Commit

Permalink
Merge branch 'master' of ssh://git.zendframework.com:21652/zf
Browse files Browse the repository at this point in the history
  • Loading branch information
Ralph Schindler committed Aug 30, 2011
Show file tree
Hide file tree
Showing 4 changed files with 358 additions and 120 deletions.
24 changes: 14 additions & 10 deletions src/Encoder.php
Expand Up @@ -146,18 +146,22 @@ protected function _encodeObject(&$value)

$props = '';

if ($value instanceof \Iterator) {
$propCollection = $value;
if (method_exists($value, 'toJson')) {
$props =',' . preg_replace("/^\{(.*)\}$/","\\1",$value->toJson());
} else {
$propCollection = get_object_vars($value);
}
if ($value instanceof \Iterator) {
$propCollection = $value;
} else {
$propCollection = get_object_vars($value);
}

foreach ($propCollection as $name => $propValue) {
if (isset($propValue)) {
$props .= ','
. $this->_encodeValue($name)
. ':'
. $this->_encodeValue($propValue);
foreach ($propCollection as $name => $propValue) {
if (isset($propValue)) {
$props .= ','
. $this->_encodeValue($name)
. ':'
. $this->_encodeValue($propValue);
}
}
}

Expand Down
229 changes: 119 additions & 110 deletions src/Json.php
Expand Up @@ -120,8 +120,12 @@ public static function decode($encodedValue, $objectDecodeType = self::TYPE_OBJE
*/
public static function encode($valueToEncode, $cycleCheck = false, $options = array())
{
if (is_object($valueToEncode) && method_exists($valueToEncode, 'toJson')) {
return $valueToEncode->toJson();
if (is_object($valueToEncode)) {
if (method_exists($valueToEncode, 'toJson')) {
return $valueToEncode->toJson();
} elseif (method_exists($valueToEncode, 'toArray')) {
return self::encode($valueToEncode->toArray(), $cycleCheck, $options);
}
}

// Pre-encoding look for Zend_Json_Expr objects and replacing by tmp ids
Expand Down Expand Up @@ -196,6 +200,107 @@ protected static function _recursiveJsonExprFinder(
}
return $value;
}
/**
* Return the value of an XML attribute text or the text between
* the XML tags
*
* In order to allow Zend_Json_Expr from xml, we check if the node
* matchs the pattern that try to detect if it is a new Zend_Json_Expr
* if it matches, we return a new Zend_Json_Expr instead of a text node
*
* @param SimpleXMLElement $simpleXmlElementObject
* @return Zend_Json_Expr|string
*/
protected static function _getXmlValue($simpleXmlElementObject)
{
$pattern = '/^[\s]*new Zend[_\\]Json[_\\]Expr[\s]*\([\s]*[\"\']{1}(.*)[\"\']{1}[\s]*\)[\s]*$/';
$matchings = array();
$match = preg_match($pattern, $simpleXmlElementObject, $matchings);
if ($match) {
return new Expr($matchings[1]);
} else {
return (trim(strval($simpleXmlElementObject)));
}
}
/**
* _processXml - Contains the logic for xml2json
*
* The logic in this function is a recursive one.
*
* The main caller of this function (i.e. fromXml) needs to provide
* only the first two parameters i.e. the SimpleXMLElement object and
* the flag for ignoring or not ignoring XML attributes. The third parameter
* will be used internally within this function during the recursive calls.
*
* This function converts the SimpleXMLElement object into a PHP array by
* calling a recursive (protected static) function in this class. Once all
* the XML elements are stored in the PHP array, it is returned to the caller.
*
* Throws a Zend\Json\RecursionException if the XML tree is deeper than the allowed limit.
*
* @param SimpleXMLElement $simpleXmlElementObject
* @param boolean $ignoreXmlAttributes
* @param integer $recursionDepth
* @return array
*/
protected static function _processXml($simpleXmlElementObject, $ignoreXmlAttributes, $recursionDepth = 0)
{
// Keep an eye on how deeply we are involved in recursion.
if ($recursionDepth > self::$maxRecursionDepthAllowed) {
// XML tree is too deep. Exit now by throwing an exception.
throw new RecursionException(
"Function _processXml exceeded the allowed recursion depth of "
. self::$maxRecursionDepthAllowed
);
}

$children = $simpleXmlElementObject->children();
$name = $simpleXmlElementObject->getName();
$value = self::_getXmlValue($simpleXmlElementObject);
$attributes = (array) $simpleXmlElementObject->attributes();

if (!count($children)) {
if (!empty($attributes) && !$ignoreXmlAttributes) {
foreach ($attributes['@attributes'] as $k => $v) {
$attributes['@attributes'][$k] = self::_getXmlValue($v);
}
if (!empty($value)) {
$attributes['@text'] = $value;
}
return array($name => $attributes);
}

return array($name => $value);
}

$childArray = array();
foreach ($children as $child) {
$childname = $child->getName();
$element = self::_processXml($child,$ignoreXmlAttributes,$recursionDepth + 1);
if (array_key_exists($childname, $childArray)) {
if (empty($subChild[$childname])) {
$childArray[$childname] = array($childArray[$childname]);
$subChild[$childname] = true;
}
$childArray[$childname][] = $element[$childname];
} else {
$childArray[$childname] = $element[$childname];
}
}

if (!empty($attributes) && !$ignoreXmlAttributes) {
foreach ($attributes['@attributes'] as $k => $v) {
$attributes['@attributes'][$k] = self::_getXmlValue($v);
}
$childArray['@attributes'] = $attributes['@attributes'];
}

if (!empty($value)) {
$childArray['@text'] = $value;
}

return array($name => $childArray);
}

/**
* fromXml - Converts XML to JSON
Expand Down Expand Up @@ -242,110 +347,6 @@ public static function fromXml ($xmlStringContents, $ignoreXmlAttributes=true) {
return($jsonStringOutput);
}

/**
* _processXml - Contains the logic for xml2json
*
* The logic in this function is a recursive one.
*
* The main caller of this function (i.e. fromXml) needs to provide
* only the first two parameters i.e. the SimpleXMLElement object and
* the flag for ignoring or not ignoring XML attributes. The third parameter
* will be used internally within this function during the recursive calls.
*
* This function converts the SimpleXMLElement object into a PHP array by
* calling a recursive (protected static) function in this class. Once all
* the XML elements are stored in the PHP array, it is returned to the caller.
*
* @static
* @access protected
* @param SimpleXMLElement $simpleXmlElementObject XML element to be converted
* @param boolean $ignoreXmlAttributes Include or exclude XML attributes in
* the xml2json conversion process.
* @param int $recursionDepth Current recursion depth of this function
* @return mixed - On success, a PHP associative array of traversed XML elements
* @throws Zend\Json\Exception\RecursionException if the XML tree is deeper than the allowed limit
*/
protected static function _processXml ($simpleXmlElementObject, $ignoreXmlAttributes, $recursionDepth=0) {
// Keep an eye on how deeply we are involved in recursion.
if ($recursionDepth > self::$maxRecursionDepthAllowed) {
// XML tree is too deep. Exit now by throwing an exception.
throw new RecursionException(
"Function _processXml exceeded the allowed recursion depth of " .
self::$maxRecursionDepthAllowed);
} // End of if ($recursionDepth > self::$maxRecursionDepthAllowed)

if ($recursionDepth == 0) {
// Store the original SimpleXmlElementObject sent by the caller.
// We will need it at the very end when we return from here for good.
$callerProvidedSimpleXmlElementObject = $simpleXmlElementObject;
} // End of if ($recursionDepth == 0)

if ($simpleXmlElementObject instanceof \SimpleXMLElement) {
// Get a copy of the simpleXmlElementObject
$copyOfSimpleXmlElementObject = $simpleXmlElementObject;
// Get the object variables in the SimpleXmlElement object for us to iterate.
$simpleXmlElementObject = get_object_vars($simpleXmlElementObject);
} // End of if (get_class($simpleXmlElementObject) == "SimpleXMLElement")

// It needs to be an array of object variables.
if (is_array($simpleXmlElementObject)) {
// Initialize a result array.
$resultArray = array();
// Is the input array size 0? Then, we reached the rare CDATA text if any.
if (count($simpleXmlElementObject) <= 0) {
// Let us return the lonely CDATA. It could even be
// an empty element or just filled with whitespaces.
return (trim(strval($copyOfSimpleXmlElementObject)));
} // End of if (count($simpleXmlElementObject) <= 0)

// Let us walk through the child elements now.
foreach($simpleXmlElementObject as $key=>$value) {
// Check if we need to ignore the XML attributes.
// If yes, you can skip processing the XML attributes.
// Otherwise, add the XML attributes to the result array.
if(($ignoreXmlAttributes == true) && (is_string($key)) && ($key == "@attributes")) {
continue;
} // End of if(($ignoreXmlAttributes == true) && ($key == "@attributes"))

// Let us recursively process the current XML element we just visited.
// Increase the recursion depth by one.
$recursionDepth++;
$resultArray[$key] = self::_processXml ($value, $ignoreXmlAttributes, $recursionDepth);

// Decrease the recursion depth by one.
$recursionDepth--;
} // End of foreach($simpleXmlElementObject as $key=>$value) {

if ($recursionDepth == 0) {
// That is it. We are heading to the exit now.
// Set the XML root element name as the root [top-level] key of
// the associative array that we are going to return to the original
// caller of this recursive function.
$tempArray = $resultArray;
$resultArray = array();
$resultArray[$callerProvidedSimpleXmlElementObject->getName()] = $tempArray;
} // End of if ($recursionDepth == 0)

return($resultArray);
} else {
// We are now looking at either the XML attribute text or
// the text between the XML tags.

// In order to allow Zend_Json_Expr from xml, we check if the node
// matchs the pattern that try to detect if it is a new Zend_Json_Expr
// if it matches, we return a new Zend_Json_Expr instead of a text node
$pattern = '/^[\s]*new Zend_Json_Expr[\s]*\([\s]*[\"\']{1}(.*)[\"\']{1}[\s]*\)[\s]*$/';
$matchings = array();
$match = preg_match($pattern, $simpleXmlElementObject, $matchings);
if ($match) {
return new Expr($matchings[1]);
} else {
return (trim(strval($simpleXmlElementObject)));
}

} // End of if (is_array($simpleXmlElementObject))
} // End of function _processXml.

/**
* Pretty-print JSON string
*
Expand All @@ -366,24 +367,32 @@ public static function prettyPrint($json, $options = array())
$ind = $options['indent'];
}

$inLiteral = false;
foreach($tokens as $token) {
if($token == "") continue;

$prefix = str_repeat($ind, $indent);
if($token == "{" || $token == "[") {
if(!$inLiteral && ($token == "{" || $token == "[")) {
$indent++;
if($result != "" && $result[strlen($result)-1] == "\n") {
$result .= $prefix;
}
$result .= "$token\n";
} else if($token == "}" || $token == "]") {
} else if(!$inLiteral && ($token == "}" || $token == "]")) {
$indent--;
$prefix = str_repeat($ind, $indent);
$result .= "\n$prefix$token";
} else if($token == ",") {
} else if(!$inLiteral && $token == ",") {
$result .= "$token\n";
} else {
$result .= $prefix.$token;
$result .= ($inLiteral ? '' : $prefix) . $token;

// Count # of unescaped double-quotes in token, subtract # of
// escaped double-quotes and if the result is odd then we are
// inside a string literal
if ((substr_count($token, "\"")-substr_count($token, "\\\"")) % 2 != 0) {
$inLiteral = !$inLiteral;
}
}
}
return $result;
Expand Down

0 comments on commit 1482b41

Please sign in to comment.