PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/cases/util/CollectionTest.php

https://github.com/rmarscher/lithium
PHP | 373 lines | 258 code | 57 blank | 58 comment | 6 complexity | afef51969776af6d255f3580596fe1ce MD5 | raw file
  1. <?php
  2. /**
  3. * Lithium: the most rad php framework
  4. *
  5. * @copyright Copyright 2012, Union of RAD (http://union-of-rad.org)
  6. * @license http://opensource.org/licenses/bsd-license.php The BSD License
  7. */
  8. namespace lithium\tests\cases\util;
  9. use stdClass;
  10. use lithium\util\Collection;
  11. use lithium\tests\mocks\util\MockCollectionMarker;
  12. use lithium\tests\mocks\util\MockCollectionObject;
  13. use lithium\tests\mocks\util\MockCollectionStringCast;
  14. class CollectionTest extends \lithium\test\Unit {
  15. public function setUp() {
  16. Collection::formats('lithium\net\http\Media');
  17. }
  18. public function testArrayLike() {
  19. $collection = new Collection();
  20. $collection[] = 'foo';
  21. $this->assertEqual($collection[0], 'foo');
  22. $this->assertEqual(count($collection), 1);
  23. $collection = new Collection(array('data' => array('foo')));
  24. $this->assertEqual($collection[0], 'foo');
  25. $this->assertEqual(count($collection), 1);
  26. }
  27. public function testObjectMethodDispatch() {
  28. $collection = new Collection();
  29. for ($i = 0; $i < 10; $i++) {
  30. $collection[] = new MockCollectionMarker();
  31. }
  32. $result = $collection->mark();
  33. $this->assertEqual($result, array_fill(0, 10, true));
  34. $result = $collection->mapArray();
  35. $this->assertEqual($result, array_fill(0, 10, array('foo')));
  36. $result = $collection->invoke('mapArray', array(), array('merge' => true));
  37. $this->assertEqual($result, array_fill(0, 10, 'foo'));
  38. $collection = new Collection(array(
  39. 'data' => array_fill(0, 10, new MockCollectionObject())
  40. ));
  41. $result = $collection->testFoo();
  42. $this->assertEqual($result, array_fill(0, 10, 'testFoo'));
  43. $result = $collection->invoke('testFoo', array(), array('collect' => true));
  44. $this->assertTrue($result instanceof Collection);
  45. $this->assertEqual($result->to('array'), array_fill(0, 10, 'testFoo'));
  46. }
  47. public function testObjectCasting() {
  48. $collection = new Collection(array(
  49. 'data' => array_fill(0, 10, new MockCollectionObject())
  50. ));
  51. $result = $collection->to('array');
  52. $expected = array_fill(0, 10, array(1 => 2, 2 => 3));
  53. $this->assertEqual($expected, $result);
  54. $collection = new Collection(array(
  55. 'data' => array_fill(0, 10, new MockCollectionMarker())
  56. ));
  57. $result = $collection->to('array');
  58. $expected = array_fill(0, 10, array('marker' => false, 'data' => 'foo'));
  59. $this->assertEqual($expected, $result);
  60. $collection = new Collection(array(
  61. 'data' => array_fill(0, 10, new MockCollectionStringCast())
  62. ));
  63. $result = $collection->to('array');
  64. $expected = array_fill(0, 10, json_encode(array(1 => 2, 2 => 3)));
  65. $this->assertEqual($expected, $result);
  66. }
  67. /**
  68. * Tests that the `find()` method properly filters items out of the resulting collection.
  69. *
  70. * @return void
  71. */
  72. public function testCollectionFindFilter() {
  73. $collection = new Collection(array('data' => array_merge(
  74. array_fill(0, 10, 1),
  75. array_fill(0, 10, 2)
  76. )));
  77. $this->assertEqual(20, count($collection->to('array')));
  78. $filter = function($item) { return $item == 1; };
  79. $result = $collection->find($filter);
  80. $this->assertTrue($result instanceof Collection);
  81. $this->assertEqual(array_fill(0, 10, 1), $result->to('array'));
  82. $result = $collection->find($filter, array('collect' => false));
  83. $this->assertEqual(array_fill(0, 10, 1), $result);
  84. }
  85. /**
  86. * Tests that the `first()` method properly returns the first non-empty value.
  87. *
  88. * @return void
  89. */
  90. public function testCollectionFirstFilter() {
  91. $collection = new Collection(array('data' => array(0, 1, 2)));
  92. $result = $collection->first(function($value) { return $value; });
  93. $this->assertEqual(1, $result);
  94. $collection = new Collection(array('data' => array('Hello', '', 'Goodbye')));
  95. $result = $collection->first(function($value) { return $value; });
  96. $this->assertEqual('Hello', $result);
  97. $collection = new Collection(array('data' => array('', 'Hello', 'Goodbye')));
  98. $result = $collection->first(function($value) { return $value; });
  99. $this->assertEqual('Hello', $result);
  100. $collection = new Collection(array('data' => array('', 'Hello', 'Goodbye')));
  101. $result = $collection->first();
  102. $this->assertEqual('', $result);
  103. }
  104. /**
  105. * Tests that the `each()` filter applies the callback to each item in the current collection,
  106. * returning an instance of itself.
  107. *
  108. * @return void
  109. */
  110. public function testCollectionEachFilter() {
  111. $collection = new Collection(array('data' => array(1, 2, 3, 4, 5)));
  112. $filter = function($item) { return ++$item; };
  113. $result = $collection->each($filter);
  114. $this->assertIdentical($collection, $result);
  115. $this->assertEqual(array(2, 3, 4, 5, 6), $collection->to('array'));
  116. }
  117. public function testCollectionMapFilter() {
  118. $collection = new Collection(array('data' => array(1, 2, 3, 4, 5)));
  119. $filter = function($item) { return ++$item; };
  120. $result = $collection->map($filter);
  121. $this->assertNotEqual($collection, $result);
  122. $this->assertEqual(array(1, 2, 3, 4, 5), $collection->to('array'));
  123. $this->assertEqual(array(2, 3, 4, 5, 6), $result->to('array'));
  124. $result = $collection->map($filter, array('collect' => false));
  125. $this->assertEqual(array(2, 3, 4, 5, 6), $result);
  126. }
  127. public function testCollectionReduceFilter() {
  128. $collection = new Collection(array('data' => array(1, 2, 3)));
  129. $filter = function($memo, $item) { return $memo + $item; };
  130. $result = $collection->reduce($filter, 0);
  131. $this->assertEqual(6, $collection->reduce($filter, 0));
  132. $this->assertEqual(7, $collection->reduce($filter, 1));
  133. }
  134. /**
  135. * Tests the `ArrayAccess` interface implementation for manipulating values by direct offsets.
  136. *
  137. * @return void
  138. */
  139. public function testArrayAccessOffsetMethods() {
  140. $collection = new Collection(array('data' => array('foo', 'bar', 'baz' => 'dib')));
  141. $this->assertTrue($collection->offsetExists(0));
  142. $this->assertTrue($collection->offsetExists(1));
  143. $this->assertTrue($collection->offsetExists('0'));
  144. $this->assertTrue($collection->offsetExists('baz'));
  145. $this->assertFalse($collection->offsetExists('2'));
  146. $this->assertFalse($collection->offsetExists('bar'));
  147. $this->assertFalse($collection->offsetExists(2));
  148. $this->assertEqual('foo', $collection->offsetSet('bar', 'foo'));
  149. $this->assertTrue($collection->offsetExists('bar'));
  150. $this->assertNull($collection->offsetUnset('bar'));
  151. $this->assertFalse($collection->offsetExists('bar'));
  152. }
  153. /**
  154. * Tests the `ArrayAccess` interface implementation for traversing values.
  155. *
  156. * @return void
  157. */
  158. public function testArrayAccessTraversalMethods() {
  159. $collection = new Collection(array('data' => array('foo', 'bar', 'baz' => 'dib')));
  160. $this->assertEqual('foo', $collection->current());
  161. $this->assertEqual('bar', $collection->next());
  162. $this->assertEqual('foo', $collection->prev());
  163. $this->assertEqual('bar', $collection->next());
  164. $this->assertEqual('dib', $collection->next());
  165. $this->assertEqual('baz', $collection->key());
  166. $this->assertTrue($collection->valid());
  167. $this->assertFalse($collection->next());
  168. $this->assertFalse($collection->valid());
  169. $this->assertEqual('foo', $collection->rewind());
  170. $this->assertTrue($collection->valid());
  171. $this->assertEqual('dib', $collection->prev());
  172. $this->assertTrue($collection->valid());
  173. $this->assertEqual('bar', $collection->prev());
  174. $this->assertTrue($collection->valid());
  175. $this->assertEqual('dib', $collection->end());
  176. $this->assertTrue($collection->valid());
  177. }
  178. /**
  179. * Tests objects and scalar values being appended to the collection.
  180. *
  181. * @return void
  182. */
  183. public function testValueAppend() {
  184. $collection = new Collection();
  185. $this->assertFalse($collection->valid());
  186. $this->assertEqual(0, count($collection));
  187. $collection->append(1);
  188. $this->assertEqual(1, count($collection));
  189. $collection->append(new stdClass());
  190. $this->assertEqual(2, count($collection));
  191. $this->assertEqual(1, $collection->current());
  192. $this->assertEqual(new stdClass(), $collection->next());
  193. }
  194. /**
  195. * Tests getting the index of the internal array.
  196. *
  197. * @return void
  198. */
  199. public function testInternalKeys() {
  200. $collection = new Collection(array('data' => array('foo', 'bar', 'baz' => 'dib')));
  201. $this->assertEqual(array(0, 1, 'baz'), $collection->keys());
  202. }
  203. /**
  204. * Tests that various types of handlers can be registered with `Collection::formats()`, and
  205. * that collection instances are converted correctly.
  206. *
  207. * @return void
  208. */
  209. public function testCollectionFormatConversion() {
  210. Collection::formats('lithium\net\http\Media');
  211. $data = array('hello', 'goodbye', 'foo' => array('bar', 'baz' => 'dib'));
  212. $collection = new Collection(compact('data'));
  213. $expected = json_encode($data);
  214. $result = $collection->to('json');
  215. $this->assertEqual($expected, $result);
  216. $this->assertNull($collection->to('badness'));
  217. Collection::formats(false);
  218. $this->assertNull($collection->to('json'));
  219. Collection::formats('json', function($collection, $options) {
  220. return json_encode($collection->to('array'));
  221. });
  222. $result = $collection->to('json');
  223. $this->assertEqual($expected, $result);
  224. $result = $collection->to(function($collection) {
  225. $value = array_map(
  226. function($i) { return is_array($i) ? join(',', $i) : $i; }, $collection->to('array')
  227. );
  228. return join(',', $value);
  229. });
  230. $expected = 'hello,goodbye,bar,dib';
  231. $this->assertEqual($expected, $result);
  232. }
  233. public function testCollectionHandlers() {
  234. $obj = new StdClass();
  235. $obj->a = "b";
  236. $handlers = array(
  237. 'stdClass' => function($v) { return (array) $v; }
  238. );
  239. $data = array(
  240. 'test' => new Collection(array('data' => compact('obj'))),
  241. 'obj' => $obj
  242. );
  243. $collection = new Collection(compact('data'));
  244. $expected = array(
  245. 'test' => array(
  246. 'obj' => array('a' => 'b')
  247. ),
  248. 'obj' => array('a' => 'b')
  249. );
  250. $this->assertIdentical($expected, $collection->to('array', compact('handlers')));
  251. $handlers = array(
  252. 'stdClass' => function($v) { return $v; }
  253. );
  254. $expected = array('test' => compact('obj')) + compact('obj');
  255. $this->assertIdentical($expected, $collection->to('array', compact('handlers')));
  256. }
  257. /**
  258. * Tests that the Collection::sort method works appropriately.
  259. *
  260. * @return void
  261. */
  262. public function testCollectionSort() {
  263. // Typical numeric sort using the default "sort" PHP function
  264. $collection = new Collection(array('data' => array(5,3,4,1,2)));
  265. $collection->sort();
  266. $expected = array(1,2,3,4,5);
  267. $this->assertEqual($expected, $collection->to('array'));
  268. // String sort using "sort"
  269. $collection = new Collection(array('data' => array('alan','dave','betsy','carl')));
  270. $collection->sort();
  271. $expected = array('alan','betsy','carl','dave');
  272. $this->assertEqual($expected, $collection->to('array'));
  273. // String sort using strcasecmp
  274. $collection = new Collection(array('data' => array('Alan','Dave','betsy','carl')));
  275. $collection->sort('strcasecmp');
  276. $expected = array('Alan','betsy','carl','Dave');
  277. $this->assertEqual($expected, $collection->to('array'));
  278. // Numeric sort using custom function
  279. $collection = new Collection(array('data' => array(5,3,4,1,2)));
  280. $collection->sort(function ($a,$b) {
  281. if ($a == $b) {
  282. return 0;
  283. }
  284. return ($b > $a ? 1 : -1);
  285. });
  286. $expected = array(5,4,3,2,1);
  287. $this->assertEqual($expected, $collection->to('array'));
  288. // Test fail
  289. $collection = new Collection(array('data' => array(5,3,4,1,2)));
  290. $result = $collection->sort('blahgah');
  291. $this->assertEqual($collection->to('array'), $result->to('array'));
  292. }
  293. public function testUnsetInForeach() {
  294. $data = array(
  295. 'Hello',
  296. 'Delete me',
  297. 'Delete me',
  298. 'Delete me',
  299. 'Delete me',
  300. 'Delete me',
  301. 'Hello again!',
  302. 'Delete me'
  303. );
  304. $collection = new Collection(array('data' => $data));
  305. $this->assertIdentical($data, $collection->to('array'));
  306. foreach ($collection as $i => $word) {
  307. if ($word == 'Delete me') {
  308. unset($collection[$i]);
  309. }
  310. }
  311. $expected = array(0 => 'Hello', 6 => 'Hello again!');
  312. $results = $collection->to('array');
  313. $this->assertIdentical($expected, $results);
  314. }
  315. }
  316. ?>