Advertisement
Guest User

Untitled

a guest
Apr 21st, 2015
329
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.18 KB | None | 0 0
  1. <?php
  2. /**
  3. * Dot notation for access multidimensional arrays.
  4. *
  5. * $dn = new DotNotation(['bar'=>['baz'=>['foo'=>true]]]);
  6. *
  7. * $value = $dn->get('bar.baz.foo'); // $value == true
  8. *
  9. * $dn->set('bar.baz.foo', false); // ['foo'=>false]
  10. *
  11. * $dn->add('bar.baz', ['boo'=>true]); // ['foo'=>false,'boo'=>true]
  12. *
  13. * @author Anton Medvedev <anton (at) elfet (dot) ru>
  14. * @version 2.0
  15. * @license MIT
  16. */
  17. class DotNotation
  18. {
  19. const SEPARATOR = '/[:\.]/';
  20.  
  21. /**
  22. * @var array
  23. */
  24. protected $values = array();
  25.  
  26. /**
  27. * @var array
  28. */
  29. public function __construct(array $values)
  30. {
  31. $this->values = $values;
  32. }
  33.  
  34. /**
  35. * @param string $path
  36. * @param string $default
  37. * @return mixed
  38. */
  39. public function get($path, $default = null)
  40. {
  41. $array = $this->values;
  42.  
  43. if (!empty($path)) {
  44. $keys = $this->explode($path);
  45. foreach ($keys as $key) {
  46. if (isset($array[$key])) {
  47. $array = $array[$key];
  48. } else {
  49. return $default;
  50. }
  51. }
  52. }
  53.  
  54. return $array;
  55. }
  56.  
  57. /**
  58. * @param string $path
  59. * @param mixed $value
  60. */
  61. public function set($path, $value)
  62. {
  63. if (!empty($path)) {
  64. $at = & $this->values;
  65. $keys = $this->explode($path);
  66.  
  67. while (count($keys) > 0) {
  68. if (count($keys) === 1) {
  69. if (is_array($at)) {
  70. $at[array_shift($keys)] = $value;
  71. } else {
  72. throw new \RuntimeException("Can not set value at this path ($path) because is not array.");
  73. }
  74. } else {
  75. $key = array_shift($keys);
  76.  
  77. if (!isset($at[$key])) {
  78. $at[$key] = array();
  79. }
  80.  
  81. $at = & $at[$key];
  82. }
  83. }
  84. } else {
  85. $this->values = $value;
  86. }
  87. }
  88.  
  89. /**
  90. * @param $path
  91. * @param array $values
  92. */
  93. public function add($path, array $values)
  94. {
  95. $get = (array)$this->get($path);
  96. $this->set($path, $this->arrayMergeRecursiveDistinct($get, $values));
  97. }
  98.  
  99. /**
  100. * @param string $path
  101. * @return bool
  102. */
  103. public function have($path)
  104. {
  105. $keys = $this->explode($path);
  106. $array = $this->values;
  107. foreach ($keys as $key) {
  108. if (isset($array[$key])) {
  109. $array = $array[$key];
  110. } else {
  111. return false;
  112. }
  113. }
  114.  
  115. return true;
  116. }
  117.  
  118. /**
  119. * @param array $values
  120. */
  121. public function setValues($values)
  122. {
  123. $this->values = $values;
  124. }
  125.  
  126. /**
  127. * @return array
  128. */
  129. public function getValues()
  130. {
  131. return $this->values;
  132. }
  133.  
  134. protected function explode($path)
  135. {
  136. return preg_split(self::SEPARATOR, $path);
  137. }
  138.  
  139. /**
  140. * array_merge_recursive does indeed merge arrays, but it converts values with duplicate
  141. * keys to arrays rather than overwriting the value in the first array with the duplicate
  142. * value in the second array, as array_merge does. I.e., with array_merge_recursive,
  143. * this happens (documented behavior):
  144. *
  145. * array_merge_recursive(array('key' => 'org value'), array('key' => 'new value'));
  146. * => array('key' => array('org value', 'new value'));
  147. *
  148. * arrayMergeRecursiveDistinct does not change the datatypes of the values in the arrays.
  149. * Matching keys' values in the second array overwrite those in the first array, as is the
  150. * case with array_merge, i.e.:
  151. *
  152. * arrayMergeRecursiveDistinct(array('key' => 'org value'), array('key' => 'new value'));
  153. * => array('key' => array('new value'));
  154. *
  155. * Parameters are passed by reference, though only for performance reasons. They're not
  156. * altered by this function.
  157. *
  158. * If key is integer, it will be merged like array_merge do:
  159. * arrayMergeRecursiveDistinct(array(0 => 'org value'), array(0 => 'new value'));
  160. * => array(0 => 'org value', 1 => 'new value');
  161. *
  162. * @param array $array1
  163. * @param array $array2
  164. * @return array
  165. * @author Daniel <daniel (at) danielsmedegaardbuus (dot) dk>
  166. * @author Gabriel Sobrinho <gabriel (dot) sobrinho (at) gmail (dot) com>
  167. * @author Anton Medvedev <anton (at) elfet (dot) ru>
  168. */
  169. protected function arrayMergeRecursiveDistinct(array &$array1, array &$array2)
  170. {
  171. $merged = $array1;
  172.  
  173. foreach ($array2 as $key => &$value) {
  174. if (is_array($value) && isset ($merged[$key]) && is_array($merged[$key])) {
  175. if (is_int($key)) {
  176. $merged[] = $this->arrayMergeRecursiveDistinct($merged[$key], $value);
  177. } else {
  178. $merged[$key] = $this->arrayMergeRecursiveDistinct($merged[$key], $value);
  179. }
  180. } else {
  181. if (is_int($key)) {
  182. $merged[] = $value;
  183. } else {
  184. $merged[$key] = $value;
  185. }
  186. }
  187. }
  188.  
  189. return $merged;
  190. }
  191. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement