/vendor/phpcollection/phpcollection/src/PhpCollection/AbstractMap.php

https://gitlab.com/cuza/Clinic_Recods · PHP · 295 lines · 199 code · 55 blank · 41 comment · 14 complexity · 8c4b65936bb2fe373a573f9db9c4cb05 MD5 · raw file

  1. <?php
  2. /*
  3. * Copyright 2012 Johannes M. Schmitt <schmittjoh@gmail.com>
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. namespace PhpCollection;
  18. use PhpOption\Some;
  19. use PhpOption\None;
  20. /**
  21. * A simple map implementation which basically wraps an array with an object oriented interface.
  22. *
  23. * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  24. */
  25. class AbstractMap extends AbstractCollection implements \IteratorAggregate, MapInterface
  26. {
  27. protected $elements;
  28. public function __construct(array $elements = array())
  29. {
  30. $this->elements = $elements;
  31. }
  32. public function set($key, $value)
  33. {
  34. $this->elements[$key] = $value;
  35. }
  36. public function exists($callable)
  37. {
  38. foreach ($this as $k => $v) {
  39. if ($callable($k, $v) === true) {
  40. return true;
  41. }
  42. }
  43. return false;
  44. }
  45. /**
  46. * Sets all key/value pairs in the map.
  47. *
  48. * @param array $kvMap
  49. *
  50. * @return void
  51. */
  52. public function setAll(array $kvMap)
  53. {
  54. $this->elements = array_merge($this->elements, $kvMap);
  55. }
  56. public function addMap(MapInterface $map)
  57. {
  58. foreach ($map as $k => $v) {
  59. $this->elements[$k] = $v;
  60. }
  61. }
  62. public function get($key)
  63. {
  64. if (isset($this->elements[$key])) {
  65. return new Some($this->elements[$key]);
  66. }
  67. return None::create();
  68. }
  69. public function remove($key)
  70. {
  71. if ( ! isset($this->elements[$key])) {
  72. throw new \InvalidArgumentException(sprintf('The map has no key named "%s".', $key));
  73. }
  74. $element = $this->elements[$key];
  75. unset($this->elements[$key]);
  76. return $element;
  77. }
  78. public function clear()
  79. {
  80. $this->elements = array();
  81. }
  82. public function first()
  83. {
  84. if (empty($this->elements)) {
  85. return None::create();
  86. }
  87. $elem = reset($this->elements);
  88. return new Some(array(key($this->elements), $elem));
  89. }
  90. public function last()
  91. {
  92. if (empty($this->elements)) {
  93. return None::create();
  94. }
  95. $elem = end($this->elements);
  96. return new Some(array(key($this->elements), $elem));
  97. }
  98. public function contains($elem)
  99. {
  100. foreach ($this->elements as $existingElem) {
  101. if ($existingElem === $elem) {
  102. return true;
  103. }
  104. }
  105. return false;
  106. }
  107. public function containsKey($key)
  108. {
  109. return isset($this->elements[$key]);
  110. }
  111. public function isEmpty()
  112. {
  113. return empty($this->elements);
  114. }
  115. /**
  116. * Returns a new filtered map.
  117. *
  118. * @param callable $callable receives the element and must return true (= keep), or false (= remove).
  119. *
  120. * @return AbstractMap
  121. */
  122. public function filter($callable)
  123. {
  124. return $this->filterInternal($callable, true);
  125. }
  126. /**
  127. * Returns a new filtered map.
  128. *
  129. * @param callable $callable receives the element and must return true (= remove), or false (= keep).
  130. *
  131. * @return AbstractMap
  132. */
  133. public function filterNot($callable)
  134. {
  135. return $this->filterInternal($callable, false);
  136. }
  137. private function filterInternal($callable, $booleanKeep)
  138. {
  139. $newElements = array();
  140. foreach ($this->elements as $k => $element) {
  141. if ($booleanKeep !== call_user_func($callable, $element)) {
  142. continue;
  143. }
  144. $newElements[$k] = $element;
  145. }
  146. return $this->createNew($newElements);
  147. }
  148. public function foldLeft($initialValue, $callable)
  149. {
  150. $value = $initialValue;
  151. foreach ($this->elements as $elem) {
  152. $value = call_user_func($callable, $value, $elem);
  153. }
  154. return $value;
  155. }
  156. public function foldRight($initialValue, $callable)
  157. {
  158. $value = $initialValue;
  159. foreach (array_reverse($this->elements) as $elem) {
  160. $value = call_user_func($callable, $elem, $value);
  161. }
  162. return $value;
  163. }
  164. public function dropWhile($callable)
  165. {
  166. $newElements = array();
  167. $stopped = false;
  168. foreach ($this->elements as $k => $v) {
  169. if ( ! $stopped) {
  170. if (call_user_func($callable, $k, $v) === true) {
  171. continue;
  172. }
  173. $stopped = true;
  174. }
  175. $newElements[$k] = $v;
  176. }
  177. return $this->createNew($newElements);
  178. }
  179. public function drop($number)
  180. {
  181. if ($number <= 0) {
  182. throw new \InvalidArgumentException(sprintf('The number must be greater than 0, but got %d.', $number));
  183. }
  184. return $this->createNew(array_slice($this->elements, $number, null, true));
  185. }
  186. public function dropRight($number)
  187. {
  188. if ($number <= 0) {
  189. throw new \InvalidArgumentException(sprintf('The number must be greater than 0, but got %d.', $number));
  190. }
  191. return $this->createNew(array_slice($this->elements, 0, -1 * $number, true));
  192. }
  193. public function take($number)
  194. {
  195. if ($number <= 0) {
  196. throw new \InvalidArgumentException(sprintf('The number must be greater than 0, but got %d.', $number));
  197. }
  198. return $this->createNew(array_slice($this->elements, 0, $number, true));
  199. }
  200. public function takeWhile($callable)
  201. {
  202. $newElements = array();
  203. foreach ($this->elements as $k => $v) {
  204. if (call_user_func($callable, $k, $v) !== true) {
  205. break;
  206. }
  207. $newElements[$k] = $v;
  208. }
  209. return $this->createNew($newElements);
  210. }
  211. public function find($callable)
  212. {
  213. foreach ($this->elements as $k => $v) {
  214. if (call_user_func($callable, $k, $v) === true) {
  215. return new Some(array($k, $v));
  216. }
  217. }
  218. return None::create();
  219. }
  220. public function keys()
  221. {
  222. return array_keys($this->elements);
  223. }
  224. public function values()
  225. {
  226. return array_values($this->elements);
  227. }
  228. public function count()
  229. {
  230. return count($this->elements);
  231. }
  232. public function getIterator()
  233. {
  234. return new \ArrayIterator($this->elements);
  235. }
  236. protected function createNew(array $elements)
  237. {
  238. return new static($elements);
  239. }
  240. }