web/lib/Zend/Json.php
changeset 807 877f952ae2bd
parent 207 621fa6caec0c
child 1230 68c69c656a2c
--- a/web/lib/Zend/Json.php	Thu Mar 21 17:31:31 2013 +0100
+++ b/web/lib/Zend/Json.php	Thu Mar 21 19:50:53 2013 +0100
@@ -14,9 +14,9 @@
  *
  * @category   Zend
  * @package    Zend_Json
- * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  * @license    http://framework.zend.com/license/new-bsd     New BSD License
- * @version    $Id: Json.php 20615 2010-01-25 19:54:12Z matthew $
+ * @version    $Id: Json.php 24593 2012-01-05 20:35:02Z matthew $
  */
 
 /**
@@ -33,7 +33,7 @@
  * @category   Zend
  * @package    Zend_Json
  * @uses       Zend_Json_Expr
- * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  * @license    http://framework.zend.com/license/new-bsd     New BSD License
  */
 class Zend_Json
@@ -125,8 +125,12 @@
      */
     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
@@ -179,12 +183,15 @@
      * NOTE: This method is used internally by the encode method.
      *
      * @see encode
-     * @param mixed $valueToCheck a string - object property to be encoded
+     * @param array|object|Zend_Json_Expr $value a string - object property to be encoded
+     * @param array $javascriptExpressions
+     * @param null $currentKey
+     *
+     * @internal param mixed $valueToCheck
      * @return void
      */
-    protected static function _recursiveJsonExprFinder(
-        &$value, array &$javascriptExpressions, $currentKey = null
-    ) {
+    protected static function _recursiveJsonExprFinder(&$value, array &$javascriptExpressions, $currentKey = null)
+    {
          if ($value instanceof Zend_Json_Expr) {
             // TODO: Optimize with ascii keys, if performance is bad
             $magicKey = "____" . $currentKey . "_" . (count($javascriptExpressions));
@@ -208,6 +215,104 @@
     }
 
     /**
+     * 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 Zend_Json_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_Exception 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.
+            require_once 'Zend/Json/Exception.php';
+            throw new Zend_Json_Exception(
+                "Function _processXml exceeded the allowed recursion depth of " .
+                self::$maxRecursionDepthAllowed);
+        } // End of if ($recursionDepth > self::$maxRecursionDepthAllowed)
+
+        $children = $simpleXmlElementObject->children();
+        $name = $simpleXmlElementObject->getName();
+        $value = self::_getXmlValue($simpleXmlElementObject);
+        $attributes = (array) $simpleXmlElementObject->attributes();
+
+        if (count($children) == 0) {
+            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);
+            } else {
+               return array($name => $value);
+            }
+        } else {
+            $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
      *
      * Converts a XML formatted string into a JSON formatted string.
@@ -233,7 +338,8 @@
      * @return mixed - JSON formatted string on success
      * @throws Zend_Json_Exception
      */
-    public static function fromXml ($xmlStringContents, $ignoreXmlAttributes=true) {
+    public static function fromXml($xmlStringContents, $ignoreXmlAttributes=true)
+    {
         // Load the XML formatted string into a Simple XML Element object.
         $simpleXmlElementObject = simplexml_load_string($xmlStringContents);
 
@@ -252,120 +358,16 @@
         // It is just that simple.
         $jsonStringOutput = self::encode($resultArray);
         return($jsonStringOutput);
-    } // End of function fromXml.
+    }
+
+    
 
     /**
-     * _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_Exception if the XML tree is deeper than the allowed limit.
+     * Pretty-print JSON string
      *
-     * @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
-     */
-    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.
-            require_once 'Zend/Json/Exception.php';
-            throw new Zend_Json_Exception(
-                "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 Zend_Json_Expr($matchings[1]);
-            } else {
-                return (trim(strval($simpleXmlElementObject)));
-            }
-
-        } // End of if (is_array($simpleXmlElementObject))
-    } // End of function _processXml.
-    
-    /**
-     * Pretty-print JSON string
-     * 
-     * Use 'indent' option to select indentation string - by default it's a tab
-     * 
+     * Use 'format' option to select output format - currently html and txt supported, txt is default
+     * Use 'indent' option to override the indentation string set in the format - by default for the 'txt' format it's a tab
+     *
      * @param string $json Original JSON string
      * @param array $options Encoding options
      * @return string
@@ -373,32 +375,62 @@
     public static function prettyPrint($json, $options = array())
     {
         $tokens = preg_split('|([\{\}\]\[,])|', $json, -1, PREG_SPLIT_DELIM_CAPTURE);
-        $result = "";
+        $result = '';
         $indent = 0;
-        
+
+        $format= 'txt';
+
         $ind = "\t";
-        if(isset($options['indent'])) {
+
+        if (isset($options['format'])) {
+            $format = $options['format'];
+        }
+
+        switch ($format) {
+            case 'html':
+                $lineBreak = '<br />';
+                $ind = '&nbsp;&nbsp;&nbsp;&nbsp;';
+                break;
+            default:
+            case 'txt':
+                $lineBreak = "\n";
+                $ind = "\t";
+                break;
+        }
+
+        // override the defined indent setting with the supplied option
+        if (isset($options['indent'])) {
             $ind = $options['indent'];
         }
-        
+
+        $inLiteral = false;
         foreach($tokens as $token) {
-            if($token == "") continue;
-            
+            if($token == '') {
+                continue;
+            }
+
             $prefix = str_repeat($ind, $indent);
-            if($token == "{" || $token == "[") {
+            if (!$inLiteral && ($token == '{' || $token == '[')) {
                 $indent++;
-                if($result != "" && $result[strlen($result)-1] == "\n") {
+                if (($result != '') && ($result[(strlen($result)-1)] == $lineBreak)) {
                     $result .= $prefix;
                 }
-                $result .= "$token\n";
-            } else if($token == "}" || $token == "]") {
+                $result .= $token . $lineBreak;
+            } elseif (!$inLiteral && ($token == '}' || $token == ']')) {
                 $indent--;
                 $prefix = str_repeat($ind, $indent);
-                $result .= "\n$prefix$token";                
-            } else if($token == ",") {
-                $result .= "$token\n";
+                $result .= $lineBreak . $prefix . $token;
+            } elseif (!$inLiteral && $token == ',') {
+                $result .= $token . $lineBreak;
             } 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;