├── .gitignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── composer.json ├── phpunit.xml ├── src └── Collection.php └── tests ├── .gitkeep └── CollectionTest.php /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | composer.phar 3 | composer.lock 4 | .DS_Store -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Collections Change Log 2 | 3 | This project follows [Semantic Versioning](CONTRIBUTING.md). 4 | 5 | ## Proposals 6 | 7 | We do not give estimated times for completion on `Accepted` Proposals. 8 | 9 | - [Accepted](https://github.com/cartalyst/collections/labels/Accepted) 10 | - [Rejected](https://github.com/cartalyst/collections/labels/Rejected) 11 | 12 | --- 13 | 14 | #### v1.1.0 - 2015-03-06 15 | 16 | `ADDED` 17 | 18 | - Added a `sum` method. 19 | - Added a `lists` method. 20 | 21 | #### v1.0.0 - 2015-02-18 22 | 23 | `INIT` 24 | 25 | - Added a Collection class. 26 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution Guide 2 | 3 | This project adheres to the following standards and practices. 4 | 5 | ## Versioning 6 | 7 | This package is versioned under the [Semantic Versioning](http://semver.org/) guidelines as much as possible. 8 | 9 | Releases will be numbered with the following format: 10 | 11 | `..` 12 | 13 | And constructed with the following guidelines: 14 | 15 | * Breaking backward compatibility bumps the major and resets the minor and patch. 16 | * New additions without breaking backward compatibility bumps the minor and resets the patch. 17 | * Bug fixes and misc changes bumps the patch. 18 | 19 | ## Coding Standards 20 | 21 | This package is compliant with the [PSR-1](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md), [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md) and [PSR-4](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md). If you notice any compliance oversights, please send a patch via pull request. 22 | 23 | ## Pull Requests 24 | 25 | The pull request process differs for new features and bugs. 26 | 27 | Pull requests for bugs may be sent without creating any proposal issue. If you believe that you know of a solution for a bug that has been filed, please leave a comment detailing your proposed fix or create a pull request with the fix mentioning that issue id. 28 | 29 | ### Proposal \ Feature Requests 30 | 31 | If you have a proposal or a feature request, you may create an issue with `[Proposal]` in the title. 32 | 33 | The proposal should also describe the new feature, as well as implementation ideas. The proposal will then be reviewed and either approved or denied. Once a proposal is approved, a pull request may be created implementing the new feature. 34 | 35 | ### Which Branch? 36 | 37 | **ALL** bug fixes should be made to the branch which they belong to. Bug fixes should never be sent to the `master` branch unless they fix features that exist only in the upcoming release. 38 | 39 | If a bug is found on a `minor` version `1.1` and it exists on the `major` version `1.0`, the bug fix should be sent to the `1.0` branch which will be afterwards merged into the `1.1` branch. 40 | 41 | > **Note:** Pull requests which do not follow these guidelines will be closed without any further notice. 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The BSD 3-Clause License 2 | Copyright (c) 2011-2015, Cartalyst LLC 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | 7 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | 9 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | 11 | Neither the name of Cartalyst LLC and its libraries nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Collections 2 | 3 | [![Build Status](http://ci.cartalyst.com/build-status/svg/49)](http://ci.cartalyst.com/build-status/view/49) 4 | 5 | A Collections Abstraction library for PHP 6 | 7 | The Collection library is one of the most useful things that many modern languages has, but for some reason PHP doesn't has a built in collection layer. 8 | 9 | The package requires PHP 5.4+ and follows the FIG standards PSR-1, PSR-2 and PSR-4 to ensure a high level of interoperability between shared PHP. 10 | 11 | An open source package by [Cartalyst](https://cartalyst.com), code well, rock on! 12 | 13 | ## Documentation 14 | 15 | Reader-friendly Documentation can be found here. [Collections Manual](https://cartalyst.com/manual/collections). 16 | 17 | Raw files can be found via this projects docs/version branch. 18 | 19 | - [1.1](https://github.com/cartalyst/collections/tree/docs/1.1) 20 | - [1.0](https://github.com/cartalyst/collections/tree/docs/1.0) 21 | 22 | ## Changelog 23 | 24 | Important versions listed below. Refer to the [Changelog](CHANGELOG.md) for a full history of the project. 25 | 26 | - [1.1](CHANGELOG.md) - 2015-03-06 27 | - [1.0](CHANGELOG.md) - 2015-02-18 28 | 29 | ## Support 30 | 31 | The following support channels can be used for contact. 32 | 33 | - [Twitter](https://twitter.com/@cartalyst) 34 | - [Email](mailto:help@cartalyst.com) 35 | 36 | Bug reports, feature requests, and pull requests can be submitted by following our [Contribution Guide](CONTRIBUTING.md). 37 | 38 | ## Contributing & Protocols 39 | 40 | - [Versioning](CONTRIBUTING.md#versioning) 41 | - [Coding Standards](CONTRIBUTING.md#coding-standards) 42 | - [Pull Requests](CONTRIBUTING.md#pull-requests) 43 | 44 | ## License 45 | 46 | This software is released under the [BSD 3-Clause](LICENSE) License. 47 | 48 | © 2011-2015 Cartalyst LLC, All rights reserved. 49 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cartalyst/collections", 3 | "description": "Collection Abstaction library for PHP.", 4 | "keywords": [ 5 | "php", 6 | "cartalyst", 7 | "collections" 8 | ], 9 | "license": "BSD-3-Clause", 10 | "authors": [ 11 | { 12 | "name": "Cartalyst LLC", 13 | "email": "help@cartalyst.com" 14 | }, 15 | { 16 | "name": "Bruno Gaspar", 17 | "email": "bruno.gaspar@cartalyst.com", 18 | "role": "Developer" 19 | }, 20 | { 21 | "name": "Dan Syme", 22 | "email": "dan.syme@cartalyst.com", 23 | "role": "Project Lead" 24 | }, 25 | { 26 | "name": "Suhayb Wardany", 27 | "email": "su.wardany@cartalyst.com", 28 | "role": "Developer" 29 | } 30 | ], 31 | "require": { 32 | "php": ">=5.4.0" 33 | }, 34 | "require-dev": { 35 | "mockery/mockery": "~0.9", 36 | "phpunit/phpunit": "~4.4" 37 | }, 38 | "autoload": { 39 | "psr-4": { 40 | "Cartalyst\\Collections\\": "src/" 41 | } 42 | }, 43 | "extra": { 44 | "component": "package", 45 | "branch-alias": { 46 | "dev-master": "1.0.x-dev" 47 | } 48 | }, 49 | "minimum-stability": "stable" 50 | } 51 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | ./tests/ 16 | 17 | 18 | 19 | 20 | ./src/ 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/Collection.php: -------------------------------------------------------------------------------- 1 | items = $items; 48 | } 49 | 50 | /** 51 | * Create a new collection instance if the value isn't one already. 52 | * 53 | * @param array $items 54 | * @return static 55 | */ 56 | public static function make(array $items = []) 57 | { 58 | return new static($items); 59 | } 60 | 61 | /** 62 | * Get all of the items in the collection. 63 | * 64 | * @return array 65 | */ 66 | public function all() 67 | { 68 | return $this->items; 69 | } 70 | 71 | /** 72 | * Count the number of items in the collection. 73 | * 74 | * @return int 75 | */ 76 | public function count() 77 | { 78 | return count($this->items); 79 | } 80 | 81 | /** 82 | * Get the first item from the collection. 83 | * 84 | * @param \Closure $callback 85 | * @param mixed $default 86 | * @return mixed|null 87 | */ 88 | public function first(Closure $callback = null, $default = null) 89 | { 90 | return count($this->items) > 0 ? reset($this->items) : null; 91 | } 92 | 93 | /** 94 | * Remove an item from the collection by key. 95 | * 96 | * @param mixed $key 97 | * @return void 98 | */ 99 | public function forget($key) 100 | { 101 | $this->offsetUnset($key); 102 | } 103 | 104 | /** 105 | * Get an item from the collection by key. 106 | * 107 | * @param mixed $key 108 | * @param mixed $default 109 | * @return mixed 110 | */ 111 | public function get($key, $default = null) 112 | { 113 | if ($this->offsetExists($key)) { 114 | return $this->items[$key]; 115 | } 116 | 117 | return $default; 118 | } 119 | 120 | /** 121 | * Determine if an item exists in the collection by key. 122 | * 123 | * @param mixed $key 124 | * @return bool 125 | */ 126 | public function has($key) 127 | { 128 | return $this->offsetExists($key); 129 | } 130 | 131 | /** 132 | * Determine if the collection is empty or not. 133 | * 134 | * @return bool 135 | */ 136 | public function isEmpty() 137 | { 138 | return empty($this->items); 139 | } 140 | 141 | /** 142 | * Get the last item from the collection. 143 | * 144 | * @return mixed|null 145 | */ 146 | public function last() 147 | { 148 | return count($this->items) > 0 ? end($this->items) : null; 149 | } 150 | 151 | /** 152 | * Get an array with the values of a given key. 153 | * 154 | * @param string $value 155 | * @return array 156 | */ 157 | public function lists($value) 158 | { 159 | return array_map(function ($item) use ($value) { 160 | return isset($item[$value]) ? $item[$value] : null; 161 | }, $this->items); 162 | } 163 | 164 | /** 165 | * Get and remove the last item from the collection. 166 | * 167 | * @return mixed|null 168 | */ 169 | public function pop() 170 | { 171 | return array_pop($this->items); 172 | } 173 | 174 | /** 175 | * Push an item onto the end of the collection. 176 | * 177 | * @param mixed $value 178 | * @return void 179 | */ 180 | public function push($value) 181 | { 182 | $this->offsetSet(null, $value); 183 | } 184 | 185 | /** 186 | * Pulls an item from the collection. 187 | * 188 | * @param mixed $key 189 | * @param mixed $default 190 | * @return mixed 191 | */ 192 | public function pull($key, $default = null) 193 | { 194 | $value = $this->offsetGet($key); 195 | 196 | $this->offsetUnset($key); 197 | 198 | return $value ?: $default; 199 | } 200 | 201 | /** 202 | * Put an item in the collection by key. 203 | * 204 | * @param mixed $key 205 | * @param mixed $value 206 | * @return void 207 | */ 208 | public function put($key, $value) 209 | { 210 | $this->offsetSet($key, $value); 211 | } 212 | 213 | /** 214 | * Get and remove the first item from the collection. 215 | * 216 | * @return mixed|null 217 | */ 218 | public function shift() 219 | { 220 | return array_shift($this->items); 221 | } 222 | 223 | /** 224 | * Sort through each item with a callback. 225 | * 226 | * @param \Closure $callback 227 | * @return $this 228 | */ 229 | public function sort(Closure $callback) 230 | { 231 | uasort($this->items, $callback); 232 | 233 | return $this; 234 | } 235 | 236 | /** 237 | * Sort the collection using the given Closure. 238 | * 239 | * @param \Closure|string $callback 240 | * @param int $options 241 | * @param bool $descending 242 | * @return $this 243 | */ 244 | public function sortBy($callback, $options = SORT_REGULAR, $descending = false) 245 | { 246 | $results = []; 247 | 248 | if (is_string($callback)) { 249 | $callback = function ($item) use ($callback) { 250 | foreach (explode('.', $callback) as $segment) { 251 | if (is_array($item)) { 252 | if (! array_key_exists($segment, $item)) { 253 | return null; 254 | } 255 | $item = $item[$segment]; 256 | } 257 | } 258 | 259 | return $item; 260 | }; 261 | } 262 | 263 | // First we will loop through the items and get the comparator from a callback 264 | // function which we were given. Then, we will sort the returned values and 265 | // and grab the corresponding values for the sorted keys from this array. 266 | foreach ($this->items as $key => $value) { 267 | $results[$key] = $callback($value); 268 | } 269 | 270 | $descending ? arsort($results, $options) : asort($results, $options); 271 | 272 | // Once we have sorted all of the keys in the array, we will loop through them 273 | // and grab the corresponding model so we can set the underlying items list 274 | // to the sorted version. Then we'll just return the collection instance. 275 | foreach (array_keys($results) as $key) { 276 | $results[$key] = $this->items[$key]; 277 | } 278 | 279 | $this->items = $results; 280 | 281 | return $this; 282 | } 283 | 284 | /** 285 | * Sort the collection in descending order using the given Closure. 286 | * 287 | * @param \Closure|string $callback 288 | * @param int $options 289 | * @return $this 290 | */ 291 | public function sortByDesc($callback, $options = SORT_REGULAR) 292 | { 293 | return $this->sortBy($callback, $options, true); 294 | } 295 | 296 | /** 297 | * Get the sum of the collection items. 298 | * 299 | * @param mixed $callback 300 | * @return mixed 301 | */ 302 | public function sum($callback = null) 303 | { 304 | if (is_null($callback)) { 305 | return array_sum($this->items); 306 | } 307 | 308 | return array_reduce($this->items, function ($result, $item) use ($callback) { 309 | if (is_string($callback)) { 310 | return $result += $item->{$callback}(); 311 | } 312 | 313 | return $result += $callback($item); 314 | }, 0); 315 | } 316 | 317 | /** 318 | * Get the collection of items as a plain array. 319 | * 320 | * @return array 321 | */ 322 | public function toArray() 323 | { 324 | return array_map(function ($value) { 325 | return $value instanceof Arrayable ? $value->toArray() : $value; 326 | 327 | }, $this->items); 328 | } 329 | 330 | /** 331 | * Convert the object into something JSON serializable. 332 | * 333 | * @return array 334 | */ 335 | public function jsonSerialize() 336 | { 337 | return $this->toArray(); 338 | } 339 | 340 | /** 341 | * Get the collection of items as JSON. 342 | * 343 | * @param int $options 344 | * @return string 345 | */ 346 | public function toJson($options = 0) 347 | { 348 | return json_encode($this->toArray(), $options); 349 | } 350 | 351 | /** 352 | * Get an iterator for the items. 353 | * 354 | * @return \ArrayIterator 355 | */ 356 | public function getIterator() 357 | { 358 | return new ArrayIterator($this->items); 359 | } 360 | 361 | /** 362 | * Determine if an item exists at an offset. 363 | * 364 | * @param mixed $key 365 | * @return bool 366 | */ 367 | public function offsetExists($key) 368 | { 369 | return array_key_exists($key, $this->items); 370 | } 371 | 372 | /** 373 | * Get an item at a given offset. 374 | * 375 | * @param mixed $key 376 | * @return mixed 377 | */ 378 | public function offsetGet($key) 379 | { 380 | return $this->items[$key]; 381 | } 382 | 383 | /** 384 | * Set the item at a given offset. 385 | * 386 | * @param mixed $key 387 | * @param mixed $value 388 | * @return void 389 | */ 390 | public function offsetSet($key, $value) 391 | { 392 | if (is_null($key)) { 393 | $this->items[] = $value; 394 | } else { 395 | $this->items[$key] = $value; 396 | } 397 | } 398 | 399 | /** 400 | * Unset the item at a given offset. 401 | * 402 | * @param string $key 403 | * @return void 404 | */ 405 | public function offsetUnset($key) 406 | { 407 | unset($this->items[$key]); 408 | } 409 | 410 | /** 411 | * Dynamically retrieve the value of an item. 412 | * 413 | * @param string $key 414 | * @return mixed 415 | */ 416 | public function __get($key) 417 | { 418 | return $this->get($key); 419 | } 420 | 421 | /** 422 | * Dynamically set the value of an item. 423 | * 424 | * @param string $key 425 | * @param mixed $value 426 | * @return void 427 | */ 428 | public function __set($key, $value) 429 | { 430 | $this->items[$key] = $value; 431 | } 432 | 433 | /** 434 | * Dynamically check if an item is set. 435 | * 436 | * @param string $key 437 | * @return void 438 | */ 439 | public function __isset($key) 440 | { 441 | return isset($this->items[$key]); 442 | } 443 | 444 | /** 445 | * Convert the collection to its string representation. 446 | * 447 | * @return string 448 | */ 449 | public function __toString() 450 | { 451 | return $this->toJson(); 452 | } 453 | 454 | /** 455 | * Dynamically unset an item. 456 | * 457 | * @param string $key 458 | * @return void 459 | */ 460 | public function __unset($key) 461 | { 462 | unset($this->items[$key]); 463 | } 464 | } 465 | -------------------------------------------------------------------------------- /tests/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartalyst/collections/1a457cac7689386ca0fa09ee13e12a2fc9e370c6/tests/.gitkeep -------------------------------------------------------------------------------- /tests/CollectionTest.php: -------------------------------------------------------------------------------- 1 | assertEmpty($collection->all()); 52 | 53 | $collection = new Collection([ 54 | 'foo' => 'Foo', 55 | 'bar' => 'Bar', 56 | ]); 57 | $this->assertEquals([ 58 | 'foo' => 'Foo', 59 | 'bar' => 'Bar', 60 | ], $collection->all()); 61 | } 62 | 63 | /** @test */ 64 | public function it_can_get_the_total_items_from_the_collection() 65 | { 66 | $collection = new Collection; 67 | $this->assertCount(0, $collection); 68 | 69 | $collection = new Collection([ 70 | 'foo' => 'Foo', 71 | 'bar' => 'Bar', 72 | ]); 73 | $this->assertCount(2, $collection); 74 | } 75 | 76 | /** @test */ 77 | public function it_can_check_if_the_collection_has_an_item() 78 | { 79 | $collection = new Collection; 80 | $this->assertFalse($collection->has('foo')); 81 | 82 | $collection = new Collection([ 83 | 'foo' => 'Foo', 84 | 'bar' => 'Bar', 85 | ]); 86 | $this->assertTrue($collection->has('foo')); 87 | } 88 | 89 | /** @test */ 90 | public function it_can_find_an_item_from_the_collection() 91 | { 92 | $collection = new Collection; 93 | $this->assertNull($collection->foo); 94 | 95 | $collection = new Collection([ 96 | 'foo' => 'Foo', 97 | 'bar' => 'Bar', 98 | ]); 99 | $this->assertEquals('Foo', $collection->foo); 100 | } 101 | 102 | /** @test */ 103 | public function it_can_return_the_first_item_from_the_collection() 104 | { 105 | $collection = new Collection([ 106 | 'foo' => 'Foo', 107 | 'bar' => 'Bar', 108 | ]); 109 | 110 | $this->assertEquals('Foo', $collection->first()); 111 | } 112 | 113 | /** @test */ 114 | public function it_can_remove_an_item_from_the_collection() 115 | { 116 | $collection = new Collection([ 117 | 'foo' => 'Foo', 118 | 'bar' => 'Bar', 119 | ]); 120 | $this->assertCount(2, $collection); 121 | $collection->forget('bar'); 122 | $this->assertCount(1, $collection); 123 | } 124 | 125 | /** @test */ 126 | public function it_can_check_that_a_collection_is_empty() 127 | { 128 | $collection = new Collection; 129 | 130 | $this->assertTrue($collection->isEmpty()); 131 | } 132 | 133 | /** @test */ 134 | public function it_can_check_that_a_collection_is_not_empty() 135 | { 136 | $collection = new Collection([ 137 | 'foo' => 'Foo', 138 | 'bar' => 'Bar', 139 | ]); 140 | 141 | $this->assertFalse($collection->isEmpty()); 142 | } 143 | 144 | /** @test */ 145 | public function it_can_return_the_last_item_from_the_collection() 146 | { 147 | $collection = new Collection([ 148 | 'foo' => 'Foo', 149 | 'bar' => 'Bar', 150 | ]); 151 | 152 | $this->assertEquals('Bar', $collection->last()); 153 | } 154 | 155 | /** @test */ 156 | public function it_can_remove_the_last_item_from_the_collection() 157 | { 158 | $collection = new Collection([ 159 | 'foo' => 'Foo', 160 | 'bar' => 'Bar', 161 | 'baz' => 'Baz', 162 | ]); 163 | $this->assertCount(3, $collection); 164 | $this->assertEquals('Baz', $collection->last()); 165 | $collection->pop(); 166 | $this->assertCount(2, $collection); 167 | $this->assertEquals('Bar', $collection->last()); 168 | } 169 | 170 | /** @test */ 171 | public function it_can_push_an_item_to_the_end_of_the_collection() 172 | { 173 | $collection = new Collection([ 174 | 'foo' => 'Foo', 175 | 'bar' => 'Bar', 176 | ]); 177 | $this->assertCount(2, $collection); 178 | $this->assertEquals('Bar', $collection->last()); 179 | $collection->push('Baz'); 180 | $this->assertCount(3, $collection); 181 | $this->assertEquals('Baz', $collection->last()); 182 | } 183 | 184 | /** @test */ 185 | public function it_can_get_and_remove_the_first_item_from_the_collection() 186 | { 187 | $collection = new Collection([ 188 | 'foo' => 'Foo', 189 | 'bar' => 'Bar', 190 | 'baz' => 'Baz', 191 | 'bat' => 'Bat', 192 | ]); 193 | 194 | $this->assertCount(4, $collection); 195 | 196 | $value = $collection->shift(); 197 | $this->assertEquals('Foo', $value); 198 | 199 | $this->assertCount(3, $collection); 200 | } 201 | 202 | /** @test */ 203 | public function it_can_retrieve_the_collection_items_as_an_array() 204 | { 205 | $collection = new Collection([ 206 | 'foo' => 'Foo', 207 | ]); 208 | $this->assertEquals(['foo' => 'Foo'], $collection->toArray()); 209 | } 210 | 211 | /** @test */ 212 | public function it_can_pull_an_item_from_the_collection() 213 | { 214 | $collection = new Collection([ 215 | 'foo' => 'Foo', 216 | 'bar' => 'Bar', 217 | 'baz' => 'Baz', 218 | 'bat' => 'Bat', 219 | ]); 220 | 221 | $this->assertCount(4, $collection); 222 | 223 | $collection->pull('bar'); 224 | 225 | $this->assertCount(3, $collection); 226 | } 227 | 228 | /** @test */ 229 | public function it_can_test_the_offset_methods() 230 | { 231 | $collection = new Collection; 232 | $collection['name'] = 'Foo'; 233 | $this->assertTrue(isset($collection['name'])); 234 | $this->assertEquals('Foo', $collection['name']); 235 | unset($collection['name']); 236 | $this->assertFalse(isset($collection['name'])); 237 | 238 | 239 | $collection = new Collection; 240 | $collection->name = 'Foo'; 241 | $this->assertTrue(isset($collection->name)); 242 | unset($collection->name); 243 | $this->assertFalse(isset($collection->name)); 244 | } 245 | 246 | /** @test */ 247 | public function it_can_sort_the_collection_items() 248 | { 249 | $collection = new Collection; 250 | $collection->put('foo', ['name' => 'Foo']); 251 | $collection->put('bar', ['name' => 'Bar']); 252 | $collection->put('baz', ['name' => 'Baz']); 253 | 254 | $collection->sort(function ($item) { 255 | return $item; 256 | }); 257 | 258 | $this->assertEquals([ 259 | 'foo' => [ 260 | 'name' => 'Foo', 261 | ], 262 | 'bar' => [ 263 | 'name' => 'Bar', 264 | ], 265 | 'baz' => [ 266 | 'name' => 'Baz', 267 | ], 268 | ], $collection->all()); 269 | 270 | $this->assertEquals([ 271 | 'bar' => [ 272 | 'name' => 'Bar', 273 | ], 274 | 'baz' => [ 275 | 'name' => 'Baz', 276 | ], 277 | 'foo' => [ 278 | 'name' => 'Foo', 279 | ], 280 | ], $collection->sortBy('name')->all()); 281 | 282 | $expected = [ 283 | 'foo' => [ 284 | 'name' => 'Foo', 285 | ], 286 | 'baz' => [ 287 | 'name' => 'Baz', 288 | ], 289 | 'bar' => [ 290 | 'name' => 'Bar', 291 | ], 292 | ]; 293 | 294 | $output = $collection->sortByDesc('name')->all(); 295 | 296 | $this->assertEquals($expected, $output); 297 | } 298 | 299 | /** @test */ 300 | public function it_can_serialize_a_collection() 301 | { 302 | $collection = new Collection([ 303 | 'foo' => 'Foo', 304 | 'bar' => 'Bar', 305 | ]); 306 | 307 | $this->assertEquals('{"foo":"Foo","bar":"Bar"}', json_encode($collection)); 308 | } 309 | 310 | /** @test */ 311 | public function it_can_get_the_items_as_a_json_object() 312 | { 313 | $collection = new Collection([ 314 | 'foo' => 'Foo', 315 | 'bar' => 'Bar', 316 | ]); 317 | 318 | $this->assertEquals('{"foo":"Foo","bar":"Bar"}', $collection->toJson()); 319 | } 320 | 321 | /** @test */ 322 | public function it_can_be_iterable() 323 | { 324 | $collection = new Collection([ 325 | 'foo' => 'Foo', 326 | 'bar' => 'Bar', 327 | 'baz' => 'Baz', 328 | 'bat' => 'Bat', 329 | ]); 330 | 331 | foreach ($collection as $item) { 332 | }; 333 | } 334 | 335 | /** @test */ 336 | public function it_can_sum_a_collection() 337 | { 338 | $collection = new Collection([ 339 | 2, 340 | 3, 341 | ]); 342 | 343 | $this->assertEquals(5, $collection->sum()); 344 | } 345 | 346 | /** @test */ 347 | public function it_can_sum_a_collection_by_method_calls() 348 | { 349 | $item1 = m::mock('stdClass'); 350 | $item2 = m::mock('stdClass'); 351 | 352 | $item1->shouldReceive('getValue') 353 | ->once() 354 | ->andReturn(2); 355 | 356 | $item2->shouldReceive('getValue') 357 | ->once() 358 | ->andReturn(3); 359 | 360 | $collection = new Collection([ 361 | $item1, 362 | $item2, 363 | ]); 364 | 365 | $this->assertEquals(5, $collection->sum('getValue')); 366 | } 367 | 368 | /** @test */ 369 | public function it_can_list_items_from_the_collection_using_a_key() 370 | { 371 | $collection = new Collection([ 372 | [ 'id' => 'foo' ], 373 | [ 'id' => 'bar' ], 374 | ]); 375 | 376 | $this->assertEquals([ 'foo', 'bar' ], $collection->lists('id')); 377 | } 378 | } 379 | --------------------------------------------------------------------------------