Added the zend framework 2 library, the path is specified in line no.26 in zend_modul...
[openemr.git] / interface / modules / zend_modules / library / Zend / Json / Json.php
blob02a792bfce7b5cdb6672d0370e26a33c7f8f41a5
1 <?php
2 /**
3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
8 */
10 namespace Zend\Json;
12 use SimpleXMLElement;
13 use Zend\Json\Exception\RecursionException;
14 use Zend\Json\Exception\RuntimeException;
16 /**
17 * Class for encoding to and decoding from JSON.
19 class Json
21 /**
22 * How objects should be encoded -- arrays or as stdClass. TYPE_ARRAY is 1
23 * so that it is a boolean true value, allowing it to be used with
24 * ext/json's functions.
26 const TYPE_ARRAY = 1;
27 const TYPE_OBJECT = 0;
29 /**
30 * To check the allowed nesting depth of the XML tree during xml2json conversion.
32 * @var int
34 public static $maxRecursionDepthAllowed = 25;
36 /**
37 * @var bool
39 public static $useBuiltinEncoderDecoder = false;
41 /**
42 * Decodes the given $encodedValue string which is
43 * encoded in the JSON format
45 * Uses ext/json's json_decode if available.
47 * @param string $encodedValue Encoded in JSON format
48 * @param int $objectDecodeType Optional; flag indicating how to decode
49 * objects. See {@link Zend\Json\Decoder::decode()} for details.
50 * @return mixed
51 * @throws RuntimeException
53 public static function decode($encodedValue, $objectDecodeType = self::TYPE_OBJECT)
55 $encodedValue = (string) $encodedValue;
56 if (function_exists('json_decode') && static::$useBuiltinEncoderDecoder !== true) {
57 $decode = json_decode($encodedValue, $objectDecodeType);
59 switch (json_last_error()) {
60 case JSON_ERROR_NONE:
61 break;
62 case JSON_ERROR_DEPTH:
63 throw new RuntimeException('Decoding failed: Maximum stack depth exceeded');
64 case JSON_ERROR_CTRL_CHAR:
65 throw new RuntimeException('Decoding failed: Unexpected control character found');
66 case JSON_ERROR_SYNTAX:
67 throw new RuntimeException('Decoding failed: Syntax error');
68 default:
69 throw new RuntimeException('Decoding failed');
72 return $decode;
75 return Decoder::decode($encodedValue, $objectDecodeType);
78 /**
79 * Encode the mixed $valueToEncode into the JSON format
81 * Encodes using ext/json's json_encode() if available.
83 * NOTE: Object should not contain cycles; the JSON format
84 * does not allow object reference.
86 * NOTE: Only public variables will be encoded
88 * NOTE: Encoding native javascript expressions are possible using Zend\Json\Expr.
89 * You can enable this by setting $options['enableJsonExprFinder'] = true
91 * @see Zend\Json\Expr
93 * @param mixed $valueToEncode
94 * @param bool $cycleCheck Optional; whether or not to check for object recursion; off by default
95 * @param array $options Additional options used during encoding
96 * @return string JSON encoded object
98 public static function encode($valueToEncode, $cycleCheck = false, $options = array())
100 if (is_object($valueToEncode)) {
101 if (method_exists($valueToEncode, 'toJson')) {
102 return $valueToEncode->toJson();
103 } elseif (method_exists($valueToEncode, 'toArray')) {
104 return static::encode($valueToEncode->toArray(), $cycleCheck, $options);
108 // Pre-encoding look for Zend\Json\Expr objects and replacing by tmp ids
109 $javascriptExpressions = array();
110 if (isset($options['enableJsonExprFinder'])
111 && ($options['enableJsonExprFinder'] == true)
113 $valueToEncode = static::_recursiveJsonExprFinder($valueToEncode, $javascriptExpressions);
116 // Encoding
117 if (function_exists('json_encode') && static::$useBuiltinEncoderDecoder !== true) {
118 $encodedResult = json_encode(
119 $valueToEncode,
120 JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP
122 } else {
123 $encodedResult = Encoder::encode($valueToEncode, $cycleCheck, $options);
126 //only do post-processing to revert back the Zend\Json\Expr if any.
127 if (count($javascriptExpressions) > 0) {
128 $count = count($javascriptExpressions);
129 for ($i = 0; $i < $count; $i++) {
130 $magicKey = $javascriptExpressions[$i]['magicKey'];
131 $value = $javascriptExpressions[$i]['value'];
133 $encodedResult = str_replace(
134 //instead of replacing "key:magicKey", we replace directly magicKey by value because "key" never changes.
135 '"' . $magicKey . '"',
136 $value,
137 $encodedResult
142 return $encodedResult;
146 * Check & Replace Zend\Json\Expr for tmp ids in the valueToEncode
148 * Check if the value is a Zend\Json\Expr, and if replace its value
149 * with a magic key and save the javascript expression in an array.
151 * NOTE this method is recursive.
153 * NOTE: This method is used internally by the encode method.
155 * @see encode
156 * @param mixed $value a string - object property to be encoded
157 * @param array $javascriptExpressions
158 * @param null|string|int $currentKey
159 * @return mixed
161 protected static function _recursiveJsonExprFinder(
162 &$value, array &$javascriptExpressions, $currentKey = null
164 if ($value instanceof Expr) {
165 // TODO: Optimize with ascii keys, if performance is bad
166 $magicKey = "____" . $currentKey . "_" . (count($javascriptExpressions));
167 $javascriptExpressions[] = array(
169 //if currentKey is integer, encodeUnicodeString call is not required.
170 "magicKey" => (is_int($currentKey)) ? $magicKey : Encoder::encodeUnicodeString($magicKey),
171 "value" => $value->__toString(),
173 $value = $magicKey;
174 } elseif (is_array($value)) {
175 foreach ($value as $k => $v) {
176 $value[$k] = static::_recursiveJsonExprFinder($value[$k], $javascriptExpressions, $k);
178 } elseif (is_object($value)) {
179 foreach ($value as $k => $v) {
180 $value->$k = static::_recursiveJsonExprFinder($value->$k, $javascriptExpressions, $k);
183 return $value;
186 * Return the value of an XML attribute text or the text between
187 * the XML tags
189 * In order to allow Zend\Json\Expr from xml, we check if the node
190 * matches the pattern that try to detect if it is a new Zend\Json\Expr
191 * if it matches, we return a new Zend\Json\Expr instead of a text node
193 * @param SimpleXMLElement $simpleXmlElementObject
194 * @return Expr|string
196 protected static function _getXmlValue($simpleXmlElementObject)
198 $pattern = '/^[\s]*new Zend[_\\]Json[_\\]Expr[\s]*\([\s]*[\"\']{1}(.*)[\"\']{1}[\s]*\)[\s]*$/';
199 $matchings = array();
200 $match = preg_match($pattern, $simpleXmlElementObject, $matchings);
201 if ($match) {
202 return new Expr($matchings[1]);
204 return (trim(strval($simpleXmlElementObject)));
208 * _processXml - Contains the logic for xml2json
210 * The logic in this function is a recursive one.
212 * The main caller of this function (i.e. fromXml) needs to provide
213 * only the first two parameters i.e. the SimpleXMLElement object and
214 * the flag for ignoring or not ignoring XML attributes. The third parameter
215 * will be used internally within this function during the recursive calls.
217 * This function converts the SimpleXMLElement object into a PHP array by
218 * calling a recursive (protected static) function in this class. Once all
219 * the XML elements are stored in the PHP array, it is returned to the caller.
221 * @param SimpleXMLElement $simpleXmlElementObject
222 * @param bool $ignoreXmlAttributes
223 * @param int $recursionDepth
224 * @throws Exception\RecursionException if the XML tree is deeper than the allowed limit.
225 * @return array
227 protected static function _processXml($simpleXmlElementObject, $ignoreXmlAttributes, $recursionDepth = 0)
229 // Keep an eye on how deeply we are involved in recursion.
230 if ($recursionDepth > static::$maxRecursionDepthAllowed) {
231 // XML tree is too deep. Exit now by throwing an exception.
232 throw new RecursionException(
233 "Function _processXml exceeded the allowed recursion depth of "
234 . static::$maxRecursionDepthAllowed
238 $children = $simpleXmlElementObject->children();
239 $name = $simpleXmlElementObject->getName();
240 $value = static::_getXmlValue($simpleXmlElementObject);
241 $attributes = (array) $simpleXmlElementObject->attributes();
243 if (!count($children)) {
244 if (!empty($attributes) && !$ignoreXmlAttributes) {
245 foreach ($attributes['@attributes'] as $k => $v) {
246 $attributes['@attributes'][$k] = static::_getXmlValue($v);
248 if (!empty($value)) {
249 $attributes['@text'] = $value;
251 return array($name => $attributes);
254 return array($name => $value);
257 $childArray = array();
258 foreach ($children as $child) {
259 $childname = $child->getName();
260 $element = static::_processXml($child, $ignoreXmlAttributes, $recursionDepth + 1);
261 if (array_key_exists($childname, $childArray)) {
262 if (empty($subChild[$childname])) {
263 $childArray[$childname] = array($childArray[$childname]);
264 $subChild[$childname] = true;
266 $childArray[$childname][] = $element[$childname];
267 } else {
268 $childArray[$childname] = $element[$childname];
272 if (!empty($attributes) && !$ignoreXmlAttributes) {
273 foreach ($attributes['@attributes'] as $k => $v) {
274 $attributes['@attributes'][$k] = static::_getXmlValue($v);
276 $childArray['@attributes'] = $attributes['@attributes'];
279 if (!empty($value)) {
280 $childArray['@text'] = $value;
283 return array($name => $childArray);
287 * fromXml - Converts XML to JSON
289 * Converts a XML formatted string into a JSON formatted string.
290 * The value returned will be a string in JSON format.
292 * The caller of this function needs to provide only the first parameter,
293 * which is an XML formatted String. The second parameter is optional, which
294 * lets the user to select if the XML attributes in the input XML string
295 * should be included or ignored in xml2json conversion.
297 * This function converts the XML formatted string into a PHP array by
298 * calling a recursive (protected static) function in this class. Then, it
299 * converts that PHP array into JSON by calling the "encode" static function.
301 * NOTE: Encoding native javascript expressions via Zend\Json\Expr is not possible.
303 * @static
304 * @access public
305 * @param string $xmlStringContents XML String to be converted
306 * @param bool $ignoreXmlAttributes Include or exclude XML attributes in
307 * the xml2json conversion process.
308 * @return mixed - JSON formatted string on success
309 * @throws \Zend\Json\Exception\RuntimeException if the input not a XML formatted string
311 public static function fromXml($xmlStringContents, $ignoreXmlAttributes = true)
313 // Load the XML formatted string into a Simple XML Element object.
314 $simpleXmlElementObject = simplexml_load_string($xmlStringContents);
316 // If it is not a valid XML content, throw an exception.
317 if ($simpleXmlElementObject == null) {
318 throw new RuntimeException('Function fromXml was called with an invalid XML formatted string.');
319 } // End of if ($simpleXmlElementObject == null)
321 $resultArray = null;
323 // Call the recursive function to convert the XML into a PHP array.
324 $resultArray = static::_processXml($simpleXmlElementObject, $ignoreXmlAttributes);
326 // Convert the PHP array to JSON using Zend\Json\Json encode method.
327 // It is just that simple.
328 $jsonStringOutput = static::encode($resultArray);
329 return($jsonStringOutput);
333 * Pretty-print JSON string
335 * Use 'indent' option to select indentation string - by default it's a tab
337 * @param string $json Original JSON string
338 * @param array $options Encoding options
339 * @return string
341 public static function prettyPrint($json, $options = array())
343 $tokens = preg_split('|([\{\}\]\[,])|', $json, -1, PREG_SPLIT_DELIM_CAPTURE);
344 $result = "";
345 $indent = 0;
347 $ind = "\t";
348 if (isset($options['indent'])) {
349 $ind = $options['indent'];
352 $inLiteral = false;
353 foreach ($tokens as $token) {
354 if ($token == "") continue;
356 $prefix = str_repeat($ind, $indent);
357 if (!$inLiteral && ($token == "{" || $token == "[")) {
358 $indent++;
359 if ($result != "" && $result[strlen($result)-1] == "\n") {
360 $result .= $prefix;
362 $result .= "$token\n";
363 } elseif (!$inLiteral && ($token == "}" || $token == "]")) {
364 $indent--;
365 $prefix = str_repeat($ind, $indent);
366 $result .= "\n$prefix$token";
367 } elseif (!$inLiteral && $token == ",") {
368 $result .= "$token\n";
369 } else {
370 $result .= ($inLiteral ? '' : $prefix) . $token;
372 // Count # of unescaped double-quotes in token, subtract # of
373 // escaped double-quotes and if the result is odd then we are
374 // inside a string literal
375 if ((substr_count($token, "\"")-substr_count($token, "\\\"")) % 2 != 0) {
376 $inLiteral = !$inLiteral;
380 return $result;