JsonRef.php 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. <?php
  2. /* Copyright (c)
  3. * - 2014, Geert Bergman (geert@scrivo.nl), highlight.php
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice,
  10. * this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. * 3. Neither the name of "highlight.js", "highlight.php", nor the names of its
  15. * contributors may be used to endorse or promote products derived from this
  16. * software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  19. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  20. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  21. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  22. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  23. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  24. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  25. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  26. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  27. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  28. * POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. /**
  31. * Implementation of the \Highlight\JsonRef class.
  32. */
  33. namespace Highlight;
  34. /**
  35. * Class to decode JSON data that contains path-based references.
  36. *
  37. * The language data file for highlight.js are written as JavaScript classes
  38. * and therefore may contain variables. This allows for inner references in
  39. * the language data. This kind of data can be converterd to JSON using the
  40. * path based references. This class can be used to decode such JSON
  41. * structures. It follows the conventions for path based referencing as
  42. * used in dojox.json.ref form the Dojo toolkit (Javascript). A typical
  43. * example of such a structure is as follows:
  44. *
  45. * {
  46. * "name":"Kris Zyp",
  47. * "children":[{"name":"Jennika Zyp"},{"name":"Korban Zyp"}],
  48. * "spouse":{
  49. * "name":"Nicole Zyp",
  50. * "spouse":{"$ref":"#"},
  51. * "children":{"$ref":"#children"}
  52. * },
  53. * "oldestChild":{"$ref":"#children.0"}
  54. * }
  55. *
  56. * Usage example:
  57. *
  58. * $jr = new JsonRef();
  59. * $data = $jr->decode(file_get_contents("data.json"));
  60. * echo $data->spouse->spouse->name; // echos 'Kris Zyp'
  61. * echo $data->oldestChild->name; // echos 'Jennika Zyp'
  62. *
  63. */
  64. class JsonRef
  65. {
  66. /**
  67. * Array to hold all data paths in the given JSON data.
  68. * @var array
  69. */
  70. private $paths = null;
  71. /**
  72. * Recurse through the data tree and fill an array of paths that reference
  73. * the nodes in the decoded JSON data structure.
  74. *
  75. * @param mixed $s
  76. * Decoded JSON data (decoded with json_decode).
  77. * @param string $r
  78. * The current path key (for example: '#children.0').
  79. */
  80. private function getPaths(&$s, $r="#")
  81. {
  82. $this->paths[$r] = &$s;
  83. if (is_array($s) || is_object($s)) {
  84. foreach ($s as $k => &$v) {
  85. if ($k !== "\$ref") {
  86. $this->getPaths($v, $r=="#"?"#{$k}":"{$r}.{$k}");
  87. }
  88. }
  89. }
  90. }
  91. /**
  92. * Recurse through the data tree and resolve all path references.
  93. *
  94. * @param mixed $s
  95. * Decoded JSON data (decoded with json_decode).
  96. */
  97. private function resolvePathReferences(&$s)
  98. {
  99. if (is_array($s) || is_object($s)) {
  100. foreach ($s as $k => &$v) {
  101. if ($k === "\$ref") {
  102. $s = $this->paths[$v];
  103. } else {
  104. $this->resolvePathReferences($v);
  105. }
  106. }
  107. }
  108. }
  109. /**
  110. * Decode JSON data that may contain path based references.
  111. *
  112. * @param string|object $json
  113. * JSON data string or JSON data object.
  114. * @return mixed
  115. * The decoded JSON data.
  116. */
  117. public function decode($json)
  118. {
  119. // Clear the path array.
  120. $this->paths = array();
  121. // Decode the given JSON data if necessary.
  122. $x = is_string($json) ? json_decode($json) : $json;
  123. // Get all data paths.
  124. $this->getPaths($x);
  125. // Resolve all path references.
  126. $this->resolvePathReferences($x);
  127. // Return the data.
  128. return $x;
  129. }
  130. }