├── .gitignore
├── .scrutinizer.yml
├── .styleci.yml
├── .travis.yml
├── CHANGELOG.md
├── README.md
├── composer.json
├── docs
├── PHPCollections-Checker.md
├── PHPCollections-Collections-ArrayList.md
├── PHPCollections-Collections-BaseCollection.md
├── PHPCollections-Collections-Dictionary.md
├── PHPCollections-Collections-GenericList.md
├── PHPCollections-Collections-Pair.md
├── PHPCollections-Collections-Stack.md
├── PHPCollections-DataHolder.md
├── PHPCollections-Exceptions-InvalidOperationException.md
├── PHPCollections-Interfaces-CollectionInterface.md
├── PHPCollections-Interfaces-DictionaryInterface.md
├── PHPCollections-Interfaces-MergeableInterface.md
├── PHPCollections-Interfaces-ObjectCollectionInterface.md
├── PHPCollections-Interfaces-SortableInterface.md
└── README.md
├── phpunit.xml
├── src
├── Checker.php
├── Collections
│ ├── ArrayList.php
│ ├── BaseCollection.php
│ ├── Dictionary.php
│ ├── GenericList.php
│ ├── Pair.php
│ └── Stack.php
├── DataHolder.php
├── Exceptions
│ └── InvalidOperationException.php
├── Interfaces
│ ├── CollectionInterface.php
│ ├── DictionaryInterface.php
│ ├── IterableInterface.php
│ ├── MergeableInterface.php
│ ├── ObjectCollectionInterface.php
│ └── SortableInterface.php
└── utils.php
└── tests
└── Unit
├── ArrayListTest.php
├── CheckerTest.php
├── DataHolderTest.php
├── DictionaryTest.php
├── GenericListTest.php
├── InvalidOperationExceptionTest.php
└── StackTest.php
/.gitignore:
--------------------------------------------------------------------------------
1 | vendor/
2 | .vscode/
3 | composer.lock
4 | docs/structure.xml
5 |
--------------------------------------------------------------------------------
/.scrutinizer.yml:
--------------------------------------------------------------------------------
1 | checks:
2 | php:
3 | code_rating: true
4 | duplication: true
5 |
6 | filter:
7 | excluded_paths:
8 | - tests/*
9 |
10 | build:
11 | environment:
12 | php:
13 | version: '7.2'
14 | nodes:
15 | analysis:
16 | tests:
17 | override:
18 | - php-scrutinizer-run
19 | -
20 | command: 'vendor/bin/phpunit --coverage-clover=coverage.clover'
21 | coverage:
22 | file: 'coverage.clover'
23 | format: 'clover'
--------------------------------------------------------------------------------
/.styleci.yml:
--------------------------------------------------------------------------------
1 | preset: recommended
2 |
3 | risky: false
4 |
5 | finder:
6 | name:
7 | - "*.php"
8 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | php:
4 | - '7.2'
5 |
6 | before_script:
7 | - composer install
8 |
9 | script:
10 | - vendor/bin/phpunit --coverage-text --coverage-clover=coverage.xml
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## Version 1.2
4 | - Added `diff` and `slice` methods to `BaseCollection` class.
5 | - Extracted `contains` method from `ArrayList` to `BaseCollection`, now is available on all child classes.
6 | - Removed `find` method from `ArrayList`, `Dictionary`, and `GenericList` classes.
7 | - Removed `search` method from `GenericList` class.
8 | - Updated documentation.
9 |
10 | ## Version 1.3
11 | - Added `equals` method to `BaseCollection` class.
12 | - Added `sum` method to `BaseCollection` class.
13 | - Added `fill` method to `BaseCollection` class.
14 | - Replaced `is_a` native function by `instanceof` operator.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://github.styleci.io/repos/106444310)
2 | [](https://scrutinizer-ci.com/g/maxalmonte14/phpcollections/?branch=master)
3 | [](https://scrutinizer-ci.com/g/maxalmonte14/phpcollections/build-status/master)
4 |
5 | ## About PHPCollections
6 |
7 | PHPCollections is a set of data structures that try to make your life easier when you're working with PHP and large sets of data. Inspired by languages like Java or C#, PHPCollections offers data structures like List, Map, Stack and more, check it out!
8 |
9 | ## Requirements
10 |
11 | ```
12 | PHP >= 7.2
13 | ```
14 |
15 | ## Installation
16 |
17 | ```
18 | composer require "maxalmonte14/phpcollections"
19 | ```
20 |
21 | ## Examples
22 |
23 | Imagine you're storing Post objects for fetching like so.
24 |
25 | ```php
26 | $posts[] = new Post(1, 'PHP 7.2 release notes');
27 | $posts[] = new Post(2, 'New Laravel 5.5 LTS make:factory command');
28 | ```
29 |
30 | Everything is fine! But maybe you made a mistake for some mysterious reason and added a non-Post object.
31 |
32 | ```php
33 | $posts[] = 5 // This is not even an object!
34 | ```
35 |
36 | When you'll try to fetch your posts array you'll be in troubles.
37 |
38 | ```html
39 |
40 |
41 |
42 | = $post->id; ?> |
43 | = $post->title; ?> |
44 |
45 |
46 | ```
47 |
48 | Fortunately PHPCollections exists.
49 |
50 | ```php
51 | $posts = new GenericList(
52 | Post::class,
53 | new Post(1, 'PHP 7.2 release notes'),
54 | new Post(2, 'New Laravel 5.5 LTS make:factory command')
55 | );
56 | $posts->add(5); // An InvalidArgumentException is thrown!
57 | ```
58 |
59 | Of course there exist more flexible data structures like ArrayList.
60 |
61 | ```php
62 | $posts = new ArrayList();
63 | $posts->add(new Post(1, 'PHP 7.2 release notes'));
64 | $posts->add(new Post(2, 'New Laravel 5.5 LTS make:factory command'));
65 | $posts->add(5); // Everything is fine, I need this 5 anyway
66 | ```
67 |
68 | ## Features
69 |
70 | - Different types of collections like Dictionary, Stack and GenericList.
71 | - Simple API.
72 | - Lightweight, no extra packages needed.
73 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "maxalmonte14/phpcollections",
3 | "description": "A set of collections for PHP.",
4 | "keywords": [
5 | "collection",
6 | "php",
7 | "php7",
8 | "php-library",
9 | "collections",
10 | "collection",
11 | "generic",
12 | "arraylist",
13 | "stack",
14 | "dictionary",
15 | "pair"
16 | ],
17 | "license": "MIT",
18 | "support": {
19 | "issues": "https://github.com/maxalmonte14/phpcollections/issues",
20 | "source": "https://github.com/maxalmonte14/phpcollections"
21 | },
22 | "authors": [
23 | {
24 | "name": "Max Almonte",
25 | "email": "maxalmonte14@hotmail.com",
26 | "homepage": "https://www.devalmonte.com"
27 | }
28 | ],
29 | "require": {
30 | "php": "^7.2"
31 | },
32 | "autoload": {
33 | "psr-4": {
34 | "PHPCollections\\": "src/"
35 | },
36 | "files": [
37 | "src/utils.php"
38 | ]
39 | },
40 | "autoload-dev": {
41 | "psr-4": {
42 | "Tests\\": "tests/"
43 | }
44 | },
45 | "require-dev": {
46 | "phpunit/phpunit": "^7.4",
47 | "evert/phpdoc-md": "^0.2.0"
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/docs/PHPCollections-Checker.md:
--------------------------------------------------------------------------------
1 | PHPCollections\Checker
2 | ===============
3 |
4 | An utility class for checking different type of data.
5 |
6 | * Class name: Checker
7 | * Namespace: PHPCollections
8 |
9 | Methods
10 | -------
11 |
12 | ### isEqual
13 |
14 | bool PHPCollections\Checker::isEqual(mixed $firstValue, mixed $secondValue, string $message)
15 |
16 | Checks that two values are equals.
17 |
18 | * Visibility: **public static**
19 |
20 | #### Arguments
21 | * $value **mixed**
22 | * $message **string**
23 |
24 | #### Throws
25 | * **\InvalidArgumentException**
26 |
27 | ### isObject
28 |
29 | bool PHPCollections\Checker::isObject(mixed $value, string $message)
30 |
31 | Checks that a value is and object if not throws an exception.
32 |
33 | * Visibility: **public static**
34 |
35 | #### Arguments
36 | * $value **mixed**
37 | * $message **string**
38 |
39 | #### Throws
40 | * **\InvalidArgumentException**
41 |
42 | ### objectIsOfType
43 |
44 | bool PHPCollections\Checker::objectIsOfType(object $object, string $type, string $message)
45 |
46 | Checks that an object is of the desired type, if not throws an exception.
47 |
48 | * Visibility: **public static**
49 |
50 | #### Arguments
51 | * $object **object**
52 | * $type **string**
53 | * $message **string**
54 |
55 | #### Throws
56 | * **\InvalidArgumentException**
57 |
58 | ### valueIsOfType
59 |
60 | bool PHPCollections\Checker::valueIsOfType(mixed $value, mixed $valueType, string $message)
61 |
62 | Checks that a Dictionary key or value is of the desire type, if not throws an exception.
63 |
64 | * Visibility: **public static**
65 |
66 | #### Arguments
67 | * $value **mixed**
68 | * $valueType **mixed**
69 | * $message **string**
70 |
71 | #### Throws
72 | * **\InvalidArgumentException**
73 |
--------------------------------------------------------------------------------
/docs/PHPCollections-Collections-ArrayList.md:
--------------------------------------------------------------------------------
1 | PHPCollections\Collections\ArrayList
2 | ===============
3 |
4 | A list of values of any type.
5 |
6 | * Class name: ArrayList
7 | * Namespace: PHPCollections\Collections
8 | * This class implements: CollectionInterface, IterableInterface, MergeableInterface, SortableInterface
9 |
10 | Methods
11 | -------
12 |
13 | ### add
14 |
15 | void PHPCollections\Collections\ArrayList::add(mixed $value)
16 |
17 | Adds a new element to the collection.
18 |
19 | * Visibility: **public**
20 |
21 | #### Arguments
22 | * $value **mixed**
23 |
24 | ### diff
25 |
26 | ArrayList PHPCollections\Collections\ArrayList::diff(ArrayList $newArrayList)
27 |
28 | Gets the difference between two ArrayList.
29 |
30 | * Visibility: **public**
31 |
32 | #### Arguments
33 | * $newArrayList **\PHPCollections\Collections\ArrayList**
34 |
35 | #### Throws
36 | * **\PHPCollections\Exceptions\InvalidOperationException**
37 |
38 | ### equals
39 |
40 | boolean PHPCollections\Collections\ArrayList::equals(ArrayList $collection)
41 |
42 | Determines if two ArrayList objects are equal.
43 |
44 | * Visibility: **public**
45 |
46 | #### Arguments
47 | * $collection **\PHPCollections\Collections\ArrayList**
48 |
49 | #### Throws
50 | * **\PHPCollections\Exceptions\InvalidOperationException**
51 |
52 | ### filter
53 |
54 | ?ArrayList PHPCollections\Collections\ArrayList::filter(callable $callback)
55 |
56 | Returns all the coincidences found
57 | for the given callback or null.
58 |
59 | * Visibility: **public**
60 |
61 | #### Arguments
62 | * $callback **callable**
63 |
64 | ### forEach
65 |
66 | void PHPCollections\Collections\ArrayList::forEach(callable $callback)
67 |
68 | Iterates over every element of the collection.
69 |
70 | * Visibility: **public**
71 |
72 | #### Arguments
73 | * $callback **callable**
74 |
75 | ### get
76 |
77 | mixed PHPCollections\Collections\ArrayList::get(integer $offset)
78 |
79 | Gets the element specified
80 | at the given index.
81 |
82 | * Visibility: **public**
83 |
84 | #### Arguments
85 | * $offset **integer**
86 |
87 | ### map
88 |
89 | ?ArrayList PHPCollections\Collections\ArrayList::map(callable $callback)
90 |
91 | Updates elements in the collection by
92 | applying a given callback function.
93 |
94 | * Visibility: **public**
95 |
96 | #### Arguments
97 | * $callback **callable**
98 |
99 | ### merge
100 |
101 | ArrayList PHPCollections\Collections\ArrayList::merge(ArrayList $newArrayList)
102 |
103 | Merges two ArrayList into a new one.
104 |
105 | * Visibility: **public**
106 |
107 | #### Arguments
108 | * $newArrayList **\PHPCollections\Collections\ArrayList**
109 |
110 | ### rand
111 |
112 | mixed PHPCollections\Collections\ArrayList::rand()
113 |
114 | Returns a random element of
115 | the collection.
116 |
117 | * Visibility: **public**
118 |
119 | #### Throws
120 | * **\PHPCollections\Exceptions\InvalidOperationException**
121 |
122 | ### remove
123 |
124 | void PHPCollections\Collections\ArrayList::remove(integer $offset)
125 |
126 | Removes an item from the collection
127 | and repopulates the data array.
128 |
129 | * Visibility: **public**
130 |
131 | #### Arguments
132 | * $offset **integer**
133 |
134 | #### Throws
135 | * **\OutOfRangeException**
136 |
137 | ### reverse
138 |
139 | ArrayList PHPCollections\Collections\ArrayList::reverse()
140 |
141 | Returns a new collection with the
142 | reversed values.
143 |
144 | * Visibility: **public**
145 |
146 | #### Throws
147 | * **\PHPCollections\Exceptions\InvalidOperationException**
148 |
149 | ### slice
150 |
151 | ?ArrayList PHPCollections\Collections\ArrayList::slice(int $offset, ?int $length = null)
152 |
153 | Returns a portion of the ArrayList.
154 |
155 | * Visibility: **public**
156 |
157 | #### Arguments
158 | * $offset **int**
159 | * $length **int**
160 |
161 | ### sort
162 |
163 | ?ArrayList PHPCollections\Collections\ArrayList::sort(callable $callback)
164 |
165 | Returns a new ArrayList with the values ordered by a given callback if couldn't sort returns null.
166 |
167 | * Visibility: **public**
168 |
169 | #### Arguments
170 | * $callback **callable**
171 |
172 | ### update
173 |
174 | bool PHPCollections\Collections\ArrayList::update(integer $index, mixed $value)
175 |
176 | Updates the value of the element
177 | at the given index.
178 |
179 | * Visibility: **public**
180 |
181 | #### Arguments
182 | * $index **integer**
183 | * $value **mixed**
184 |
--------------------------------------------------------------------------------
/docs/PHPCollections-Collections-BaseCollection.md:
--------------------------------------------------------------------------------
1 | PHPCollections\Collections\BaseCollection
2 | ===============
3 |
4 | The base class for countable and
5 | JSON serializable collections.
6 |
7 | * Class name: BaseCollection
8 | * Namespace: PHPCollections\Collections
9 | * This is an **abstract** class
10 | * This class implements: Countable, JsonSerializable
11 |
12 | Properties
13 | ----------
14 |
15 | ### $dataHolder
16 |
17 | protected \PHPCollections\DataHolder $dataHolder
18 |
19 | The data container.
20 |
21 | * Visibility: **protected**
22 |
23 | Methods
24 | -------
25 |
26 | ### __construct
27 |
28 | void PHPCollections\Collections\BaseCollection::__construct(array $data)
29 |
30 | Initializes the dataHolder property.
31 |
32 | * Visibility: **public**
33 |
34 | #### Arguments
35 | * $data **array**
36 |
37 | ### clear
38 |
39 | void PHPCollections\Collections\BaseCollection::clear()
40 |
41 | Reinitializes the dataHolder property.
42 |
43 | * Visibility: **public**
44 |
45 | ### contains
46 |
47 | boolean PHPCollections\Collections\ArrayList::contains(mixed $needle)
48 |
49 | Checks if the collection
50 | contains a given value.
51 |
52 | * Visibility: **public**
53 |
54 | #### Arguments
55 | * $needle **mixed**
56 |
57 | ### count
58 |
59 | integer PHPCollections\Collections\BaseCollection::count()
60 |
61 | Returns the length of the collection.
62 |
63 | * Visibility: **public**
64 |
65 | ### diff
66 |
67 | Basecollection PHPCollections\Collections\BaseCollection::diff(Basecollection $collection)
68 |
69 | Gets the difference between two collections.
70 |
71 | * Visibility: **public abstract**
72 |
73 | #### Arguments
74 | * $collection **\PHPCollections\Collections\BaseCollection**
75 |
76 | ### exists
77 |
78 | boolean PHPCollections\Collections\BaseCollection::exists(mixed $offset)
79 |
80 | Checks if the given index
81 | exists in the collection.
82 |
83 | * Visibility: **public**
84 |
85 | ### equals
86 |
87 | boolean PHPCollections\Collections\BaseCollection::equals(BaseCollection $collection)
88 |
89 | Determines if two collections are equal.
90 |
91 | * Visibility: **public abstract**
92 |
93 | #### Arguments
94 | * $collection **\PHPCollections\Collections\BaseCollection**
95 |
96 | ### fill
97 |
98 | void PHPCollections\Collections\BaseCollection::fill()
99 |
100 | Fills the collection with a set of data.
101 |
102 | * Visibility: **public**
103 |
104 | ### first
105 |
106 | mixed PHPCollections\Collections\BaseCollection::first()
107 |
108 | Gets the first element in the collection.
109 |
110 | * Visibility: **public**
111 |
112 | #### Throws
113 | **\OutOfRangeException**
114 |
115 | ### isEmpty
116 |
117 | boolean PHPCollections\Collections\BaseCollection::isEmpty()
118 |
119 | Checks if the collection is empty.
120 |
121 | * Visibility: **public**
122 |
123 | #### Throws
124 | **\OutOfRangeException**
125 |
126 | ### jsonSerialize
127 |
128 | array PHPCollections\Collections\BaseCollection::jsonSerialize()
129 |
130 | Defines the behavior of the collection
131 | when json_encode is called.
132 |
133 | * Visibility: **public**
134 |
135 | ### last
136 |
137 | mixed PHPCollections\Collections\BaseCollection::last()
138 |
139 | Gets the last element in the collection.
140 |
141 | * Visibility: **public**
142 |
143 | ### toArray
144 |
145 | array PHPCollections\Collections\BaseCollection::toArray()
146 |
147 | Returns a plain array with
148 | your dictionary data.
149 |
150 | * Visibility: **public**
151 |
152 | ### slice
153 |
154 | ?BaseCollection PHPCollections\Collections\BaseCollection::slice(int $offset, ?int $length = null)
155 |
156 | Returns a portion of the collection.
157 |
158 | * Visibility: **public abstract**
159 |
160 | #### Arguments
161 | * $offset **int**
162 | * $length **int**
163 |
164 | ### sum
165 |
166 | float PHPCollections\Collections\BaseCollection::sum(callable $callback)
167 |
168 | Returns the sum of a set of values.
169 |
170 | * Visibility: **public**
171 |
172 | #### Arguments
173 | * $callback **callable**
174 |
175 | #### Throws
176 | **\OutOfRangeException**
--------------------------------------------------------------------------------
/docs/PHPCollections-Collections-Dictionary.md:
--------------------------------------------------------------------------------
1 | PHPCollections\Collections\Dictionary
2 | ===============
3 |
4 | A Pair object collection
5 | represented by a generic
6 | type key and value.
7 |
8 | * Class name: Dictionary
9 | * Namespace: PHPCollections\Collections
10 | * This class extends: BaseCollection
11 | * This class implements: DictionaryInterface, MergeableInterface, SortableInterface
12 |
13 | Properties
14 | ----------
15 |
16 | ### $keyType
17 |
18 | private mixed $keyType
19 |
20 | The type of the keys
21 | for this dictionary.
22 |
23 | * Visibility: **private**
24 |
25 | ### $valueType
26 |
27 | private mixed $valueType
28 |
29 | The type of the values
30 | for this dictionary.
31 |
32 | * Visibility: **private**
33 |
34 | Methods
35 | -------
36 |
37 | ### __construct
38 |
39 | void PHPCollections\Collections\Dictionary::__construct(mixed $keyType, mixed $valueType, array $data = [])
40 |
41 | Creates a new Dictionary.
42 |
43 | * Visibility: **public**
44 |
45 | #### Arguments
46 | * $keyType **mixed**
47 | * $valueType **mixed**
48 | * $data **array**
49 |
50 | #### Throws
51 | * **\InvalidArgumentException**
52 |
53 | ### add
54 |
55 | void PHPCollections\Collections\Dictionary::add(mixed $key, mixed $value)
56 |
57 | Adds a new value to the dictionary.
58 |
59 | * Visibility: **public**
60 |
61 | #### Arguments
62 | * $key **mixed**
63 | * $value **mixed**
64 |
65 | #### Throws
66 | * **\InvalidArgumentException**
67 |
68 | ### diff
69 |
70 | Dictionary PHPCollections\Collections\Dictionary::diff(Dictionary $newDictionary)
71 |
72 | Gets the difference between two Dictionary.
73 |
74 | * Visibility: **public**
75 |
76 | #### Arguments
77 | * $newDictionary **\PHPCollections\Collections\Dictionary**
78 |
79 | #### Throws
80 | * **\PHPCollections\Exceptions\InvalidOperationException**
81 |
82 | ### equals
83 |
84 | boolean PHPCollections\Collections\Dictionary::equals(Dictionary $collection)
85 |
86 | Determines if two Dictionary objects are equal.
87 |
88 | * Visibility: **public**
89 |
90 | #### Arguments
91 | * $collection **\PHPCollections\Collections\Dictionary**
92 |
93 | #### Throws
94 | * **\PHPCollections\Exceptions\InvalidOperationException**
95 |
96 | ### filter
97 |
98 | ?Dictionary PHPCollections\Collections\Dictionary::filter(callable $callback)
99 |
100 | Filters the collection applying
101 | a given callback.
102 |
103 | * Visibility: **public**
104 |
105 | #### Arguments
106 | * $callback **callable**
107 |
108 | ### forEach
109 |
110 | void PHPCollections\Collections\Dictionary::forEach(callable $callback)
111 |
112 | Iterates over every element of the collection.
113 |
114 | * Visibility: **public**
115 |
116 | #### Arguments
117 | * $callback **callable**
118 |
119 | ### get
120 |
121 | ?mixed PHPCollections\Collections\Dictionary::get(mixed $key)
122 |
123 | Returns the value for the specified
124 | key or null if it's not defined.
125 |
126 | * Visibility: **public**
127 |
128 | #### Arguments
129 | * $key **mixed**
130 |
131 | ### getKeyType
132 |
133 | mixed PHPCollections\Collections\Dictionary::getKeyType()
134 |
135 | Returns the key type for this collection.
136 |
137 | * Visibility: **public**
138 |
139 | ### getValueType
140 |
141 | mixed PHPCollections\Collections\Dictionary::getValueType()
142 |
143 | Returns the key value for this collection.
144 |
145 | * Visibility: **public**
146 |
147 | ### initializePairs
148 |
149 | void PHPCollections\Collections\Dictionary::initializePairs(array $data)
150 |
151 | Populates the container with Pair objects.
152 |
153 | * Visibility: **private**
154 |
155 | #### Arguments
156 | * $data **array**
157 |
158 | ### map
159 |
160 | ?Dictionary PHPCollections\Collections\Dictionary::map(callable $callback)
161 |
162 | Updates elements in the collection by
163 | applying a given callback function.
164 |
165 | * Visibility: **public**
166 |
167 | #### Arguments
168 | * $callback **callable**
169 |
170 | ### merge
171 |
172 | Dictionary PHPCollections\Collections\Dictionary::merge(Dictionary $newDictionary)
173 |
174 | Merges two dictionaries into a new one.
175 |
176 | * Visibility: **public**
177 |
178 | #### Arguments
179 | * $newDictionary **PHPCollections\Collections\Dictionary**
180 |
181 | #### Throws
182 | * **\InvalidArgumentException**
183 |
184 | ### remove
185 |
186 | boolean PHPCollections\Collections\Dictionary::remove(mixed key)
187 |
188 | Removes a value from the dictionary.
189 |
190 | * Visibility: **public**
191 |
192 | #### Arguments
193 | * $key **mixed**
194 |
195 | ### slice
196 |
197 | ?Dictionary PHPCollections\Collections\Dictionary::slice(int $offset, ?int $length = null)
198 |
199 | Returns a portion of the Dictionary.
200 |
201 | * Visibility: **public**
202 |
203 | #### Arguments
204 | * $offset **int**
205 | * $length **int**
206 |
207 | ### sort
208 |
209 | ?Dictionary PHPCollections\Collections\Dictionary::sort(callable $callback)
210 |
211 | Returns a new Dictionary with the values ordered by a given callback if couldn't sort returns null.
212 |
213 | * Visibility: **public**
214 |
215 | #### Arguments
216 | * $callback **callable**
217 |
218 | ### toArray
219 |
220 | array PHPCollections\Collections\Dictionary::toArray()
221 |
222 | Returns an array representation
223 | of your dictionary data.
224 |
225 | * Visibility: **public**
226 |
227 | ### toJson
228 |
229 | string PHPCollections\Collections\Dictionary::toJson()
230 |
231 | Returns a JSON representation
232 | of your dictionary data.
233 |
234 | * Visibility: **public**
235 |
236 | #### Arguments
237 | * $key **mixed**
238 | * $value **mixed**
239 |
240 | ### update
241 |
242 | boolean PHPCollections\Collections\Dictionary::update(mixed $key, mixed $value)
243 |
244 | Updates the value of one Pair
245 | in the collection.
246 |
247 | * Visibility: **public**
248 |
249 | #### Arguments
250 | * $key **mixed**
251 | * $value **mixed**
252 |
253 | #### Throws
254 | * **\InvalidArgumentException**
255 | * **\PHPCollections\Exceptions\InvalidOperationException**
256 |
257 | ### validateEntry
258 |
259 | boolean PHPCollections\Collections\Dictionary::validateEntry(mixed $key, mixed $value)
260 |
261 | Validates that a key and value are of the specified types in the class.
262 |
263 | * Visibility: **private**
264 |
265 | #### Arguments
266 | * $key **mixed**
267 | * $value **mixed**
268 |
269 | #### Throws
270 | * **\InvalidArgumentException**
--------------------------------------------------------------------------------
/docs/PHPCollections-Collections-GenericList.md:
--------------------------------------------------------------------------------
1 | PHPCollections\Collections\GenericList
2 | ===============
3 |
4 | A list for a generic type of data.
5 |
6 | * Class name: GenericList
7 | * Namespace: PHPCollections\Collections
8 | * This class extends: BaseCollection
9 | * This class implements: ObjectCollectionInterface, IterableInterface, MergeableInterface,SortableInterface
10 |
11 | Properties
12 | ----------
13 |
14 | ### $error
15 |
16 | private string $error
17 |
18 | The error message to show when someone try to store a value of a different type than the specified in the type property.
19 |
20 | * Visibility: **private**
21 |
22 | ### $type
23 |
24 | private string $type
25 |
26 | The type of data that
27 | will be stored.
28 |
29 | * Visibility: **private**
30 |
31 | Methods
32 | -------
33 |
34 | ### __construct
35 |
36 | void PHPCollections\Collections\GenericList::__construct(string $type, object ...$data)
37 |
38 | Creates a new GenericList.
39 |
40 | * Visibility: **public**
41 |
42 | #### Arguments
43 | * $type **string**
44 | * $data **object ...**
45 |
46 | #### Throws
47 | * **\InvalidArgumentException**
48 |
49 | ### add
50 |
51 | void PHPCollections\Collections\GenericList::add(mixed $value)
52 |
53 | Adds a new object to the collection.
54 |
55 | * Visibility: **public**
56 |
57 | #### Arguments
58 | * $value **mixed**
59 |
60 | #### Throws
61 | * **\InvalidArgumentException**
62 |
63 | ### diff
64 |
65 | GenericList PHPCollections\Collections\GenericList::diff(GenericList $newGenericList)
66 |
67 | Gets the difference between two GenericList.
68 |
69 | * Visibility: **public**
70 |
71 | #### Arguments
72 | * $newGenericList **\PHPCollections\Collections\GenericList**
73 |
74 | #### Throws
75 | * **\PHPCollections\Exceptions\InvalidOperationException**
76 |
77 | ### equals
78 |
79 | boolean PHPCollections\Collections\GenericList::equals(GenericList $collection)
80 |
81 | Determines if two GenericList objects are equal.
82 |
83 | * Visibility: **public**
84 |
85 | #### Arguments
86 | * $collection **\PHPCollections\Collections\GenericList**
87 |
88 | #### Throws
89 | * **\PHPCollections\Exceptions\InvalidOperationException**
90 |
91 | ### filter
92 |
93 | ?GenericList PHPCollections\Collections\GenericList::filter(callable $callback)
94 |
95 | Returns all the coincidences found
96 | for the given callback or null.
97 |
98 | * Visibility: **public**
99 |
100 | #### Arguments
101 | * $callback **callable**
102 |
103 | ### forEach
104 |
105 | void PHPCollections\Collections\GenericList::forEach(callable $callback)
106 |
107 | Iterates over every element of the collection.
108 |
109 | * Visibility: **public**
110 |
111 | #### Arguments
112 | * $callback **callable**
113 |
114 | ### get
115 |
116 | ?object PHPCollections\Collections\GenericList::get(int $offset)
117 |
118 | Returns the object at the specified index
119 | or null if it's not defined.
120 |
121 | * Visibility: **public**
122 |
123 | #### Arguments
124 | * $offset **int**
125 |
126 | #### Throws
127 | * **\OutOfRangeException**
128 |
129 | ### map
130 |
131 | ?GenericList PHPCollections\Collections\GenericList::map(callable $callback)
132 |
133 | Updates elements in the collection by
134 | applying a given callback function.
135 |
136 | * Visibility: **public**
137 |
138 | #### Arguments
139 | * $callback **callable**
140 |
141 | ### merge
142 |
143 | GenericList PHPCollections\Collections\GenericList::merge(GenericList $newGenericList)
144 |
145 | Merges two GenericList into a new one.
146 |
147 | * Visibility: **public**
148 |
149 | #### Arguments
150 | * $data **\PHPCollections\Collections\GenericList**
151 |
152 | #### Throws
153 | * **\InvalidArgumentException**
154 |
155 | ### rand
156 |
157 | mixed PHPCollections\Collections\GenericList::rand()
158 |
159 | Returns a random element from
160 | the collection.
161 |
162 | * Visibility: **public**
163 |
164 | ### remove
165 |
166 | bool PHPCollections\Collections\GenericList::remove(int $offset)
167 |
168 | Removes an item from the collection
169 | and repopulate the data container.
170 |
171 | * Visibility: **public**
172 |
173 | #### Arguments
174 | * $offset **int**
175 |
176 | #### Throws
177 | * **\OutOfRangeException**
178 |
179 | ### repopulate
180 |
181 | void PHPCollections\Collections\GenericList::repopulate()
182 |
183 | Repopulates the data container.
184 |
185 | * Visibility: **private**
186 |
187 | ### reverse
188 |
189 | GenericList PHPCollections\Collections\GenericList::reverse()
190 |
191 | Returns a new collection with the
192 | reversed values.
193 |
194 | * Visibility: **public**
195 |
196 | #### Throws
197 | * **\PHPCollections\Exceptions\InvalidOperationException**
198 |
199 | ### slice
200 |
201 | ?GenericList PHPCollections\Collections\GenericList::slice(int $offset, ?int $length = null)
202 |
203 | Returns a portion of the GenericList.
204 |
205 | * Visibility: **public**
206 |
207 | #### Arguments
208 | * $offset **int**
209 | * $length **int**
210 |
211 | ### sort
212 |
213 | ?GenericList PHPCollections\Collections\GenericList::sort(callable $callback)
214 |
215 | Returns a new GenericList with the values ordered by a given callback if couldn't sort returns null.
216 |
217 | * Visibility: **public**
218 |
219 | #### Arguments
220 | * $callback **callable**
221 |
222 | ### update
223 |
224 | bool PHPCollections\Collections\GenericList::update(integer $index, mixed $value)
225 |
226 | Updates the value of the element
227 | at the given index.
228 |
229 | * Visibility: **public**
230 |
231 | #### Arguments
232 | * $index **integer**
233 | * $value **mixed**
234 |
235 | #### Throws
236 | * **\PHPCollections\Exceptions\InvalidOperationException**
237 | * **\InvalidArgumentException**
238 |
--------------------------------------------------------------------------------
/docs/PHPCollections-Collections-Pair.md:
--------------------------------------------------------------------------------
1 | PHPCollections\Collections\Pair
2 | ===============
3 |
4 | A simple key / value pair
5 | object representation.
6 |
7 | * Class name: Pair
8 | * Namespace: PHPCollections\Collections
9 |
10 | Properties
11 | ----------
12 |
13 | ### $key
14 |
15 | private mixed $key
16 |
17 | The key for the Pair object.
18 |
19 | * Visibility: **private**
20 |
21 | ### $value
22 |
23 | private mixed $value
24 |
25 | The value for the Pair object.
26 |
27 | * Visibility: **private**
28 |
29 | Methods
30 | -------
31 |
32 | ### __construct
33 |
34 | void PHPCollections\Collections\Pair::__construct(mixed $key, mixed $value)
35 |
36 | Initializes class properties.
37 |
38 | * Visibility: **public**
39 |
40 | #### Arguments
41 | * $key **mixed**
42 | * $value **mixed**
43 |
44 | ### __get
45 |
46 | mixed PHPCollections\Collections\Pair::__get(string $name)
47 |
48 | Allows access to the key
49 | property by its value.
50 |
51 | * Visibility: **public**
52 |
53 | #### Arguments
54 | * $name **string**
55 |
56 | ### getKey
57 |
58 | mixed PHPCollections\Collections\Pair::getKey()
59 |
60 | Returns the key property.
61 |
62 | * Visibility: **public**
63 |
64 | ### getValue
65 |
66 | mixed PHPCollections\Collections\Pair::getValue()
67 |
68 | Returns the value property.
69 |
70 | * Visibility: **public**
71 |
72 | ### setValue
73 |
74 | void PHPCollections\Collections\Pair::setValue(mixed $value)
75 |
76 | Sets the value of the value property.
77 |
78 | * Visibility: **public**
79 |
80 | #### Arguments
81 | * $value **mixed**
82 |
--------------------------------------------------------------------------------
/docs/PHPCollections-Collections-Stack.md:
--------------------------------------------------------------------------------
1 | PHPCollections\Collections\Stack
2 | ===============
3 |
4 | A generic LIFO Stack.
5 |
6 | * Class name: Stack
7 | * Namespace: PHPCollections\Collections
8 | * This class implements: Countable
9 |
10 | Properties
11 | ----------
12 |
13 | ### $data
14 |
15 | private array $data
16 |
17 | The data container.
18 |
19 | * Visibility: **private**
20 |
21 | ### $type
22 |
23 | private mixed $type
24 |
25 | The type of the values
26 | for this Stack.
27 |
28 | * Visibility: **private**
29 |
30 | Methods
31 | -------
32 |
33 | ### __construct
34 |
35 | void PHPCollections\Collections\Stack::__construct(string $type)
36 |
37 | Creates a new Stack.
38 |
39 | * Visibility: **public**
40 |
41 | #### Arguments
42 | * $type **string**
43 |
44 | ### clear
45 |
46 | void PHPCollections\Collections\Stack::clear()
47 |
48 | Clears the data values.
49 |
50 | * Visibility: **public**
51 |
52 | ### count
53 |
54 | int PHPCollections\Collections\Stack::count()
55 |
56 | Returns the length of the Stack.
57 |
58 | * Visibility: **public**
59 |
60 | ### isEmpty
61 |
62 | bool PHPCollections\Collections\Stack::isEmpty()
63 |
64 | Checks if the stack is empty.
65 |
66 | * Visibility: **public**
67 |
68 | ### peek
69 |
70 | mixed PHPCollections\Collections\Stack::peek()
71 |
72 | Gets the element at
73 | the end of the Stack.
74 |
75 | * Visibility: **public**
76 |
77 | ### pop
78 |
79 | mixed PHPCollections\Collections\Stack::pop()
80 |
81 | Pops the element at
82 | the end of the stack.
83 |
84 | * Visibility: **public**
85 |
86 | ### push
87 |
88 | mixed PHPCollections\Collections\Stack::push(mixed $value)
89 |
90 | Adds a new element at
91 | the end of the Stack.
92 |
93 | * Visibility: **public**
94 |
95 | #### Arguments
96 | * $value **mixed**
97 |
98 | #### Throws
99 | * **\InvalidArgumentException**
100 |
--------------------------------------------------------------------------------
/docs/PHPCollections-DataHolder.md:
--------------------------------------------------------------------------------
1 | PHPCollections\DataHolder
2 | ===============
3 |
4 | A class for storing and managing data.
5 |
6 | * Class name: DataHolder
7 | * Namespace: PHPCollections
8 | * This class implements: ArrayAccess, IteratorAggregate
9 |
10 | Properties
11 | ----------
12 |
13 | ### $container
14 |
15 | private array $container
16 |
17 | The array for storing data.
18 |
19 | * Visibility: **private**
20 |
21 | Methods
22 | -------
23 |
24 | ### __construct
25 |
26 | void PHPCollections\DataHolder::__construct(array $data)
27 |
28 | Initializes the container property.
29 |
30 | * Visibility: **public**
31 |
32 | #### Arguments
33 | * $data **array**
34 |
35 | ### getContainer
36 |
37 | array PHPCollections\DataHolder::getContainer()
38 |
39 | Returns the container array.
40 |
41 | * Visibility: **public**
42 |
43 | ### getIterator
44 |
45 | \ArrayIterator PHPCollections\DataHolder::getIterator()
46 |
47 | Returns an array iterator for
48 | the container property.
49 |
50 | * Visibility: **public**
51 |
52 | ### offsetExists
53 |
54 | boolean PHPCollections\DataHolder::offsetExists(mixed $offset)
55 |
56 | Checks if an offset exists in the container.
57 |
58 | * Visibility: **public**
59 |
60 | #### Arguments
61 | * $offset **mixed**
62 |
63 | ### offsetGet
64 |
65 | ?mixed PHPCollections\DataHolder::offsetGet(mixed $offset)
66 |
67 | Gets a value from the container.
68 |
69 | * Visibility: **public**
70 |
71 | #### Arguments
72 | * $offset **mixed**
73 |
74 | ### offsetSet
75 |
76 | void PHPCollections\DataHolder::offsetSet(mixed $offset, mixed $value)
77 |
78 | Sets a value into the container.
79 |
80 | * Visibility: **public**
81 |
82 | #### Arguments
83 | * $offset **mixed**
84 | * $value **mixed**
85 |
86 | ### offsetUnset
87 |
88 | void PHPCollections\DataHolder::offsetUnset(mixed $offset)
89 |
90 | Unsets an offset from the container.
91 |
92 | * Visibility: **public**
93 |
94 | #### Arguments
95 | * $offset **mixed**
96 |
97 | ### setContainer
98 |
99 | void PHPCollections\DataHolder::setContainer(array $data)
100 |
101 | Sets the container array.
102 |
103 | * Visibility: **public**
104 |
105 | #### Arguments
106 | * $data **array**
107 |
--------------------------------------------------------------------------------
/docs/PHPCollections-Exceptions-InvalidOperationException.md:
--------------------------------------------------------------------------------
1 | PHPCollections\Exceptions\InvalidOperationException
2 | ===============
3 |
4 | An Exception for representing
5 | invalid operations with collections.
6 |
7 | * Class name: InvalidOperationException
8 | * Namespace: PHPCollections\Exceptions
9 | * Parent class: Exception
10 |
11 | Methods
12 | -------
13 |
14 | ### __toString
15 |
16 | string PHPCollections\Exceptions\InvalidOperationException::__toString()
17 |
18 | Returns the string representation
19 | of the Exception.
20 |
21 | * Visibility: **public**
22 |
--------------------------------------------------------------------------------
/docs/PHPCollections-Interfaces-CollectionInterface.md:
--------------------------------------------------------------------------------
1 | PHPCollections\Interfaces\CollectionInterface
2 | ===============
3 |
4 | * Interface name: CollectionInterface
5 | * Namespace: PHPCollections\Interfaces
6 | * This is an **interface**
7 |
8 | Methods
9 | -------
10 |
11 | ### add
12 |
13 | void PHPCollections\Interfaces\CollectionInterface::add(mixed $value)
14 |
15 | * Visibility: **public**
16 |
17 | #### Arguments
18 | * $value **mixed**
19 |
20 |
21 |
22 | ### get
23 |
24 | mixed PHPCollections\Interfaces\CollectionInterface::get(int $offset)
25 |
26 | * Visibility: **public**
27 |
28 | #### Arguments
29 | * $offset **int**
30 |
31 | ### remove
32 |
33 | void PHPCollections\Interfaces\CollectionInterface::remove(int $offset)
34 |
35 | * Visibility: **public**
36 |
37 | #### Arguments
38 | * $offset **int**
39 |
40 | ### update
41 |
42 | bool PHPCollections\Interfaces\CollectionInterface::update(int $offset, mixed $value)
43 |
44 | * Visibility: **public**
45 |
46 | #### Arguments
47 | * $offset **int**
48 | * $value **mixed**
49 |
--------------------------------------------------------------------------------
/docs/PHPCollections-Interfaces-DictionaryInterface.md:
--------------------------------------------------------------------------------
1 | PHPCollections\Interfaces\DictionaryInterface
2 | ===============
3 |
4 | * Interface name: DictionaryInterface
5 | * Namespace: PHPCollections\Interfaces
6 | * This is an **interface**
7 |
8 | Methods
9 | -------
10 |
11 | ### add
12 |
13 | void PHPCollections\Interfaces\DictionaryInterface::add($key, $value)
14 |
15 | * Visibility: **public**
16 |
17 | #### Arguments
18 | * $key **mixed**
19 | * $value **mixed**
20 |
21 | ### get
22 |
23 | mixed PHPCollections\Interfaces\DictionaryInterface::get($key)
24 |
25 | * Visibility: **public**
26 |
27 | #### Arguments
28 | * $key **mixed**
29 |
30 | ### remove
31 |
32 | bool PHPCollections\Interfaces\DictionaryInterface::remove($key)
33 |
34 | * Visibility: **public**
35 |
36 | #### Arguments
37 | * $key **mixed**
38 |
39 | ### update
40 |
41 | bool PHPCollections\Interfaces\DictionaryInterface::update($key, $value)
42 |
43 | * Visibility: **public**
44 |
45 | #### Arguments
46 | * $key **mixed**
47 | * $value **mixed**
48 |
--------------------------------------------------------------------------------
/docs/PHPCollections-Interfaces-MergeableInterface.md:
--------------------------------------------------------------------------------
1 | PHPCollections\Interfaces\MergeableInterface
2 | ===============
3 |
4 | * Interface name: MergeableInterface
5 | * Namespace: PHPCollections\Interfaces
6 | * This is an **interface**
7 |
8 | Methods
9 | -------
10 |
11 | ### merge
12 |
13 | BaseCollection PHPCollections\Interfaces\MergeableInterface::merge(BaseCollection $collection)
14 |
15 | * Visibility: **public**
16 |
17 | #### Arguments
18 | * $collection **PHPCollections\Collections\BaseCollection**
19 |
--------------------------------------------------------------------------------
/docs/PHPCollections-Interfaces-ObjectCollectionInterface.md:
--------------------------------------------------------------------------------
1 | PHPCollections\Interfaces\ObjectCollectionInterface
2 | ===============
3 |
4 | * Interface name: ObjectCollectionInterface
5 | * Namespace: PHPCollections\Interfaces
6 | * This is an **interface**
7 |
8 | Methods
9 | -------
10 |
11 | ### add
12 |
13 | void PHPCollections\Interfaces\ObjectCollectionInterface::add(object $value)
14 |
15 | * Visibility: **public**
16 |
17 | #### Arguments
18 | * $value **object**
19 |
20 |
21 |
22 | ### get
23 |
24 | object PHPCollections\Interfaces\ObjectCollectionInterface::get(int $offset)
25 |
26 | * Visibility: **public**
27 |
28 | #### Arguments
29 | * $offset **int**
30 |
31 | ### remove
32 |
33 | void PHPCollections\Interfaces\ObjectCollectionInterface::remove(int $offset)
34 |
35 | * Visibility: **public**
36 |
37 | #### Arguments
38 | * $offset **int**
39 |
40 | ### update
41 |
42 | bool PHPCollections\Interfaces\ObjectCollectionInterface::update(int $offset, object $value)
43 |
44 | * Visibility: **public**
45 |
46 | #### Arguments
47 | * $offset **int**
48 | * $value **object**
49 |
--------------------------------------------------------------------------------
/docs/PHPCollections-Interfaces-SortableInterface.md:
--------------------------------------------------------------------------------
1 | PHPCollections\Interfaces\SortableInterface
2 | ===============
3 |
4 | * Interface name: SortableInterface
5 | * Namespace: PHPCollections\Interfaces
6 | * This is an **interface**
7 |
8 | Methods
9 | -------
10 |
11 | ### sort
12 |
13 | bool PHPCollections\Interfaces\SortableInterface::sort(callable $callback)
14 |
15 | * Visibility: **public**
16 |
17 | #### Arguments
18 | * $callback **callable**
19 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | Package Index
2 | =========
3 |
4 | * PHPCollections
5 | * PHPCollections\Exceptions
6 | * [InvalidOperationException](PHPCollections-Exceptions-InvalidOperationException.md)
7 | * PHPCollections\Interfaces
8 | * [CollectionInterface](PHPCollections-Interfaces-CollectionInterface.md)
9 | * [DictionaryInterface](PHPCollections-Interfaces-DictionaryInterface.md)
10 | * [MergeableInterface](PHPCollections-Interfaces-MergeableInterface.md)
11 | * [ObjectCollectionInterface](PHPCollections-Interfaces-ObjectCollectionInterface.md)
12 | * [SortableInterface](PHPCollections-Interfaces-SortableInterface.md)
13 | * PHPCollections\Collections
14 | * [ArrayList](PHPCollections-Collections-ArrayList.md)
15 | * [BaseCollection](PHPCollections-Collections-BaseCollection.md)
16 | * [Dictionary](PHPCollections-Collections-Dictionary.md)
17 | * [GenericList](PHPCollections-Collections-GenericList.md)
18 | * [Pair](PHPCollections-Collections-Pair.md)
19 | * [Stack](PHPCollections-Collections-Stack.md)
20 | * [Checker](PHPCollections-Checker.md)
21 | * [DataHolder](PHPCollections-DataHolder.md)
22 |
23 |
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 | ./tests/Unit
14 |
15 |
16 |
17 |
18 | ./src
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/Checker.php:
--------------------------------------------------------------------------------
1 | toArray();
29 |
30 | array_push($data, $value);
31 | $this->dataHolder->setContainer($data);
32 | }
33 |
34 | /**
35 | * Gets the difference between two ArrayList.
36 | *
37 | * @param \PHPCollections\Collections\ArrayList $newArrayList
38 | *
39 | * @throws \PHPCollections\Exceptions\InvalidOperationException
40 | *
41 | * @return \PHPCollections\Collections\ArrayList
42 | */
43 | public function diff(BaseCollection $newArrayList): BaseCollection
44 | {
45 | if (!$newArrayList instanceof self) {
46 | throw new InvalidOperationException('You should only compare an ArrayList against another ArrayList');
47 | }
48 |
49 | $diffValues = array_udiff($this->toArray(), $newArrayList->toArray(), function ($firstValue, $secondValue) {
50 | if (gettype($firstValue) !== gettype($secondValue)) {
51 | return -1;
52 | }
53 |
54 | return $firstValue <=> $secondValue;
55 | });
56 |
57 | return new self($diffValues);
58 | }
59 |
60 | /**
61 | * Determines if two ArrayList objects are equal.
62 | *
63 | * @param \PHPCollections\Collections\ArrayList $newArrayList
64 | *
65 | * @return \PHPCollections\Collections\ArrayList
66 | */
67 | public function equals(BaseCollection $newArrayList): bool
68 | {
69 | if (!$newArrayList instanceof self) {
70 | throw new InvalidOperationException('You should only compare an ArrayList against another ArrayList');
71 | }
72 |
73 | return $this->toArray() == $newArrayList->toArray();
74 | }
75 |
76 | /**
77 | * Returns all the coincidences found
78 | * for the given callback or null.
79 | *
80 | * @param callable $callback
81 | *
82 | * @return \PHPCollections\Collections\ArrayList|null
83 | */
84 | public function filter(callable $callback): ?self
85 | {
86 | $matcheds = [];
87 |
88 | foreach ($this->dataHolder as $value) {
89 | if (call_user_func($callback, $value) === true) {
90 | $matcheds[] = $value;
91 | }
92 | }
93 |
94 | return count($matcheds) > 0 ? new $this(array_values($matcheds)) : null;
95 | }
96 |
97 | /**
98 | * Iterates over every element of the collection.
99 | *
100 | * @param callable $callback
101 | *
102 | * @return void
103 | */
104 | public function forEach(callable $callback): void
105 | {
106 | $data = $this->toArray();
107 |
108 | array_walk($data, $callback);
109 | $this->dataHolder->setContainer($data);
110 | }
111 |
112 | /**
113 | * Gets the element specified
114 | * at the given index.
115 | *
116 | * @param int $offset
117 | *
118 | * @return mixed
119 | */
120 | public function get(int $offset)
121 | {
122 | return $this->dataHolder->offsetGet($offset);
123 | }
124 |
125 | /**
126 | * Updates elements in the collection by
127 | * applying a given callback function.
128 | *
129 | * @param callable $callback
130 | *
131 | * @return \PHPCollections\Collections\ArrayList|null
132 | */
133 | public function map(callable $callback): ?self
134 | {
135 | $matcheds = array_map($callback, $this->toArray());
136 |
137 | return count($matcheds) > 0 ? new $this(array_values($matcheds)) : null;
138 | }
139 |
140 | /**
141 | * Merges two ArrayList into a new one.
142 | *
143 | * @param \PHPCollections\Collections\ArrayList $newArrayList
144 | *
145 | * @return \PHPCollections\Collections\ArrayList
146 | */
147 | public function merge(BaseCollection $newArrayList): BaseCollection
148 | {
149 | return new $this(array_merge($this->toArray(), $newArrayList->toArray()));
150 | }
151 |
152 | /**
153 | * Returns a random element of
154 | * the collection.
155 | *
156 | * @throws \PHPCollections\Exceptions\InvalidOperationException
157 | *
158 | * @return mixed
159 | */
160 | public function rand()
161 | {
162 | if ($this->isEmpty()) {
163 | throw new InvalidOperationException('You cannot get a random element from an empty collection');
164 | }
165 |
166 | $randomIndex = array_rand($this->toArray());
167 |
168 | return $this->get($randomIndex);
169 | }
170 |
171 | /**
172 | * Removes an item from the collection
173 | * and repopulates the data array.
174 | *
175 | * @param int $offset
176 | *
177 | * @throws \OutOfRangeException
178 | *
179 | * @return void
180 | */
181 | public function remove(int $offset): void
182 | {
183 | if ($this->isEmpty()) {
184 | throw new OutOfRangeException('You\'re trying to remove data from an empty collection');
185 | }
186 |
187 | if (!$this->dataHolder->offsetExists($offset)) {
188 | throw new OutOfRangeException(sprintf('The %d index does not exists for this collection', $offset));
189 | }
190 |
191 | $this->dataHolder->offsetUnset($offset);
192 | }
193 |
194 | /**
195 | * Returns a new collection with the
196 | * reversed values.
197 | *
198 | * @throws \PHPCollections\Exceptions\InvalidOperationException
199 | *
200 | * @return \PHPCollections\Collections\ArrayList
201 | */
202 | public function reverse(): self
203 | {
204 | if ($this->isEmpty()) {
205 | throw new InvalidOperationException('You cannot reverse an empty collection');
206 | }
207 |
208 | return new $this(array_reverse($this->toArray()));
209 | }
210 |
211 | /**
212 | * Returns a portion of the ArrayList.
213 | *
214 | * @param int $offset
215 | * @param int|null $length
216 | *
217 | * @return \PHPCollections\Collections\ArrayList|null
218 | */
219 | public function slice(int $offset, ?int $length = null): ?BaseCollection
220 | {
221 | $newData = array_slice($this->toArray(), $offset, $length);
222 |
223 | return count($newData) > 0 ? new self($newData) : null;
224 | }
225 |
226 | /**
227 | * Returns a new ArrayList with the
228 | * values ordered by a given callback
229 | * if couldn't sort returns null.
230 | *
231 | * @param callable $callback
232 | *
233 | * @return \PHPCollections\Collections\ArrayList|null
234 | */
235 | public function sort(callable $callback): ?BaseCollection
236 | {
237 | $data = $this->toArray();
238 |
239 | return usort($data, $callback) ? new $this($data) : null;
240 | }
241 |
242 | /**
243 | * Updates the value of the element
244 | * at the given index.
245 | *
246 | * @param int $index
247 | * @param mixed $value
248 | *
249 | * @return bool
250 | */
251 | public function update(int $index, $value): bool
252 | {
253 | if (!$this->exists($index)) {
254 | throw new InvalidOperationException('You cannot update a non-existent value');
255 | }
256 |
257 | $this->dataHolder->offsetSet($index, $value);
258 |
259 | return $this->dataHolder->offsetGet($index) === $value;
260 | }
261 | }
262 |
--------------------------------------------------------------------------------
/src/Collections/BaseCollection.php:
--------------------------------------------------------------------------------
1 | dataHolder = new DataHolder($data);
34 | }
35 |
36 | /**
37 | * Reinitializes the dataHolder property.
38 | *
39 | * @return void
40 | */
41 | public function clear(): void
42 | {
43 | $this->dataHolder = new DataHolder();
44 | }
45 |
46 | /**
47 | * Checks if the collection
48 | * contains a given value.
49 | *
50 | * @param mixed $needle
51 | *
52 | * @return bool
53 | */
54 | public function contains($needle): bool
55 | {
56 | return in_array($needle, $this->toArray());
57 | }
58 |
59 | /**
60 | * Returns the length of the collection.
61 | *
62 | * @return int
63 | */
64 | public function count(): int
65 | {
66 | return count($this->toArray());
67 | }
68 |
69 | /**
70 | * Gets the difference between two collections.
71 | *
72 | * @param \PHPCollections\Collections\BaseCollection $collection
73 | *
74 | * @return \PHPCollections\Collections\BaseCollection
75 | */
76 | abstract public function diff(self $collection): self;
77 |
78 | /**
79 | * Checks if the given index
80 | * exists in the collection.
81 | *
82 | * @param mixed $offset
83 | *
84 | * @return bool
85 | */
86 | public function exists($offset): bool
87 | {
88 | return $this->dataHolder->offsetExists($offset);
89 | }
90 |
91 | /**
92 | * Determines if two collections are equal.
93 | *
94 | * @param \PHPCollections\Collections\BaseCollection $collection
95 | *
96 | * @return bool
97 | */
98 | abstract public function equals(self $collection): bool;
99 |
100 | /**
101 | * Fills the collection with a set of data.
102 | *
103 | * @param array $data
104 | *
105 | * @return void
106 | */
107 | public function fill(array $data): void
108 | {
109 | foreach ($data as $entry) {
110 | $this->add($entry);
111 | }
112 | }
113 |
114 | /**
115 | * Gets the first element in the collection.
116 | *
117 | * @throws \OutOfRangeException
118 | *
119 | * @return mixed
120 | */
121 | public function first()
122 | {
123 | if ($this->isEmpty()) {
124 | throw new OutOfRangeException('You\'re trying to get data from an empty collection');
125 | }
126 |
127 | return array_values($this->toArray())[0];
128 | }
129 |
130 | /**
131 | * Checks if the collection is empty.
132 | *
133 | * @return bool
134 | */
135 | public function isEmpty(): bool
136 | {
137 | return $this->count() === 0;
138 | }
139 |
140 | /**
141 | * Defines the behavior of the collection
142 | * when json_encode is called.
143 | *
144 | * @return array
145 | */
146 | public function jsonSerialize(): array
147 | {
148 | return $this->toArray();
149 | }
150 |
151 | /**
152 | * Gets the last element of the collection.
153 | *
154 | * @throws \OutOfRangeException
155 | *
156 | * @return mixed
157 | */
158 | public function last()
159 | {
160 | if ($this->isEmpty()) {
161 | throw new OutOfRangeException('You\'re trying to get data from an empty collection');
162 | }
163 |
164 | return array_values($this->toArray())[$this->count() - 1];
165 | }
166 |
167 | /**
168 | * Returns a portion of the collection.
169 | *
170 | * @param int $offset
171 | * @param int|null $lenght
172 | *
173 | * @return \PHPCollections\Collections\BaseCollection
174 | */
175 | abstract public function slice(int $offset, ?int $lenght): ?self;
176 |
177 | /**
178 | * Returns the sum of a set of values.
179 | *
180 | * @param callable $callback
181 | *
182 | * @throws \PHPCollections\Exceptions\InvalidOperationException
183 | *
184 | * @return float
185 | */
186 | public function sum(callable $callback): float
187 | {
188 | $sum = 0;
189 |
190 | foreach ($this->dataHolder as $value) {
191 | if (!is_numeric($result = call_user_func($callback, $value))) {
192 | throw new InvalidOperationException('You cannot sum non-numeric values');
193 | }
194 |
195 | $sum += $result;
196 | }
197 |
198 | return $sum;
199 | }
200 |
201 | /**
202 | * Returns a plain array with
203 | * your dictionary data.
204 | *
205 | * @return array
206 | */
207 | public function toArray(): array
208 | {
209 | return $this->dataHolder->getContainer();
210 | }
211 | }
212 |
--------------------------------------------------------------------------------
/src/Collections/Dictionary.php:
--------------------------------------------------------------------------------
1 | keyType = $keyType;
49 | $this->valueType = $valueType;
50 |
51 | foreach ($data as $key => $value) {
52 | $this->validateEntry($key, $value);
53 | }
54 |
55 | parent::__construct($data);
56 | $this->initializePairs($data);
57 | }
58 |
59 | /**
60 | * Adds a new value to the dictionary.
61 | *
62 | * @param mixed $key
63 | * @param mixed $value
64 | *
65 | * @throws \InvalidArgumentException
66 | *
67 | * @return void
68 | */
69 | public function add($key, $value): void
70 | {
71 | $this->validateEntry($key, $value);
72 | $this->dataHolder->offsetSet($key, new Pair($key, $value));
73 | }
74 |
75 | /**
76 | * Gets the difference between two Dictionary.
77 | *
78 | * @param \PHPCollections\Collections\Dictionary $newDictionary
79 | *
80 | * @throws \PHPCollections\Exceptions\InvalidOperationException
81 | *
82 | * @return \PHPCollections\Collections\Dictionary
83 | */
84 | public function diff(BaseCollection $newDictionary): BaseCollection
85 | {
86 | if (!$newDictionary instanceof self) {
87 | throw new InvalidOperationException('You should only compare a Dictionary against another Dictionary');
88 | }
89 |
90 | if ($this->keyType !== $newDictionary->getKeyType()) {
91 | throw new InvalidOperationException(sprintf('The key type for this Dictionary is %s, you cannot pass a Dictionary with %s as key type', $this->keyType, $newDictionary->getKeyType()));
92 | }
93 |
94 | if ($this->valueType !== $newDictionary->getValueType()) {
95 | throw new InvalidOperationException(sprintf('The value type for this Dictionary is %s, you cannot pass a Dictionary with %s as value types', $this->valueType, $newDictionary->getValueType()));
96 | }
97 |
98 | $diffValues = array_udiff_uassoc($this->toArray(), $newDictionary->toArray(), function ($firstValue, $secondValue) {
99 | return $firstValue <=> $secondValue;
100 | }, function ($firstKey, $secondKey) {
101 | return $firstKey <=> $secondKey;
102 | });
103 |
104 | return new self($this->keyType, $this->valueType, $diffValues);
105 | }
106 |
107 | /**
108 | * Determines if two Dictionary objects are equal.
109 | *
110 | * @param \PHPCollections\Collections\Dictionary $newDictionary
111 | *
112 | * @return \PHPCollections\Collections\Dictionary
113 | */
114 | public function equals(BaseCollection $newDictionary): bool
115 | {
116 | if (!$newDictionary instanceof self) {
117 | throw new InvalidOperationException('You should only compare an Dictionary against another Dictionary');
118 | }
119 |
120 | return $this->toArray() == $newDictionary->toArray();
121 | }
122 |
123 | /**
124 | * Fills the dictionary with data.
125 | *
126 | * @param array $data
127 | *
128 | * @return void
129 | */
130 | public function fill(array $data): void
131 | {
132 | foreach ($data as $key => $entry) {
133 | $this->add($key, $entry);
134 | }
135 | }
136 |
137 | /**
138 | * Filters the collection applying
139 | * a given callback.
140 | *
141 | * @param callable $callback
142 | *
143 | * @return \PHPCollections\Collections\Dictionary|null
144 | */
145 | public function filter(callable $callback): ?self
146 | {
147 | $matcheds = [];
148 |
149 | foreach ($this->dataHolder as $key => $value) {
150 | if (call_user_func($callback, $value->getKey(), $value->getValue()) === true) {
151 | $matcheds[$value->getKey()] = $value->getValue();
152 | }
153 | }
154 |
155 | return count($matcheds) > 0 ? new $this($this->keyType, $this->valueType, $matcheds) : null;
156 | }
157 |
158 | /**
159 | * Iterates over every element of the collection.
160 | *
161 | * @param callable $callback
162 | *
163 | * @return void
164 | */
165 | public function forEach(callable $callback): void
166 | {
167 | $data = $this->toArray();
168 |
169 | array_walk($data, $callback);
170 | $this->initializePairs($data);
171 | }
172 |
173 | /**
174 | * Returns the value for the specified
175 | * key or null if it's not defined.
176 | *
177 | * @param mixed $key
178 | *
179 | * @return mixed|null
180 | */
181 | public function get($key)
182 | {
183 | return $this->dataHolder->offsetExists($key) ?
184 | $this->dataHolder->offsetGet($key)->getValue() :
185 | null;
186 | }
187 |
188 | /**
189 | * Returns the key type for this collection.
190 | *
191 | * @return mixed
192 | */
193 | public function getKeyType()
194 | {
195 | return $this->keyType;
196 | }
197 |
198 | /**
199 | * Returns the key value for this collection.
200 | *
201 | * @return mixed
202 | */
203 | public function getValueType()
204 | {
205 | return $this->valueType;
206 | }
207 |
208 | /**
209 | * Populates the container with Pair objects.
210 | *
211 | * @param array $data
212 | *
213 | * @return void
214 | */
215 | private function initializePairs(array $data): void
216 | {
217 | foreach ($data as $key => $value) {
218 | $this->dataHolder[$key] = new Pair($key, $value);
219 | }
220 | }
221 |
222 | /**
223 | * Updates elements in the collection by
224 | * applying a given callback function.
225 | *
226 | * @param callable $callback
227 | *
228 | * @return \PHPCollections\Collections\Dictionary|null
229 | */
230 | public function map(callable $callback): ?self
231 | {
232 | $matcheds = array_map($callback, $this->toArray());
233 |
234 | return count($matcheds) > 0 ? new $this($this->keyType, $this->valueType, $this->toArray()) : null;
235 | }
236 |
237 | /**
238 | * Merges two dictionaries into a new one.
239 | *
240 | * @param \PHPCollections\Collections\Dictionary $newDictionary
241 | *
242 | * @throws \InvalidArgumentException
243 | *
244 | * @return \PHPCollections\Collections\Dictionary
245 | */
246 | public function merge(BaseCollection $newDictionary): BaseCollection
247 | {
248 | Checker::isEqual(
249 | $newDictionary->getKeyType(), $this->getKeyType(),
250 | sprintf('The new Dictionary key should be of type %s', $this->getKeyType())
251 | );
252 | Checker::isEqual(
253 | $newDictionary->getValueType(), $this->getValueType(),
254 | sprintf('The new Dictionary value type should be of type %s', $this->getValueType())
255 | );
256 |
257 | return new $this(
258 | $this->keyType,
259 | $this->valueType,
260 | array_merge($this->toArray(), $newDictionary->toArray())
261 | );
262 | }
263 |
264 | /**
265 | * Removes a value from the dictionary.
266 | *
267 | * @param mixed $key
268 | *
269 | * @throws \OutOfRangeException
270 | *
271 | * @return bool
272 | */
273 | public function remove($key): void
274 | {
275 | if ($this->isEmpty()) {
276 | throw new OutOfRangeException('You\'re trying to remove data from an empty collection');
277 | }
278 |
279 | if (!$this->dataHolder->offsetExists($key)) {
280 | throw new OutOfRangeException(sprintf('The %s key does not exists for this collection', $key));
281 | }
282 |
283 | $this->dataHolder->offsetUnset($key);
284 | }
285 |
286 | /**
287 | * Returns a portion of the Dictionary.
288 | *
289 | * @param int $offset
290 | * @param int|null $length
291 | *
292 | * @return \PHPCollections\Collections\Dictionary|null
293 | */
294 | public function slice(int $offset, ?int $length = null): ?BaseCollection
295 | {
296 | $newData = array_slice($this->toArray(), $offset, $length, true);
297 |
298 | return count($newData) > 0 ? new self($this->keyType, $this->valueType, $newData) : null;
299 | }
300 |
301 | /**
302 | * Returns a new Dictionary with the
303 | * values ordered by a given callback
304 | * if couldn't sort returns null.
305 | *
306 | * @param callable $callback
307 | *
308 | * @return \PHPCollections\Collections\Dictionary|null
309 | */
310 | public function sort(callable $callback): ?BaseCollection
311 | {
312 | $data = $this->toArray();
313 |
314 | return uasort($data, $callback) ? new $this($this->keyType, $this->valueType, $data) : null;
315 | }
316 |
317 | /**
318 | * Returns an array representation
319 | * of your dictionary data.
320 | *
321 | * @return array
322 | */
323 | public function toArray(): array
324 | {
325 | $array = [];
326 |
327 | foreach ($this->dataHolder as $pair) {
328 | $array[$pair->getKey()] = $pair->getValue();
329 | }
330 |
331 | return $array;
332 | }
333 |
334 | /**
335 | * Returns a JSON representation
336 | * of your dictionary data.
337 | *
338 | * @return string
339 | */
340 | public function toJson(): string
341 | {
342 | return json_encode($this->dataHolder);
343 | }
344 |
345 | /**
346 | * Updates the value of one Pair
347 | * in the collection.
348 | *
349 | * @param mixed $key
350 | * @param mixed $value
351 | *
352 | * @throws \InvalidArgumentException
353 | * @throws \PHPCollections\Exceptions\InvalidOperationException
354 | *
355 | * @return bool
356 | */
357 | public function update($key, $value): bool
358 | {
359 | $this->validateEntry($key, $value);
360 |
361 | if (!$this->dataHolder->offsetExists($key)) {
362 | throw new InvalidOperationException('You cannot update a non-existent value');
363 | }
364 |
365 | $this->dataHolder[$key]->setValue($value);
366 |
367 | return $this->dataHolder[$key]->getValue() === $value;
368 | }
369 |
370 | /**
371 | * Validates that a key and value are of the
372 | * specified types in the class.
373 | *
374 | * @param mixed $key
375 | * @param mixed $value
376 | *
377 | * @throws \InvalidArgumentException
378 | *
379 | * @return bool
380 | */
381 | private function validateEntry($key, $value): bool
382 | {
383 | Checker::valueIsOfType(
384 | $key, $this->keyType,
385 | sprintf(
386 | 'The %s type specified for this dictionary is %s, you cannot pass %s %s',
387 | 'key', $this->keyType, getArticle(gettype($key)), gettype($key)
388 | )
389 | );
390 | Checker::valueIsOfType(
391 | $value, $this->valueType,
392 | sprintf(
393 | 'The %s type specified for this dictionary is %s, you cannot pass %s %s',
394 | 'value', $this->valueType, getArticle(gettype($value)), gettype($value)
395 | )
396 | );
397 |
398 | return true;
399 | }
400 | }
401 |
--------------------------------------------------------------------------------
/src/Collections/GenericList.php:
--------------------------------------------------------------------------------
1 | type = $type;
49 | $this->error = "The type specified for this collection is {$type}, you cannot pass an object of type %s";
50 |
51 | foreach ($data as $value) {
52 | Checker::objectIsOfType($value, $this->type, sprintf($this->error, get_class($value)));
53 | }
54 |
55 | parent::__construct($data);
56 | }
57 |
58 | /**
59 | * Adds a new object to the collection.
60 | *
61 | * @param object $value
62 | *
63 | * @throws \InvalidArgumentException
64 | *
65 | * @return void
66 | */
67 | public function add(object $value): void
68 | {
69 | Checker::objectIsOfType($value, $this->type, sprintf($this->error, get_class($value)));
70 |
71 | $data = $this->toArray();
72 |
73 | array_push($data, $value);
74 | $this->dataHolder->setContainer($data);
75 | }
76 |
77 | /**
78 | * Gets the difference between two GenericList.
79 | *
80 | * @param \PHPCollections\Collections\GenericList $newGenericList
81 | *
82 | * @throws \PHPCollections\Exceptions\InvalidOperationException
83 | *
84 | * @return \PHPCollections\Collections\GenericList
85 | */
86 | public function diff(BaseCollection $newGenericList): BaseCollection
87 | {
88 | if (!$newGenericList instanceof self) {
89 | throw new InvalidOperationException('You should only compare a GenericList against another GenericList');
90 | }
91 |
92 | if ($this->type !== $newGenericList->getType()) {
93 | throw new InvalidOperationException("This is a collection of {$this->type} objects, you cannot pass a collection of {$newGenericList->getType()} objects");
94 | }
95 |
96 | $diffValues = array_udiff($this->toArray(), $newGenericList->toArray(), function ($firstValue, $secondValue) {
97 | return $firstValue <=> $secondValue;
98 | });
99 |
100 | return new self($this->type, ...$diffValues);
101 | }
102 |
103 | /**
104 | * Determines if two GenericList objects are equal.
105 | *
106 | * @param \PHPCollections\Collections\GenericList $newGenericList
107 | *
108 | * @return bool
109 | */
110 | public function equals(BaseCollection $newGenericList): bool
111 | {
112 | if (!$newGenericList instanceof self) {
113 | throw new InvalidOperationException('You should only compare an GenericList against another GenericList');
114 | }
115 |
116 | return $this->toArray() == $newGenericList->toArray();
117 | }
118 |
119 | /**
120 | * Returns all the coincidences found
121 | * for the given callback or null.
122 | *
123 | * @param callable $callback
124 | *
125 | * @return \PHPCollections\Collections\GenericList|null
126 | */
127 | public function filter(callable $callback): ?self
128 | {
129 | $matcheds = [];
130 |
131 | foreach ($this->dataHolder as $key => $value) {
132 | if (call_user_func($callback, $key, $value) === true) {
133 | $matcheds[] = $value;
134 | }
135 | }
136 |
137 | return count($matcheds) > 0 ? new $this($this->type, ...array_values($matcheds)) : null;
138 | }
139 |
140 | /**
141 | * Iterates over every element of the collection.
142 | *
143 | * @param callable $callback
144 | *
145 | * @return void
146 | */
147 | public function forEach(callable $callback): void
148 | {
149 | $data = $this->toArray();
150 |
151 | array_walk($data, $callback);
152 | $this->dataHolder->setContainer($data);
153 | }
154 |
155 | /**
156 | * Returns the object at the specified index
157 | * or null if it's not defined.
158 | *
159 | * @param int $offset
160 | *
161 | * @throws \OutOfRangeException
162 | *
163 | * @return object
164 | */
165 | public function get(int $offset): object
166 | {
167 | if ($this->isEmpty()) {
168 | throw new OutOfRangeException('You\'re trying to get data from an empty collection.');
169 | }
170 |
171 | if (!$this->dataHolder->offsetExists($offset)) {
172 | throw new OutOfRangeException(sprintf('The %d index do not exits for this collection.', $offset));
173 | }
174 |
175 | return $this->dataHolder->offsetGet($offset);
176 | }
177 |
178 | /**
179 | * Returns the type property.
180 | *
181 | * @return string
182 | */
183 | private function getType(): string
184 | {
185 | return $this->type;
186 | }
187 |
188 | /**
189 | * Updates elements in the collection by
190 | * applying a given callback function.
191 | *
192 | * @param callable $callback
193 | *
194 | * @return \PHPCollections\Collections\GenericList|null
195 | */
196 | public function map(callable $callback): ?self
197 | {
198 | $matcheds = array_map($callback, $this->toArray());
199 |
200 | return count($matcheds) > 0 ? new $this($this->type, ...array_values($matcheds)) : null;
201 | }
202 |
203 | /**
204 | * Merges two GenericList into a new one.
205 | *
206 | * @param array $data
207 | *
208 | * @throws \InvalidArgumentException
209 | *
210 | * @return \PHPCollections\Collections\GenericList
211 | */
212 | public function merge(BaseCollection $newGenericList): BaseCollection
213 | {
214 | $newGenericList->forEach(function ($value) {
215 | Checker::objectIsOfType($value, $this->type, sprintf($this->error, get_class($value)));
216 | });
217 |
218 | return new $this($this->type, ...array_merge($this->toArray(), $newGenericList->toArray()));
219 | }
220 |
221 | /**
222 | * Returns a random element from
223 | * the collection.
224 | *
225 | * @throws \PHPCollections\Exceptions\InvalidOperationException
226 | *
227 | * @return mixed
228 | */
229 | public function rand()
230 | {
231 | if ($this->isEmpty()) {
232 | throw new InvalidOperationException('You cannot get a random element from an empty collection.');
233 | }
234 |
235 | $randomIndex = array_rand($this->toArray());
236 |
237 | return $this->get($randomIndex);
238 | }
239 |
240 | /**
241 | * Removes an item from the collection
242 | * and repopulate the data container.
243 | *
244 | * @param int $offset
245 | *
246 | * @throws \OutOfRangeException
247 | *
248 | * @return void
249 | */
250 | public function remove(int $offset): void
251 | {
252 | if ($this->isEmpty()) {
253 | throw new OutOfRangeException('You\'re trying to remove data into a empty collection.');
254 | }
255 |
256 | if (!$this->dataHolder->offsetExists($offset)) {
257 | throw new OutOfRangeException(sprintf('The %d index do not exits for this collection.', $offset));
258 | }
259 |
260 | $this->dataHolder->offsetUnset($offset);
261 | $this->repopulate();
262 | }
263 |
264 | /**
265 | * Repopulates the data container.
266 | *
267 | * @return void
268 | */
269 | private function repopulate(): void
270 | {
271 | $oldData = array_values($this->toArray());
272 | $this->dataHolder->setContainer($oldData);
273 | }
274 |
275 | /**
276 | * Returns a new collection with the
277 | * reversed values.
278 | *
279 | * @throws \PHPCollections\Exceptions\InvalidOperationException
280 | *
281 | * @return \PHPCollections\Collections\GenericList
282 | */
283 | public function reverse(): self
284 | {
285 | if ($this->isEmpty()) {
286 | throw new InvalidOperationException('You cannot reverse an empty collection.');
287 | }
288 |
289 | return new $this($this->type, ...array_reverse($this->toArray()));
290 | }
291 |
292 | /**
293 | * Returns a portion of the GenericList.
294 | *
295 | * @param int $offset
296 | * @param int|null $length
297 | *
298 | * @return \PHPCollections\Collections\GenericList|null
299 | */
300 | public function slice(int $offset, ?int $length = null): ?BaseCollection
301 | {
302 | $newData = array_slice($this->toArray(), $offset, $length);
303 |
304 | return count($newData) > 0 ? new self($this->type, ...$newData) : null;
305 | }
306 |
307 | /**
308 | * Returns a new GenericList with the
309 | * values ordered by a given callback
310 | * if couldn't sort returns null.
311 | *
312 | *
313 | * @param callable $callback
314 | *
315 | * @return \PHPCollections\Collections\GenericList|null
316 | */
317 | public function sort(callable $callback): ?BaseCollection
318 | {
319 | $data = $this->toArray();
320 |
321 | return usort($data, $callback) ? new $this($this->type, ...$data) : null;
322 | }
323 |
324 | /**
325 | * Updates the value of the element
326 | * at the given index.
327 | *
328 | * @param int $index
329 | * @param mixed $value
330 | *
331 | * @throws \InvalidArgumentException
332 | * @throws \PHPCollections\Exceptions\InvalidOperationException
333 | *
334 | * @return bool
335 | */
336 | public function update(int $index, object $value): bool
337 | {
338 | Checker::objectIsOfType($value, $this->type, sprintf($this->error, get_class($value)));
339 |
340 | if (!$this->exists($index)) {
341 | throw new InvalidOperationException('You cannot update a non-existent value');
342 | }
343 |
344 | $this->dataHolder[$index] = $value;
345 |
346 | return $this->dataHolder[$index] === $value;
347 | }
348 | }
349 |
--------------------------------------------------------------------------------
/src/Collections/Pair.php:
--------------------------------------------------------------------------------
1 | key = $key;
36 | $this->value = $value;
37 | }
38 |
39 | /**
40 | * Allows access to the key
41 | * property by its value.
42 | *
43 | * @param string $name
44 | *
45 | * @return mixed
46 | */
47 | public function __get(string $name)
48 | {
49 | if ($name === $this->key) {
50 | return $this->value;
51 | }
52 | }
53 |
54 | /**
55 | * Returns the key property.
56 | *
57 | * @return mixed
58 | */
59 | public function getKey()
60 | {
61 | return $this->key;
62 | }
63 |
64 | /**
65 | * Returns the value property.
66 | *
67 | * @return mixed
68 | */
69 | public function getValue()
70 | {
71 | return $this->value;
72 | }
73 |
74 | /**
75 | * Sets the value of the value property.
76 | *
77 | * @param mixed $value
78 | *
79 | * @return void
80 | */
81 | public function setValue($value): void
82 | {
83 | $this->value = $value;
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/Collections/Stack.php:
--------------------------------------------------------------------------------
1 | data = [];
38 | $this->type = $type;
39 | }
40 |
41 | /**
42 | * Clears the data values.
43 | *
44 | * @return void
45 | */
46 | public function clear(): void
47 | {
48 | $this->data = [];
49 | }
50 |
51 | /**
52 | * Returns the length of the Stack.
53 | *
54 | * @return int
55 | */
56 | public function count(): int
57 | {
58 | return count($this->data);
59 | }
60 |
61 | /**
62 | * Checks if the stack is empty.
63 | *
64 | * @return bool
65 | */
66 | public function isEmpty(): bool
67 | {
68 | return $this->count() === 0;
69 | }
70 |
71 | /**
72 | * Gets the element at
73 | * the end of the Stack.
74 | *
75 | * @return mixed
76 | */
77 | public function peek()
78 | {
79 | return $this->data[$this->count() - 1];
80 | }
81 |
82 | /**
83 | * Pops the element at
84 | * the end of the stack.
85 | *
86 | * @return mixed
87 | */
88 | public function pop()
89 | {
90 | return array_pop($this->data);
91 | }
92 |
93 | /**
94 | * Adds a new element at
95 | * the end of the Stack.
96 | *
97 | * @param mixed $value
98 | *
99 | * @throws \InvalidArgumentException
100 | *
101 | * @return mixed
102 | */
103 | public function push($value)
104 | {
105 | $message = sprintf(
106 | 'The type specified for this collection is %s, you cannot pass a value of type %s',
107 | $this->type, gettype($value)
108 | );
109 |
110 | Checker::valueIsOfType($value, $this->type, $message);
111 |
112 | $this->data[] = $value;
113 |
114 | return $value;
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/src/DataHolder.php:
--------------------------------------------------------------------------------
1 | container = $data;
31 | }
32 |
33 | /**
34 | * Returns the container array.
35 | *
36 | * @return array
37 | */
38 | public function getContainer(): array
39 | {
40 | return $this->container;
41 | }
42 |
43 | /**
44 | * Returns an array iterator for
45 | * the container property.
46 | *
47 | * @return \ArrayIterator
48 | */
49 | public function getIterator(): ArrayIterator
50 | {
51 | return new ArrayIterator($this->container);
52 | }
53 |
54 | /**
55 | * Checks if an offset exists in the container.
56 | *
57 | * @param mixed $offset
58 | *
59 | * @return bool
60 | */
61 | public function offsetExists($offset): bool
62 | {
63 | return isset($this->container[$offset]);
64 | }
65 |
66 | /**
67 | * Gets a value from the container.
68 | *
69 | * @param mixed $offset
70 | *
71 | * @return mixed|null
72 | */
73 | public function offsetGet($offset)
74 | {
75 | return $this->container[$offset] ?? null;
76 | }
77 |
78 | /**
79 | * Sets a value into the container.
80 | *
81 | * @param mixed $offset
82 | * @param mixed $value
83 | *
84 | * @return void
85 | */
86 | public function offsetSet($offset, $value): void
87 | {
88 | $this->container[$offset] = $value;
89 | }
90 |
91 | /**
92 | * Unsets an offset from the container.
93 | *
94 | * @param mixed $offset
95 | *
96 | * @return void
97 | */
98 | public function offsetUnset($offset): void
99 | {
100 | unset($this->container[$offset]);
101 | }
102 |
103 | /**
104 | * Sets the container array.
105 | *
106 | * @param array $data
107 | *
108 | * @return void
109 | */
110 | public function setContainer(array $data): void
111 | {
112 | $this->container = $data;
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/src/Exceptions/InvalidOperationException.php:
--------------------------------------------------------------------------------
1 | code, $this->message);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/Interfaces/CollectionInterface.php:
--------------------------------------------------------------------------------
1 | arrayList = new ArrayList();
17 | $this->arrayList->add('Max');
18 | $this->arrayList->add(5);
19 | $this->arrayList->add(false);
20 | $this->arrayList->add(new StdClass());
21 | $this->arrayList->add(null);
22 | }
23 |
24 | /** @test */
25 | public function canAddElements()
26 | {
27 | $this->arrayList->add('last index');
28 |
29 | $lastIndex = $this->arrayList->count() - 1;
30 |
31 | $this->assertEquals('last index', $this->arrayList->get($lastIndex));
32 | }
33 |
34 | /** @test */
35 | public function canClearData()
36 | {
37 | $this->arrayList->clear();
38 | $this->assertEmpty($this->arrayList);
39 | }
40 |
41 | /** @test */
42 | public function canCheckIfIndexExists()
43 | {
44 | $this->assertTrue($this->arrayList->exists(0));
45 | }
46 |
47 | /** @test */
48 | public function canFilterByValue()
49 | {
50 | $newArrayList = $this->arrayList->filter(function ($value) {
51 | return is_string($value);
52 | });
53 |
54 | $this->assertNotNull($newArrayList);
55 | $this->assertCount(1, $newArrayList);
56 | $this->assertEquals('Max', $newArrayList->get(0));
57 | }
58 |
59 | /** @test */
60 | public function canCheckIfAValueIsContained()
61 | {
62 | $isContained = $this->arrayList->contains(null);
63 |
64 | $this->assertTrue($isContained);
65 | }
66 |
67 | /** @test */
68 | public function canGetFirstElement()
69 | {
70 | $firstElement = $this->arrayList->first();
71 |
72 | $this->assertEquals('Max', $firstElement);
73 | }
74 |
75 | /** @test */
76 | public function canGetLastElement()
77 | {
78 | $lastElement = $this->arrayList->last();
79 |
80 | $this->assertNull($lastElement);
81 | }
82 |
83 | /** @test */
84 | public function canUpdateTheElementsByMapping()
85 | {
86 | $newArrayList = $this->arrayList->map(function ($val) {
87 | if ($val == false) {
88 | return 'Empty value';
89 | } else {
90 | return $val;
91 | }
92 | });
93 |
94 | $this->assertContains('Empty value', $newArrayList->toArray());
95 | }
96 |
97 | /** @test */
98 | public function canMergeNewDataIntoNewArrayList()
99 | {
100 | $numbers = new ArrayList([1, 2, 3, 4, 5]);
101 | $newArrayList = $numbers->merge(new ArrayList([6, 7, 8, 9, 10]));
102 |
103 | $this->assertCount(10, $newArrayList);
104 | $this->assertEquals(1, $newArrayList->first());
105 | $this->assertEquals(10, $newArrayList->last());
106 | }
107 |
108 | /**
109 | * @test
110 | * @expectedException PHPCollections\Exceptions\InvalidOperationException
111 | */
112 | public function cannotGetARandomValueFromEmptyArrayList()
113 | {
114 | $newArrayList = new ArrayList();
115 | $newArrayList->rand(); // Here an InvalidOperationException is thrown!
116 | }
117 |
118 | /** @test */
119 | public function canReverse()
120 | {
121 | $reversedList = $this->arrayList->reverse();
122 | $this->assertEquals(null, $reversedList->first());
123 | $this->assertEquals('Max', $reversedList->last());
124 | }
125 |
126 | /**
127 | * @test
128 | * @expectedException PHPCollections\Exceptions\InvalidOperationException
129 | */
130 | public function cannotReverseAnEmptyArrayList()
131 | {
132 | $newArrayList = new ArrayList();
133 | $reversedList = $newArrayList->reverse(); // Here an InvalidOperationException is thrown!
134 | }
135 |
136 | /** @test */
137 | public function canUpdateAValue()
138 | {
139 | $this->arrayList->update(0, 'John');
140 | $this->assertEquals('John', $this->arrayList->get(0));
141 | }
142 |
143 | /**
144 | * @test
145 | * @expectedException PHPCollections\Exceptions\InvalidOperationException
146 | */
147 | public function cannotUpdateAnNonExistingValue()
148 | {
149 | $newArrayList = new ArrayList();
150 | $newArrayList->update(0, 'Some value'); // Here an InvalidOperationException is thrown!
151 | }
152 |
153 | /** @test */
154 | public function canIterateOverEachElement()
155 | {
156 | $this->arrayList->forEach(function (&$value, $key) {
157 | if (!is_object($value) && $value) {
158 | $value = $value.'x';
159 | }
160 | });
161 |
162 | $this->assertEquals('Maxx', $this->arrayList->get(0));
163 | $this->assertEquals('5x', $this->arrayList->get(1));
164 | }
165 |
166 | /**
167 | * @test
168 | * @expectedException \OutOfRangeException
169 | */
170 | public function canRemoveElementByIndex()
171 | {
172 | $this->assertEquals('Max', $this->arrayList->get(0));
173 | $this->arrayList->remove(0);
174 |
175 | $this->assertFalse($this->arrayList->contains('Max'));
176 | $this->arrayList->remove(0); // Here an OutOfRangeException is thrown!
177 | }
178 |
179 | /** @test */
180 | public function canCompareTwoArrayList()
181 | {
182 | $newList = new ArrayList(['Max', 5, false]);
183 | $diffList = $this->arrayList->diff($newList);
184 |
185 | $this->assertInstanceOf(ArrayList::class, $diffList);
186 | $this->assertTrue($diffList->contains(null));
187 | $this->assertCount(2, $diffList);
188 | }
189 |
190 | /** @test */
191 | public function canNotCompareAnArrayListAgainstAnotherTypeOfCollection()
192 | {
193 | $this->expectException('\PHPCollections\Exceptions\InvalidOperationException');
194 | $this->expectExceptionMessage('You should only compare an ArrayList against another ArrayList');
195 |
196 | $newList = new GenericList(
197 | StdClass::class,
198 | new StdClass(['name' => 'John']),
199 | new StdClass(['name' => 'Carter'])
200 | );
201 |
202 | $diffList = $this->arrayList->diff($newList); // Here an InvalidOperationException is thrown!
203 | }
204 |
205 | /** @test */
206 | public function canSliceAnArrayList()
207 | {
208 | $this->assertCount(3, $this->arrayList->slice(2));
209 | $this->assertCount(3, $this->arrayList->slice(2, null));
210 | $this->assertCount(3, $this->arrayList->slice(2, 3));
211 | $this->assertNull((new ArrayList())->slice(2));
212 | }
213 |
214 | /** @test */
215 | public function canCheckIfTwoArrayListAreEqual()
216 | {
217 | $newArrayList = new ArrayList(['Max', 5, false, new StdClass(), null]);
218 |
219 | $this->assertTrue($this->arrayList->equals($newArrayList));
220 | $this->assertFalse($this->arrayList->equals(new ArrayList(['Max', 5, false])));
221 | }
222 |
223 | /** @test */
224 | public function canNotCheckIfAnArrayListIsEqualToAnotherTypeOfCollection()
225 | {
226 | $this->expectException('\PHPCollections\Exceptions\InvalidOperationException');
227 | $this->expectExceptionMessage('You should only compare an ArrayList against another ArrayList');
228 | $this->arrayList->equals(new GenericList(StdClass::class));
229 | }
230 |
231 | /** @test */
232 | public function canSumANumericFieldOfTheArrayList()
233 | {
234 | $newList = new ArrayList([18, 12, 23, 16, 14]);
235 | $totalPoints = $newList->sum(function ($points) {
236 | return $points;
237 | });
238 |
239 | $this->assertEquals(83, $totalPoints);
240 | }
241 |
242 | /** @test */
243 | public function canNotSumANonNumericFieldOfTheArrayList()
244 | {
245 | $newList = new ArrayList(['Kyle Lowry', 'Danny Green', 'Kawhi Leonard', 'Paskal Siakam', 'Serge Ibaka']);
246 |
247 | $this->expectException('\PHPCollections\Exceptions\InvalidOperationException');
248 | $this->expectExceptionMessage('You cannot sum non-numeric values');
249 | $newList->sum(function ($name) {
250 | return $name;
251 | }); // Here an InvalidOperationException is thrown!
252 | }
253 |
254 | /** @test */
255 | public function itCanFillAnArrayListWithData()
256 | {
257 | $this->arrayList->fill([
258 | 'first_value',
259 | 'second_value',
260 | ]);
261 |
262 | $this->assertCount(7, $this->arrayList);
263 | }
264 | }
265 |
--------------------------------------------------------------------------------
/tests/Unit/CheckerTest.php:
--------------------------------------------------------------------------------
1 | assertTrue($isChecked);
17 | }
18 |
19 | /**
20 | * @test
21 | * @expectedException InvalidArgumentException
22 | * @expectedExceptionMessage You're not passing a stdClass object
23 | */
24 | public function it_throws_an_exception_when_object_is_not_of_certain_type()
25 | {
26 | Checker::objectIsOfType(new StdClass(), 'ArrayObject', 'You\'re not passing a stdClass object');
27 | }
28 |
29 | /** @test */
30 | public function it_can_check_a_value_is_an_object()
31 | {
32 | $isObject = Checker::isObject(new StdClass(), 'You\'re not passing an object');
33 |
34 | $this->assertTrue($isObject);
35 | }
36 |
37 | /**
38 | * @test
39 | * @expectedException InvalidArgumentException
40 | * @expectedExceptionMessage You're not passing an object
41 | */
42 | public function it_throws_an_exception_when_you_treat_a_primitive_like_an_object()
43 | {
44 | Checker::isObject('hello world', 'You\'re not passing an object');
45 | }
46 |
47 | /** @test */
48 | public function it_can_check_dictionary_value_is_of_certain_type()
49 | {
50 | $isChecked = Checker::valueIsOfType('hello world', 'string', 'You\'re not passing a string');
51 |
52 | $this->assertTrue($isChecked);
53 | }
54 |
55 | /**
56 | * @test
57 | * @expectedException InvalidArgumentException
58 | * @expectedExceptionMessage You're not passing a string
59 | */
60 | public function it_throws_an_exception_when_dictionary_value_is_not_of_certain_type()
61 | {
62 | Checker::valueIsOfType(500, 'string', 'You\'re not passing a string');
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/tests/Unit/DataHolderTest.php:
--------------------------------------------------------------------------------
1 | dataHolder = new DataHolder([
15 | 'name' => 'Max',
16 | 'age' => '24',
17 | ]);
18 | }
19 |
20 | /** @test */
21 | public function it_can_add_elements()
22 | {
23 | $this->dataHolder->offsetSet('job', 'Programmer');
24 | $this->assertEquals('Programmer', $this->dataHolder->offsetGet('job'));
25 | }
26 |
27 | /** @test */
28 | public function it_can_remove_elements()
29 | {
30 | $this->dataHolder->offsetUnset('name');
31 | $this->assertArrayNotHasKey('name', $this->dataHolder);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/tests/Unit/DictionaryTest.php:
--------------------------------------------------------------------------------
1 | dictionary = new Dictionary('string', 'string');
18 | $this->dictionary->add('name', 'Max');
19 | $this->dictionary->add('job', 'programmer');
20 | $this->dictionary->add('drink', 'no');
21 | $this->dictionary->add('smoke', 'no');
22 | $this->dictionary->add('dance', 'a little bit');
23 | $this->dictionary->add('drugs', 'no');
24 | $this->dictionary->add('age', '23');
25 | }
26 |
27 | /**
28 | * @test
29 | * @expectedException InvalidArgumentException
30 | */
31 | public function canAddValuesOfTheSpecifiedTypes()
32 | {
33 | $this->dictionary->add('nickname', 'maxalmonte14');
34 | $this->assertArrayHasKey('nickname', $this->dictionary->toArray());
35 | $this->dictionary->add('movies', new ArrayObject(['Plan 9', 'The creature of the black lagoon', 'Nigth of the living dead']));
36 | }
37 |
38 | /** @test */
39 | public function canCheckIfContainsAValue()
40 | {
41 | $this->assertTrue($this->dictionary->exists('drink'));
42 | }
43 |
44 | /** @test */
45 | public function canClearData()
46 | {
47 | $this->dictionary->clear();
48 | $this->assertCount(0, $this->dictionary);
49 | }
50 |
51 | /** @test */
52 | public function canGetAnElementByIndex()
53 | {
54 | $job = $this->dictionary->get('job');
55 | $this->assertEquals('programmer', $job);
56 |
57 | $nullPointer = $this->dictionary->get('posts');
58 |
59 | $this->assertNull($nullPointer);
60 | }
61 |
62 | /** @test */
63 | public function canUpdateDataByMapping()
64 | {
65 | $newDictionary = $this->dictionary->map(function ($value) {
66 | return $value = 'no';
67 | });
68 |
69 | $this->assertInstanceOf(Dictionary::class, $newDictionary);
70 | $this->assertEquals('no', $newDictionary->get('smoke'));
71 | }
72 |
73 | /** @test */
74 | public function canConvertDictionaryToArray()
75 | {
76 | $array = $this->dictionary->toArray();
77 |
78 | $this->assertArrayHasKey('job', $array);
79 | $this->assertEquals('programmer', $array['job']);
80 | }
81 |
82 | /** @test */
83 | public function canRemoveDataByIndex()
84 | {
85 | $this->dictionary->add('post', 'Lorem ipsum dolor sit amet...');
86 | $this->dictionary->remove('post');
87 | $this->assertArrayNotHasKey('post', $this->dictionary->toArray());
88 | }
89 |
90 | /** @test */
91 | public function canFilterDataByKeyAndValue()
92 | {
93 | $dictionary = new Dictionary('string', 'array');
94 | $dictionary->add('books', ['Code smart', 'JS the good parts', 'Laravel up and running']);
95 | $dictionary->add('videogames', ['Assasin Creed', 'God of war', 'Need for speed']);
96 |
97 | $newDictionary = $dictionary->filter(function ($key, $value) {
98 | return $key === 'videogames';
99 | });
100 |
101 | $this->assertNotNull($newDictionary);
102 | $this->assertArrayHasKey('videogames', $newDictionary->toArray());
103 | }
104 |
105 | /**
106 | * @test
107 | * @expectedException \OutOfRangeException
108 | * @expectedExceptionMessage You're trying to get data from an empty collection
109 | */
110 | public function canGetFirstElement()
111 | {
112 | $this->assertEquals('Max', $this->dictionary->first());
113 |
114 | $newDictionary = new Dictionary('string', 'int');
115 |
116 | $newDictionary->first(); // Here an InvalidOperationException is thrown!
117 | }
118 |
119 | /**
120 | * @test
121 | * @expectedException \OutOfRangeException
122 | * @expectedExceptionMessage You're trying to get data from an empty collection
123 | */
124 | public function canGetLastElement()
125 | {
126 | $this->assertEquals('23', $this->dictionary->last());
127 | $newDictionary = new Dictionary('string', 'int');
128 |
129 | $newDictionary->last(); // Here an InvalidOperationException is thrown!
130 | }
131 |
132 | /**
133 | * @test
134 | * @expectedException PHPCollections\Exceptions\InvalidOperationException
135 | */
136 | public function canUpdateElementByIndex()
137 | {
138 | $isUpdated = $this->dictionary->update('job', 'PHP developer');
139 |
140 | $this->assertTrue($isUpdated);
141 | $this->assertEquals('PHP developer', $this->dictionary->get('job'));
142 | $this->dictionary->update('height', '2.80'); // Here an InvalidOperationException is thrown!
143 | }
144 |
145 | /**
146 | * @test
147 | * @expectedException InvalidArgumentException
148 | */
149 | public function canMergeNewDataIntoNewDictionary()
150 | {
151 | $dictionary1 = new Dictionary('string', 'array');
152 | $dictionary1->add('english-spanish', ['one' => 'uno', 'two' => 'dos']);
153 |
154 | $translations = $dictionary1->merge(
155 | new Dictionary('string', 'array', ['english-japanese' => ['one' => 'ichi', 'two' => 'ni']])
156 | );
157 |
158 | $this->assertNotNull($translations);
159 | $this->assertCount(2, $translations);
160 | $this->assertArrayHasKey('english-spanish', $translations->toArray());
161 | $this->assertArrayHasKey('english-japanese', $translations->toArray());
162 |
163 | $dictionary2 = new Dictionary('string', 'string');
164 | $dictionary2->merge(
165 | new Dictionary('string', 'integer', ['one' => 1, 'two' => 2])
166 | ); // Here a InvalidOperationException is thrown!
167 | }
168 |
169 | /** @test */
170 | public function canGetKeyType()
171 | {
172 | $key = $this->dictionary->getKeyType();
173 |
174 | $this->assertInternalType('string', $key);
175 | }
176 |
177 | /** @test */
178 | public function canGetValueType()
179 | {
180 | $value = $this->dictionary->getValueType();
181 |
182 | $this->assertInternalType('string', $value);
183 | }
184 |
185 | /** @test */
186 | public function canSortByGivenRules()
187 | {
188 | $sortedDictionary = $this->dictionary->sort(function ($x, $y) {
189 | return strlen($x) <=> strlen($y);
190 | });
191 |
192 | $this->assertEquals('a little bit', $sortedDictionary->last());
193 | }
194 |
195 | /** @test */
196 | public function canIterateOverEachElement()
197 | {
198 | $this->dictionary->forEach(function (&$value, $key) {
199 | $value = $value.'x';
200 | });
201 |
202 | $this->assertEquals('Maxx', $this->dictionary->get('name'));
203 | $this->assertEquals('programmerx', $this->dictionary->get('job'));
204 | }
205 |
206 | /** @test */
207 | public function canCompareTwoDictionary()
208 | {
209 | $newDictionary = new Dictionary('string', 'string', [
210 | 'drink' => 'no',
211 | 'smoke' => 'no',
212 | 'dance' => 'a little bit',
213 | ]);
214 |
215 | $diffDictionary = $this->dictionary->diff($newDictionary);
216 |
217 | $this->assertInstanceOf(Dictionary::class, $diffDictionary);
218 | $this->assertEquals($diffDictionary->get('job'), 'programmer');
219 | $this->assertCount(4, $diffDictionary);
220 | }
221 |
222 | /** @test */
223 | public function canNotCompareTwoDictionaryOfDifferentKeyTypes()
224 | {
225 | $this->expectException('\PHPCollections\Exceptions\InvalidOperationException');
226 | $this->expectExceptionMessage('The key type for this Dictionary is string, you cannot pass a Dictionary with integer as key type');
227 |
228 | $newDictionary = new Dictionary(
229 | 'integer', 'string', [1 => 'one', 2 => 'two', 3 => 'three', 4 => 'four', 5 => 'five']
230 | );
231 |
232 | $diffDictionary = $this->dictionary->diff($newDictionary); // Here an InvalidOperationException is thrown!
233 | }
234 |
235 | /** @test */
236 | public function canNotCompareTwoDictionaryOfDifferentValueTypes()
237 | {
238 | $this->expectException('\PHPCollections\Exceptions\InvalidOperationException');
239 | $this->expectExceptionMessage('The value type for this Dictionary is string, you cannot pass a Dictionary with integer as value type');
240 |
241 | $newDictionary = new Dictionary(
242 | 'string', 'integer', ['one' => 1, 'two' => 2, 'three' => 3, 'four' => 4, 'five' => 5]
243 | );
244 |
245 | $diffDictionary = $this->dictionary->diff($newDictionary); // Here an InvalidOperationException is thrown!
246 | }
247 |
248 | /** @test */
249 | public function canNotCompareADictionaryAgainstAnotherTypeOfCollection()
250 | {
251 | $this->expectException('\PHPCollections\Exceptions\InvalidOperationException');
252 | $this->expectExceptionMessage('You should only compare a Dictionary against another Dictionary');
253 |
254 | $newDictionary = new GenericList(
255 | StdClass::class,
256 | new StdClass(['name' => 'John']),
257 | new StdClass(['name' => 'Carter'])
258 | );
259 |
260 | $diffDictionary = $this->dictionary->diff($newDictionary); // Here an InvalidOperationException is thrown!
261 | }
262 |
263 | /** @test */
264 | public function canSliceADictionary()
265 | {
266 | $this->assertCount(5, $this->dictionary->slice(2));
267 | $this->assertCount(5, $this->dictionary->slice(2, null));
268 | $this->assertCount(4, $this->dictionary->slice(2, 4));
269 | $this->assertNull((new Dictionary('string', 'string'))->slice(2));
270 | }
271 |
272 | /** @test */
273 | public function canCheckIfTheDictionaryContainsAGivenValue()
274 | {
275 | $this->assertTrue($this->dictionary->contains('Max'));
276 | $this->assertFalse($this->dictionary->contains('Almonte'));
277 | }
278 |
279 | /** @test */
280 | public function canCheckIfTwoDictionaryObjectsAreEqual()
281 | {
282 | $newDictionary = new Dictionary('string', 'string', [
283 | 'name' => 'Max',
284 | 'job' => 'programmer',
285 | 'drink' => 'no',
286 | 'smoke' => 'no',
287 | 'dance' => 'a little bit',
288 | 'drugs' => 'no',
289 | 'age' => '23',
290 | ]);
291 |
292 | $this->assertTrue($this->dictionary->equals($newDictionary));
293 | $this->assertFalse($this->dictionary->equals(new Dictionary('string', 'string')));
294 | }
295 |
296 | /** @test */
297 | public function canNotCheckIfAnDictionaryIsEqualToAnotherTypeOfCollection()
298 | {
299 | $this->expectException('\PHPCollections\Exceptions\InvalidOperationException');
300 | $this->expectExceptionMessage('You should only compare an Dictionary against another Dictionary');
301 | $this->dictionary->equals(new GenericList(StdClass::class));
302 | }
303 |
304 | /** @test */
305 | public function canSumANumericFieldOfTheDictionary()
306 | {
307 | $newList = new Dictionary(
308 | 'string', 'integer',
309 | [
310 | 'Kyle Lowry' => 18,
311 | 'Danny Green' => 12,
312 | 'Kawhi Leonard'=> 23,
313 | 'Paskal Siakam'=> 16,
314 | 'Serge Ibaka' => 14,
315 | ]
316 | );
317 | $totalPoints = $newList->sum(function ($pair) {
318 | return $pair->getValue();
319 | });
320 |
321 | $this->assertEquals(83, $totalPoints);
322 | }
323 |
324 | /** @test */
325 | public function canNotSumANonNumericFieldOfTheDictionary()
326 | {
327 | $newList = new Dictionary(
328 | 'string', 'integer',
329 | [
330 | 'Kyle Lowry' => 18,
331 | 'Danny Green' => 12,
332 | 'Kawhi Leonard'=> 23,
333 | 'Paskal Siakam'=> 16,
334 | 'Serge Ibaka' => 14,
335 | ]
336 | );
337 |
338 | $this->expectException('\PHPCollections\Exceptions\InvalidOperationException');
339 | $this->expectExceptionMessage('You cannot sum non-numeric values');
340 | $newList->sum(function ($pair) {
341 | return $pair->getKey();
342 | }); // Here an InvalidOperationException is thrown!
343 | }
344 |
345 | /** @test */
346 | public function itCanFillADictionarytWithData()
347 | {
348 | $this->dictionary->fill([
349 | 'first_key' => 'first_value',
350 | 'second_key' => 'second_value',
351 | ]);
352 |
353 | $this->assertCount(9, $this->dictionary);
354 | $this->expectException('\InvalidArgumentException');
355 | $this->expectExceptionMessage('The key type specified for this dictionary is string, you cannot pass an integer');
356 | $this->dictionary->fill([0 => true]);
357 | }
358 | }
359 |
--------------------------------------------------------------------------------
/tests/Unit/GenericListTest.php:
--------------------------------------------------------------------------------
1 | list = new GenericList(ArrayObject::class);
18 | $this->list->add(new ArrayObject(['name' => 'John']));
19 | $this->list->add(new ArrayObject(['name' => 'Finch']));
20 | $this->list->add(new ArrayObject(['name' => 'Shaw']));
21 | $this->list->add(new ArrayObject(['name' => 'Carter']));
22 | $this->list->add(new ArrayObject(['name' => 'Kara']));
23 | $this->list->add(new ArrayObject(['name' => 'Snow']));
24 | $this->list->add(new ArrayObject(['name' => 'Zoey']));
25 | $this->list->add(new ArrayObject(['name' => 'Cal']));
26 | $this->list->add(new ArrayObject(['name' => 'Lionel']));
27 | }
28 |
29 | /** @test */
30 | public function canCreateACollectionWithMultipleParameters()
31 | {
32 | $this->list = null;
33 | $this->list = new GenericList(
34 | ArrayObject::class,
35 | new ArrayObject(['name' => 'John']),
36 | new ArrayObject(['name' => 'Finch']),
37 | new ArrayObject(['name' => 'Shaw']),
38 | new ArrayObject(['name' => 'Carter'])
39 | );
40 |
41 | $this->assertInstanceOf(GenericList::class, $this->list);
42 | $this->assertCount(4, $this->list);
43 | }
44 |
45 | /**
46 | * @test
47 | */
48 | public function canAddAnElementToList()
49 | {
50 | $this->assertCount(9, $this->list);
51 | $this->list->add(new ArrayObject(['name' => 'Samaritan']));
52 | }
53 |
54 | /**
55 | * @test
56 | * @expectedException InvalidArgumentException
57 | * @expectedExceptionMessage The type specified for this collection is
58 | * ArrayObject, you cannot pass an object of type stdClass
59 | */
60 | public function canNotAddAnElementOfDifferentTypeToList()
61 | {
62 | $this->list->add(new StdClass()); // Here an InvalidArgumentException is thrown!
63 | }
64 |
65 | /** @test */
66 | public function canClearData()
67 | {
68 | $this->list->clear();
69 | $this->assertCount(0, $this->list);
70 | }
71 |
72 | /**
73 | * @test
74 | * @expectedException OutOfRangeException
75 | */
76 | public function canGetAnElementOfTheList()
77 | {
78 | $arrayObject = $this->list->get(2);
79 | $this->assertEquals('Shaw', $arrayObject->offsetGet('name'));
80 | $this->list->get(9); // Here an OutOfRangeException is thrown!
81 | }
82 |
83 | /**
84 | * @test
85 | * @expectedException OutOfRangeException
86 | */
87 | public function canRemoveAnElementOfTheList()
88 | {
89 | $this->list->remove(0);
90 | $this->assertCount(8, $this->list);
91 | $arrayObject = $this->list->get(0);
92 | $this->assertNotEquals('John', $arrayObject->offsetGet('name'));
93 | $this->list->remove(9); // Here an OutOfRangeException is thrown!
94 | }
95 |
96 | /** @test */
97 | public function canFilterElementsOfTheList()
98 | {
99 | $newList = $this->list->filter(function ($value, $key) {
100 | return strlen($value['name']) <= 4;
101 | });
102 |
103 | $this->assertEquals('John', $newList->get(0)->offsetGet('name'));
104 | $this->assertEquals('Finch', $newList->get(1)->offsetGet('name'));
105 |
106 | $anotherList = $this->list->filter(function ($value, $key) {
107 | return strlen($value['name']) > 10;
108 | });
109 |
110 | $this->assertNull($anotherList);
111 | }
112 |
113 | /** @test */
114 | public function canUpdateElementsOfTheListByMapping()
115 | {
116 | $newList = $this->list->map(function ($value) {
117 | $value['name'] = sprintf('%s %s', 'Sr.', $value['name']);
118 |
119 | return $value;
120 | });
121 | $this->assertEquals('Sr. John', $newList->get(0)->offsetGet('name'));
122 | }
123 |
124 | /** @test */
125 | public function canSortTheList()
126 | {
127 | $newList = $this->list->sort(function ($a, $b) {
128 | return $a->offsetGet('name') <=> $b->offsetGet('name');
129 | });
130 |
131 | $this->assertEquals('Cal', $newList->get(0)->offsetGet('name'));
132 | }
133 |
134 | /**
135 | * @test
136 | * @expectedException PHPCollections\Exceptions\InvalidOperationException
137 | */
138 | public function canGetReversedOrderList()
139 | {
140 | $reversedList = $this->list->reverse();
141 | $this->assertEquals('Lionel', $reversedList->get(0)->offsetGet('name'));
142 |
143 | $newList = new GenericList(ArrayObject::class);
144 | $newReversedList = $newList->reverse(); // Here an InvalidOperationException is thrown!
145 | }
146 |
147 | /**
148 | * @test
149 | * @expectedException PHPCollections\Exceptions\InvalidOperationException
150 | */
151 | public function canGetARandomValue()
152 | {
153 | $randElement = $this->list->rand();
154 | $this->assertArrayHasKey('name', $randElement);
155 |
156 | $newList = new GenericList(ArrayObject::class);
157 | $newList->rand(); // Here an InvalidOperationException is thrown!
158 | }
159 |
160 | /** @test */
161 | public function canCheckIfIndexExists()
162 | {
163 | $this->assertTrue($this->list->exists(0));
164 | $this->assertFalse($this->list->exists(20));
165 | }
166 |
167 | /** @test */
168 | public function canMergeNewDataIntoNewList()
169 | {
170 | $newList = $this->list->merge(
171 | new GenericList(
172 | ArrayObject::class,
173 | new ArrayObject(['name' => 'Max']),
174 | new ArrayObject(['name' => 'Alex'])
175 | )
176 | );
177 | $this->assertCount(11, $newList);
178 | $this->assertEquals('Max', $newList->get(9)->offsetGet('name'));
179 | }
180 |
181 | /** @test */
182 | public function canGetFirstElementOfList()
183 | {
184 | $arrayObject = $this->list->first();
185 | $this->assertEquals('John', $arrayObject->offsetGet('name'));
186 | }
187 |
188 | /** @test */
189 | public function canGetLastElementOfList()
190 | {
191 | $arrayObject = $this->list->last();
192 | $this->assertEquals('Lionel', $arrayObject->offsetGet('name'));
193 | }
194 |
195 | /**
196 | * @test
197 | */
198 | public function canUpdateAnElement()
199 | {
200 | $isUpdated = $this->list->update(0, new ArrayObject(['name' => 'Elliot']));
201 | $this->assertTrue($isUpdated);
202 | $this->assertEquals('Elliot', $this->list->get(0)->offsetGet('name'));
203 | }
204 |
205 | /** @test */
206 | public function canIterateOverEachElement()
207 | {
208 | $this->list->forEach(function ($value, $key) {
209 | $value->offsetSet('name', $value->offsetGet('name').'x');
210 | });
211 |
212 | $this->assertEquals('Johnx', $this->list->get(0)->offsetGet('name'));
213 | }
214 |
215 | /** @test */
216 | public function canCompareTwoGenericListOfTheSameType()
217 | {
218 | $newList = new GenericList(
219 | ArrayObject::class,
220 | new ArrayObject(['name' => 'John']),
221 | new ArrayObject(['name' => 'Finch']),
222 | new ArrayObject(['name' => 'Shaw']),
223 | new ArrayObject(['name' => 'Carter'])
224 | );
225 |
226 | $diffList = $this->list->diff($newList);
227 |
228 | $this->assertInstanceOf(GenericList::class, $diffList);
229 | $this->assertEquals('Kara', $diffList->first()['name']);
230 | $this->assertEquals('Lionel', $diffList->last()['name']);
231 | $this->assertCount(5, $diffList);
232 | }
233 |
234 | /** @test */
235 | public function canNotCompareTwoGenericListOfDifferentTypes()
236 | {
237 | $this->expectException('\PHPCollections\Exceptions\InvalidOperationException');
238 | $this->expectExceptionMessage('This is a collection of ArrayObject objects, you cannot pass a collection of StdClass objects');
239 |
240 | $newList = new GenericList(
241 | StdClass::class,
242 | new StdClass(['name' => 'John']),
243 | new StdClass(['name' => 'Finch']),
244 | new StdClass(['name' => 'Shaw']),
245 | new StdClass(['name' => 'Carter'])
246 | );
247 |
248 | $diffList = $this->list->diff($newList); // Here an InvalidOperationException is thrown!
249 | }
250 |
251 | /** @test */
252 | public function canNotCompareAGenericListAgainstAnotherTypeOfCollection()
253 | {
254 | $this->expectException('\PHPCollections\Exceptions\InvalidOperationException');
255 | $this->expectExceptionMessage('You should only compare a GenericList against another GenericList');
256 |
257 | $newList = new ArrayList([
258 | new StdClass(['name' => 'John']),
259 | new StdClass(['name' => 'Finch']),
260 | new StdClass(['name' => 'Shaw']),
261 | new StdClass(['name' => 'Carter']),
262 | ]);
263 |
264 | $diffList = $this->list->diff($newList); // Here an InvalidOperationException is thrown!
265 | }
266 |
267 | /** @test */
268 | public function canSliceAGenericList()
269 | {
270 | $this->assertCount(7, $this->list->slice(2));
271 | $this->assertCount(7, $this->list->slice(2, null));
272 | $this->assertCount(5, $this->list->slice(2, 5));
273 | $this->assertNull((new GenericList(\StdClass::class))->slice(2));
274 | }
275 |
276 | /** @test */
277 | public function canCheckIfTheGenericListContainsAGivenValue()
278 | {
279 | $this->assertTrue($this->list->contains(new ArrayObject(['name' => 'John'])));
280 | $this->assertFalse($this->list->contains(new ArrayObject(['name' => 'Max'])));
281 | }
282 |
283 | /** @test */
284 | public function canCheckIfTwoGenericListAreEqual()
285 | {
286 | $newList = new GenericList(
287 | ArrayObject::class,
288 | new ArrayObject(['name' => 'John']),
289 | new ArrayObject(['name' => 'Finch']),
290 | new ArrayObject(['name' => 'Shaw']),
291 | new ArrayObject(['name' => 'Carter']),
292 | new ArrayObject(['name' => 'Kara']),
293 | new ArrayObject(['name' => 'Snow']),
294 | new ArrayObject(['name' => 'Zoey']),
295 | new ArrayObject(['name' => 'Cal']),
296 | new ArrayObject(['name' => 'Lionel'])
297 | );
298 |
299 | $this->assertTrue($this->list->equals($newList));
300 | $this->assertFalse(
301 | $this->list->equals(new GenericList(ArrayObject::class, new ArrayObject(['name' => 'Max'])))
302 | );
303 | }
304 |
305 | /** @test */
306 | public function canNotCheckIfAGenericListIsEqualToAnotherTypeOfCollection()
307 | {
308 | $this->expectException('\PHPCollections\Exceptions\InvalidOperationException');
309 | $this->expectExceptionMessage('You should only compare an GenericList against another GenericList');
310 | $this->list->equals(new ArrayList(['first', 'second', 'third'])); // Here an InvalidOperationException is thrown!
311 | }
312 |
313 | /** @test */
314 | public function canSumANumericFieldOfTheGenericList()
315 | {
316 | $newList = new GenericList(
317 | ArrayObject::class,
318 | new ArrayObject(['name' => 'Kyle Lowry', 'points' => 18]),
319 | new ArrayObject(['name' => 'Danny Green', 'points' => 12]),
320 | new ArrayObject(['name' => 'Kawhi Leonard', 'points' => 23]),
321 | new ArrayObject(['name' => 'Paskal Siakam', 'points' => 16]),
322 | new ArrayObject(['name' => 'Serge Ibaka', 'points' => 14])
323 | );
324 | $totalPoints = $newList->sum(function ($arrayObject) {
325 | return $arrayObject->offsetGet('points');
326 | });
327 |
328 | $this->assertEquals(83, $totalPoints);
329 | }
330 |
331 | /** @test */
332 | public function canNotSumANonNumericFieldOfTheGenericList()
333 | {
334 | $newList = new GenericList(
335 | ArrayObject::class,
336 | new ArrayObject(['name' => 'Kyle Lowry', 'points' => 18]),
337 | new ArrayObject(['name' => 'Danny Green', 'points' => 12]),
338 | new ArrayObject(['name' => 'Kawhi Leonard', 'points' => 23]),
339 | new ArrayObject(['name' => 'Paskal Siakam', 'points' => 16]),
340 | new ArrayObject(['name' => 'Serge Ibaka', 'points' => 14])
341 | );
342 |
343 | $this->expectException('\PHPCollections\Exceptions\InvalidOperationException');
344 | $this->expectExceptionMessage('You cannot sum non-numeric values');
345 | $newList->sum(function ($arrayObject) {
346 | return $arrayObject->offsetGet('name');
347 | }); // Here an InvalidOperationException is thrown!
348 | }
349 |
350 | /** @test */
351 | public function itCanFillAGenericListWithData()
352 | {
353 | $this->list->fill([
354 | new ArrayObject(['name' => 'Max']),
355 | new ArrayObject(['name' => 'John']),
356 | ]);
357 |
358 | $this->assertCount(11, $this->list);
359 | $this->expectException('\InvalidArgumentException');
360 | $this->expectExceptionMessage('The type specified for this collection is ArrayObject, you cannot pass an object of type stdClass');
361 | $this->list->fill([new StdClass()]);
362 | }
363 | }
364 |
--------------------------------------------------------------------------------
/tests/Unit/InvalidOperationExceptionTest.php:
--------------------------------------------------------------------------------
1 | assertEquals('The Exception is catchable!', $e->getMessage());
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/tests/Unit/StackTest.php:
--------------------------------------------------------------------------------
1 | stack = new Stack('string');
15 | $this->stack->push('John');
16 | $this->stack->push('Harold');
17 | $this->stack->push('Sameen');
18 | $this->stack->push('Joss');
19 | $this->stack->push('Cal');
20 | $this->stack->push('Peter');
21 | $this->stack->push('Samantha');
22 | }
23 |
24 | /**
25 | * @test
26 | * @expectedException InvalidArgumentException
27 | */
28 | public function cannotPushUncompatibleValueToStack()
29 | {
30 | $this->stack->push(['color' => 'green']);
31 | }
32 |
33 | /** @test */
34 | public function canPushAnElement()
35 | {
36 | $newElement = $this->stack->push('Zoey');
37 | $this->assertEquals($newElement, $this->stack->peek());
38 | }
39 |
40 | /** @test */
41 | public function canPeekLastElement()
42 | {
43 | $lastElement = $this->stack->peek();
44 | $this->assertEquals('Samantha', $lastElement);
45 | }
46 |
47 | /** @test */
48 | public function canPopLastElement()
49 | {
50 | $lastElement = $this->stack->pop();
51 | $this->assertEquals('Samantha', $lastElement);
52 | $this->assertEquals('Peter', $this->stack->peek());
53 | }
54 |
55 | /** @test */
56 | public function canCountTheElements()
57 | {
58 | $this->assertCount(7, $this->stack);
59 | }
60 |
61 | /** @test */
62 | public function canCheckIfTheStackIsEmpty()
63 | {
64 | $newStack = new Stack('string');
65 | $this->assertTrue($newStack->isEmpty());
66 | $this->assertFalse($this->stack->isEmpty());
67 | }
68 |
69 | /** @test */
70 | public function canClearStack()
71 | {
72 | $this->stack->clear();
73 | $this->assertTrue($this->stack->isEmpty());
74 | }
75 | }
76 |
--------------------------------------------------------------------------------