Model.php 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. <?php
  2. /**
  3. * Copyright (c) 2011-2018 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to deal
  6. * in the Software without restriction, including without limitation the rights
  7. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. * copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:
  10. * The above copyright notice and this permission notice shall be included in
  11. * all copies or substantial portions of the Software.
  12. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  13. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  14. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  15. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  16. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  17. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  18. * THE SOFTWARE.
  19. */
  20. namespace Obs\Internal\Common;
  21. class Model implements \ArrayAccess, \IteratorAggregate, \Countable, ToArrayInterface
  22. {
  23. protected $data;
  24. public function __construct(array $data = [])
  25. {
  26. $this->data = $data;
  27. }
  28. public function count()
  29. {
  30. return count($this->data);
  31. }
  32. public function getIterator()
  33. {
  34. return new \ArrayIterator($this->data);
  35. }
  36. public function toArray()
  37. {
  38. return $this->data;
  39. }
  40. public function clear()
  41. {
  42. $this->data = [];
  43. return $this;
  44. }
  45. public function getAll(array $keys = null)
  46. {
  47. return $keys ? array_intersect_key($this->data, array_flip($keys)) : $this->data;
  48. }
  49. public function get($key)
  50. {
  51. return isset($this->data[$key]) ? $this->data[$key] : null;
  52. }
  53. public function set($key, $value)
  54. {
  55. $this->data[$key] = $value;
  56. return $this;
  57. }
  58. public function add($key, $value)
  59. {
  60. if (!array_key_exists($key, $this->data)) {
  61. $this->data[$key] = $value;
  62. } elseif (is_array($this->data[$key])) {
  63. $this->data[$key][] = $value;
  64. } else {
  65. $this->data[$key] = [$this->data[$key], $value];
  66. }
  67. return $this;
  68. }
  69. public function remove($key)
  70. {
  71. unset($this->data[$key]);
  72. return $this;
  73. }
  74. public function getKeys()
  75. {
  76. return array_keys($this->data);
  77. }
  78. public function hasKey($key)
  79. {
  80. return array_key_exists($key, $this->data);
  81. }
  82. public function keySearch($key)
  83. {
  84. foreach (array_keys($this->data) as $k) {
  85. if (!strcasecmp($k, $key)) {
  86. return $k;
  87. }
  88. }
  89. return false;
  90. }
  91. public function hasValue($value)
  92. {
  93. return array_search($value, $this->data);
  94. }
  95. public function replace(array $data)
  96. {
  97. $this->data = $data;
  98. return $this;
  99. }
  100. public function merge($data)
  101. {
  102. foreach ($data as $key => $value) {
  103. $this->add($key, $value);
  104. }
  105. return $this;
  106. }
  107. public function overwriteWith($data)
  108. {
  109. if (is_array($data)) {
  110. $this->data = $data + $this->data;
  111. } else {
  112. foreach ($data as $key => $value) {
  113. $this->data[$key] = $value;
  114. }
  115. }
  116. return $this;
  117. }
  118. public function map(\Closure $closure, array $context = [], $static = true)
  119. {
  120. $collection = $static ? new static() : new self();
  121. foreach ($this as $key => $value) {
  122. $collection->add($key, $closure($key, $value, $context));
  123. }
  124. return $collection;
  125. }
  126. public function filter(\Closure $closure, $static = true)
  127. {
  128. $collection = ($static) ? new static() : new self();
  129. foreach ($this->data as $key => $value) {
  130. if ($closure($key, $value)) {
  131. $collection->add($key, $value);
  132. }
  133. }
  134. return $collection;
  135. }
  136. public function offsetExists($offset)
  137. {
  138. return isset($this->data[$offset]);
  139. }
  140. public function offsetGet($offset)
  141. {
  142. return isset($this->data[$offset]) ? $this->data[$offset] : null;
  143. }
  144. public function offsetSet($offset, $value)
  145. {
  146. $this->data[$offset] = $value;
  147. }
  148. public function offsetUnset($offset)
  149. {
  150. unset($this->data[$offset]);
  151. }
  152. public function setPath($path, $value)
  153. {
  154. $current =& $this->data;
  155. $queue = explode('/', $path);
  156. while (null !== ($key = array_shift($queue))) {
  157. if (!is_array($current)) {
  158. throw new \RuntimeException("Trying to setPath {$path}, but {$key} is set and is not an array");
  159. } elseif (!$queue) {
  160. $current[$key] = $value;
  161. } elseif (isset($current[$key])) {
  162. $current =& $current[$key];
  163. } else {
  164. $current[$key] = [];
  165. $current =& $current[$key];
  166. }
  167. }
  168. return $this;
  169. }
  170. public function getPath($path, $separator = '/', $data = null)
  171. {
  172. if ($data === null) {
  173. $data =& $this->data;
  174. }
  175. $path = is_array($path) ? $path : explode($separator, $path);
  176. while (null !== ($part = array_shift($path))) {
  177. if (!is_array($data)) {
  178. return null;
  179. } elseif (isset($data[$part])) {
  180. $data =& $data[$part];
  181. } elseif ($part != '*') {
  182. return null;
  183. } else {
  184. // Perform a wildcard search by diverging and merging paths
  185. $result = [];
  186. foreach ($data as $value) {
  187. if (!$path) {
  188. $result = array_merge_recursive($result, (array) $value);
  189. } elseif (null !== ($test = $this->getPath($path, $separator, $value))) {
  190. $result = array_merge_recursive($result, (array) $test);
  191. }
  192. }
  193. return $result;
  194. }
  195. }
  196. return $data;
  197. }
  198. public function __toString()
  199. {
  200. $output = 'Debug output of ';
  201. $output .= 'model';
  202. $output = str_repeat('=', strlen($output)) . "\n" . $output . "\n" . str_repeat('=', strlen($output)) . "\n\n";
  203. $output .= "Model data\n-----------\n\n";
  204. $output .= "This data can be retrieved from the model object using the get() method of the model "
  205. . "(e.g. \$model->get(\$key)) or accessing the model like an associative array (e.g. \$model['key']).\n\n";
  206. $lines = array_slice(explode("\n", trim(print_r($this->toArray(), true))), 2, -1);
  207. $output .= implode("\n", $lines);
  208. return $output . "\n";
  209. }
  210. }