├── _config.yml
├── .gitignore
├── config
└── arrayed.php
├── src
├── Types
│ └── Undefined.php
├── Exceptions
│ └── ArrayedException.php
├── Providers
│ └── ArrayedServiceProvider.php
├── Interfaces
│ └── ArrayedInterface.php
├── Traits
│ └── ArrayPrefix.php
└── Arrayed.php
├── .travis.yml
├── dockerizer.sh
├── phpcs.xml
├── docker-compose.yml
├── phpunit.xml
├── Dockerfile
├── .github
└── workflows
│ └── ci.yml
├── LICENSE
├── Helpers
└── helpers.php
├── composer.json
├── docs
└── ArrayMethods.md
├── tests
├── ArrayPrefixTraitTest.php
└── ArrayedTest.php
└── README.md
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-minimal
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .bash_history
2 | /vendor
3 | .phpunit.result.cache
4 | /.idea
5 | .vscode
6 | .composer
7 | composer.lock
--------------------------------------------------------------------------------
/config/arrayed.php:
--------------------------------------------------------------------------------
1 | '\\Illuminate\\Support\\Collection',
6 | ];
--------------------------------------------------------------------------------
/src/Types/Undefined.php:
--------------------------------------------------------------------------------
1 |
2 |
3 | Arrayed CodeSniffer config file
4 |
5 |
6 |
7 | ./src
8 | ./tests
9 |
10 | */vendor/*
11 | *.(css|js|sh|phar|json|lock|cache|yml|Dockerfile|md)
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3"
2 |
3 | services:
4 | arrayed:
5 | build:
6 | context: .
7 | dockerfile: Dockerfile
8 | container_name: arrayed
9 | restart: unless-stopped
10 | tty: true
11 | working_dir: /var/www/html
12 | environment:
13 | SERVICE_TAGS: dev
14 | SERVICE_NAME: arrayed
15 | volumes:
16 | - ./:/var/www/html
17 | networks:
18 | - arrayed-network
19 |
20 | #Docker Networks
21 | networks:
22 | arrayed-network:
23 | driver: bridge
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 | ./tests/
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/Providers/ArrayedServiceProvider.php:
--------------------------------------------------------------------------------
1 | publishes([
19 | __DIR__ . '/../../config/arrayed.php' => config_path('arrayed.php'),
20 | ], 'arrayed');
21 |
22 | $this->app->bind(ArrayedInterface::class, Arrayed::class);
23 | }
24 |
25 | public function register()
26 | {
27 | $this->mergeConfigFrom(__DIR__ . '/../../config/arrayed.php', 'arrayed');
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | # Set master image
2 | FROM php:7.2-fpm-alpine
3 |
4 | # Copy composer.lock and composer.json
5 | COPY composer.json /var/www/html/
6 |
7 | # Set working directory
8 | WORKDIR /var/www/html
9 |
10 | # Install Additional dependencies
11 | RUN apk update && apk add --no-cache \
12 | build-base shadow vim curl \
13 | php7 \
14 | php7-fpm \
15 | php7-common \
16 | php7-mcrypt \
17 | php7-mbstring \
18 | php7-xml \
19 | php7-openssl \
20 | php7-json \
21 | php7-phar \
22 | php7-zip \
23 | php7-gd \
24 | php7-dom \
25 | php7-session \
26 | php7-zlib
27 |
28 | # Add and Enable PHP-PDO Extenstions
29 |
30 | # Install PHP Composer
31 | RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
32 |
33 | # Remove Cache
34 | RUN rm -rf /var/cache/apk/*
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: PHP Composer
2 |
3 | on:
4 | push:
5 | branches: [ "master" ]
6 | pull_request:
7 | branches: [ "master" ]
8 |
9 | permissions:
10 | contents: read
11 |
12 | jobs:
13 | build:
14 |
15 | runs-on: ubuntu-latest
16 |
17 | steps:
18 | - uses: actions/checkout@v4
19 |
20 | - name: Validate composer.json and composer.lock
21 | run: composer validate --strict
22 |
23 | - name: Cache Composer packages
24 | id: composer-cache
25 | uses: actions/cache@v3
26 | with:
27 | path: vendor
28 | key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
29 | restore-keys: |
30 | ${{ runner.os }}-php-
31 |
32 | - name: Install dependencies
33 | run: composer install --prefer-dist --no-progress
34 |
35 | # Add a test script to composer.json, for instance: "test": "vendor/bin/phpunit"
36 | # Docs: https://getcomposer.org/doc/articles/scripts.md
37 |
38 | - name: Run test suite
39 | run: vendor/bin/phpunit
40 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 transprime-research
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Helpers/helpers.php:
--------------------------------------------------------------------------------
1 | Up to firs level without Laravel config
24 | *
25 | * @param $value
26 | * @param null $default
27 | * @return mixed
28 | */
29 | function configured($value, $default = null)
30 | {
31 | if (function_exists('config')) {
32 | return config($value, $default);
33 | }
34 |
35 | $keys = explode('.', $value);
36 |
37 | $data = require (__DIR__.'/../config/'.$keys[0].'.php');
38 |
39 | foreach ($keys as $index => $key) {
40 | if ($index < 1) {
41 | continue;
42 | }
43 |
44 | return $data[$key] ?? $default;
45 | }
46 |
47 | return $data;
48 | }
49 | }
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "transprime-research/arrayed",
3 | "description": "PHP Array(ed) in object oriented way wrapping PHP arrays in a consistent manner.",
4 | "license": "MIT",
5 | "keywords": [
6 | "php",
7 | "Arrayed",
8 | "Arrays",
9 | "Array",
10 | "Helpers",
11 | "Laravel"
12 | ],
13 | "homepage": "https://transprime-research.github.io/arrayed/",
14 | "support": {
15 | "issues": "https://github.com/transprime-research/arrayed/issues",
16 | "source": "https://github.com/transprime-research/arrayed/issues"
17 | },
18 | "authors": [
19 | {
20 | "name": "Oluwatobi Samuel Omisakin",
21 | "email": "omisakin.oluwatobi@gmail.com"
22 | }
23 | ],
24 | "require": {
25 | "php": ">=7.4",
26 | "transprime-research/piper": "^2.0"
27 | },
28 | "require-dev": {
29 | "phpunit/phpunit": ">=8.0",
30 | "squizlabs/php_codesniffer": "3.*",
31 | "illuminate/support": ">=5.5",
32 | "ext-json": "*",
33 | "symfony/var-dumper": "^6.4"
34 | },
35 | "autoload": {
36 | "psr-4": {
37 | "Transprime\\Arrayed\\": "src"
38 | },
39 | "files": [
40 | "Helpers/helpers.php"
41 | ]
42 | },
43 | "autoload-dev": {
44 | "psr-4": {
45 | "Transprime\\Arrayed\\Tests\\": "tests/"
46 | }
47 | },
48 | "minimum-stability": "dev",
49 | "prefer-stable": true,
50 | "extra": {
51 | "laravel": {
52 | "providers": [
53 | "Transprime\\Arrayed\\Providers\\ArrayedServiceProvider"
54 | ]
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/Interfaces/ArrayedInterface.php:
--------------------------------------------------------------------------------
1 | setResult(array_change_key_case($this->getWorkableItem(), $case));
25 | }
26 |
27 | public function chunk(int $size, bool $preserve_keys = false): ArrayedInterface
28 | {
29 | return $this->setResult(array_chunk($this->getWorkableItem(), $size, $preserve_keys));
30 | }
31 |
32 | public function column($column, $index_key = null): ArrayedInterface
33 | {
34 | return $this->setResult(array_column($this->getWorkableItem(), $column, $index_key));
35 | }
36 |
37 | public function countValues(): ArrayedInterface
38 | {
39 | return $this->setResult(array_count_values($this->getWorkableItem()));
40 | }
41 |
42 | public function diffAssoc(array $array2, array ...$_): ArrayedInterface
43 | {
44 | return $this->setResult(array_diff_assoc($this->getWorkableItem(), $array2, ...$_));
45 | }
46 |
47 | public function diff(array $array2, array ...$_): ArrayedInterface
48 | {
49 | return $this->setResult(array_diff($this->getWorkableItem(), $array2, ...$_));
50 | }
51 |
52 | public function reverse(bool $preserve_keys = false): ArrayedInterface
53 | {
54 | return $this->setResult(array_reverse($this->getWorkableItem(), $preserve_keys));
55 | }
56 |
57 | public function diffUassoc(callable $key_compare_func, array $array2, array ...$_): ArrayedInterface
58 | {
59 | return $this->setResult(array_diff_uassoc($this->getWorkableItem(), $array2, ...$_, ...[$key_compare_func]));
60 | }
61 |
62 | public function diffKey(array $array2, array ...$_): ArrayedInterface
63 | {
64 | return $this->setResult(array_diff_key($this->getWorkableItem(), $array2, ...$_));
65 | }
66 |
67 | public function walk(callable $callable, $arg = null)
68 | {
69 | $workableItem = $this->getWorkableItem();
70 | array_walk($workableItem, function (&$value, $key, $arg) use ($callable) {
71 | $value = $callable($value, $key, $arg);
72 | }, $arg);
73 |
74 | return $this->setResult($workableItem);
75 | }
76 |
77 |
78 | public function walkRecursive(callable $callable, $arg = null)
79 | {
80 | $workableItem = $this->getWorkableItem();
81 | array_walk_recursive($workableItem, function (&$value, $key, $arg) use ($callable) {
82 | $value = $callable($value, $key, $arg);
83 | }, $arg);
84 |
85 | return $this->setResult($workableItem);
86 | }
87 |
88 | public function search($needle, bool $strict = true, $default = null)
89 | {
90 | if ($needle instanceof \Closure) {
91 | $result = $this
92 | ->copy()
93 | ->filter(fn($value, $key) => $needle($value, $key))
94 | ->keys(false);
95 |
96 | return $result->empty() ? $default : $result->offsetGet(0);
97 | }
98 |
99 |
100 | $result = array_search($needle, $this->getWorkableItem(), $strict);
101 |
102 | if ($result === false) {
103 | return $default;
104 | }
105 |
106 | return $result;
107 | }
108 |
109 |
110 | /**
111 | * Like php array_key_exists, this instead search if (one or more) keys exists in the array
112 | *
113 | * @param array $needles - keys to look for in the array
114 | * @param bool $all - [Optional] if false then checks if at least one key is found
115 | * @return bool true if the needle(s) is found else false
116 | */
117 | public function keysExists(array $needles, bool $all = true): bool
118 | {
119 | $size = arrayed($needles)->count();
120 | $intersect = $this->keys()->intersect($needles);
121 |
122 | return $all
123 | ? ($intersect->count() === $size)
124 | : (!$intersect->empty());
125 | }
126 |
127 | /**
128 | * @return ArrayedInterface|mixed
129 | */
130 | public function head(bool $preserveKeys = false)
131 | {
132 | return self::makeArrayed(
133 | $this->when($this->getWorkableItem())
134 | ->slice(0, 1, $preserveKeys)
135 | ->values()
136 | ->offsetGet(0)
137 | );
138 | }
139 |
140 | public function tail(): ArrayedInterface
141 | {
142 | return $this->when($this->getWorkableItem())
143 | ->slice(1);
144 | }
145 |
146 | private function when($truthyValue, $default = Undefined::class)
147 | {
148 | if ($truthyValue) {
149 | return $this;
150 | }
151 |
152 | if ($default === Undefined::class || $default instanceof Undefined) {
153 | throw new \InvalidArgumentException('Value cannot be resolved');
154 | }
155 |
156 | return $this->setResult($default);
157 | }
158 |
159 | /**
160 | * Forward the calls to `array_*` that is not yet implemented
161 | *
162 | * Assumption is for those array method that accepts the initial array as the first value
163 | * @param $name
164 | * @param $arguments
165 | * @return mixed
166 | * @throws ArrayedException
167 | */
168 | public function __call($name, $arguments)
169 | {
170 | // See: https://stackoverflow.com/a/57833019/5704410
171 | $methodName = strtolower(preg_replace("/([a-z])([A-Z])/", "$1_$2", $name));
172 | $methodName = 'array_' . $methodName;
173 |
174 | if (function_exists($methodName)) {
175 | $result = $methodName($this->getWorkableItem(), ...$arguments);
176 |
177 | return is_array($result)
178 | ? $this->setResult($result)
179 | : $result;
180 | }
181 |
182 | throw new ArrayedException(sprintf('Method %s cannot be resolved', $name));
183 | }
184 | }
185 |
--------------------------------------------------------------------------------
/src/Arrayed.php:
--------------------------------------------------------------------------------
1 | raw = $this->argumentsToArray(...$values);
25 |
26 | $this->setResult(new Undefined());
27 | }
28 |
29 | private function argumentsToArray(...$values): array
30 | {
31 | if (func_num_args() === 1 && is_array($values[0])) {
32 | return $values[0];
33 | }
34 |
35 | if (func_num_args() === 1 && $values[0] instanceof ArrayedInterface) {
36 | return $values[0]->toArray();
37 | }
38 |
39 | return $values;
40 | }
41 |
42 | public static function on(...$values): ArrayedInterface
43 | {
44 | return new static($values);
45 | }
46 |
47 | public function __invoke(callable $callable = null)
48 | {
49 | return $this->result($callable);
50 | }
51 |
52 | public function map($callback, ...$_): ArrayedInterface
53 | {
54 | return $this->setResult(array_map($callback, $this->getWorkableItem(), ...$_));
55 | }
56 |
57 | public function filter(Closure $callback = null, int $flag = ARRAY_FILTER_USE_BOTH): ArrayedInterface
58 | {
59 | if ($callback) {
60 | return $this->setResult(array_filter($this->getWorkableItem(), $callback, $flag));
61 | }
62 |
63 | return $this->setResult(array_filter($this->getWorkableItem()));
64 | }
65 |
66 | public function reduce($function, $initial = null): ArrayedInterface
67 | {
68 | return $this->setResult(array_reduce($this->getWorkableItem(), $function, $initial));
69 | }
70 |
71 | public function merge(array $array2 = null, ...$_): ArrayedInterface
72 | {
73 | return $this->setResult(array_merge($this->getWorkableItem(), $array2, ...$_));
74 | }
75 |
76 | public function mergeRecursive(...$_): ArrayedInterface
77 | {
78 | return $this->setResult(array_merge_recursive($this->getWorkableItem(), ...$_));
79 | }
80 |
81 | public function flip(): ArrayedInterface
82 | {
83 | return $this->setResult(array_flip($this->getWorkableItem()));
84 | }
85 |
86 | public function intersect(array $array2, ...$_): ArrayedInterface
87 | {
88 | return $this->setResult(array_intersect($this->getWorkableItem(), $array2, ...$_));
89 | }
90 |
91 | public function values(): ArrayedInterface
92 | {
93 | return $this->setResult(array_values($this->getWorkableItem()));
94 | }
95 |
96 | public function keys($overwrite = true): ArrayedInterface
97 | {
98 | $keys = array_keys($this->getWorkableItem());
99 |
100 | if (!$overwrite) {
101 | return $this->makeArrayed($keys);
102 | }
103 |
104 | return $this->setResult($keys);
105 | }
106 |
107 | public function offsetGet($offset)
108 | {
109 | return $this->makeArrayed($this->getWorkableItem()[$offset]);
110 | }
111 |
112 | public function offsetSet($offset, $value): ArrayedInterface
113 | {
114 | return $this->merge([$offset => $value]);
115 | }
116 |
117 | public function offsetUnset($offset): ArrayedInterface
118 | {
119 | $item = $this->getWorkableItem();
120 |
121 | unset($item[$offset]);
122 |
123 | return $this->setResult($item);
124 | }
125 |
126 | //Scalar returns
127 |
128 | public function sum(): int
129 | {
130 | return array_sum($this->getWorkableItem());
131 | }
132 |
133 | public function contains($needle, bool $strict = false): bool
134 | {
135 | return in_array($needle, $this->getWorkableItem(), $strict);
136 | }
137 |
138 | public function isArray(): bool
139 | {
140 | return is_array($this->getWorkableItem());
141 | }
142 |
143 | public function keyExists($key): bool
144 | {
145 | return array_key_exists($key, $this->getWorkableItem());
146 | }
147 |
148 | public function offsetExists($offset): bool
149 | {
150 | return $this->keyExists($offset);
151 | }
152 |
153 | public function empty(): bool
154 | {
155 | return empty($this->getWorkableItem());
156 | }
157 |
158 | public function count(): int
159 | {
160 | return count($this->getWorkableItem());
161 | }
162 |
163 | //Getters to end chained calls
164 |
165 | public function getIterator()
166 | {
167 | return new ArrayIterator($this->getWorkableItem());
168 | }
169 |
170 | public function pipe(callable $action, ...$parameters)
171 | {
172 | return $this->setResult(
173 | piper($this->getWorkableItem())->to($action, ...$parameters)()
174 | );
175 | }
176 |
177 | private function setResult($value)
178 | {
179 | $this->result = $value;
180 |
181 | return $this;
182 | }
183 |
184 | public function result(callable $callable = null)
185 | {
186 | return $callable ? $callable($this->result) : $this->getWorkableItem();
187 | }
188 |
189 | private function getWorkableItem(bool $asArray = false)
190 | {
191 | if ($this->result instanceof Undefined) {
192 | return $this->raw;
193 | }
194 |
195 | if ($asArray && !is_array($this->result)) {
196 | return (array)$this->result;
197 | }
198 |
199 | return $this->result;
200 | }
201 |
202 | private static function makeArrayed($data)
203 | {
204 | return is_array($data) ? new static($data) : $data;
205 | }
206 |
207 | public function raw(): array
208 | {
209 | return $this->raw;
210 | }
211 |
212 | /**
213 | * @inheritDoc
214 | */
215 | public function initial(): array
216 | {
217 | return $this->raw;
218 | }
219 |
220 | public function __toString(): string
221 | {
222 | return json_encode($this->getWorkableItem(true));
223 | }
224 |
225 | public function toArray(): array
226 | {
227 | return $this->walkRecursive(
228 | function ($value) {
229 | return $value instanceof ArrayedInterface ? $value->getWorkableItem() : $value;
230 | }
231 | )->result();
232 | }
233 |
234 | /**
235 | * @inheritDoc
236 | */
237 | public function jsonSerialize()
238 | {
239 | return $this->getWorkableItem(true);
240 | }
241 |
242 | public function copy(): ArrayedInterface
243 | {
244 | return new static($this->result());
245 | }
246 |
247 | public function tap(Closure $closure): ArrayedInterface
248 | {
249 | function_exists('tap') ? tap($this->copy(), $closure) : $closure($this->copy());
250 |
251 | return $this;
252 | }
253 |
254 | /**
255 | * @param $with
256 | * @return mixed
257 | * @throws ArrayedException
258 | */
259 | public function collect(...$with)
260 | {
261 | $collectionClass = $this->getConfig('collection_class');
262 |
263 | if ($collectionClass && class_exists($collectionClass)) {
264 | return new $collectionClass($this->copy()->merge($this->argumentsToArray(...$with))->result());
265 | }
266 |
267 | throw new ArrayedException('Collection class is not set or does not exist');
268 | }
269 |
270 | private function getConfig($item)
271 | {
272 | return configured("arrayed.$item", null);
273 | }
274 | }
275 |
--------------------------------------------------------------------------------
/tests/ArrayPrefixTraitTest.php:
--------------------------------------------------------------------------------
1 | assertEquals(
14 | ['ABC' => 'cde'],
15 | arrayed(['abc' => 'cde'])->changeKeyCase(CASE_UPPER)->result()
16 | );
17 | }
18 |
19 | public function testChunk()
20 | {
21 | $this->assertEquals(
22 | [[1, 2], [3, 4]],
23 | arrayed(1, 2, 3, 4)->chunk(2)->result()
24 | );
25 | }
26 |
27 | public function testMap()
28 | {
29 | $array1 = [1, 2];
30 | $array2 = ['one', 'two'];
31 |
32 | $this->assertEquals(
33 | ['ONE', 'TWO'],
34 | arrayed($array2)
35 | ->map(function ($value) {
36 | return strtoupper($value);
37 | })->result()
38 | );
39 |
40 | $this->assertEquals(
41 | [
42 | [1 => 'one'],
43 | [2 => 'two'],
44 | ],
45 | arrayed($array1)
46 | ->map(function ($first, $second) {
47 | return [$first => $second];
48 | }, $array2)
49 | ->result()
50 | );
51 |
52 | $this->assertEquals(
53 | [
54 | [1, 'one'],
55 | [2, 'two'],
56 | ],
57 | arrayed($array1)->map(null, $array2)->result()
58 | );
59 | }
60 |
61 | public function testColumn()
62 | {
63 | $array = [
64 | ['a' => 1, 'b' => 4],
65 | ['a' => 2, 'b' => 3],
66 | ];
67 |
68 | $this->assertEquals(
69 | [4, 3],
70 | arrayed($array)->column('b')->result()
71 | );
72 | }
73 |
74 | public function testCountValues()
75 | {
76 | $this->assertEquals(
77 | ['a' => 2, 'b' => 2, 1 => 1, 4 => 1],
78 | arrayed(['a', 1, 'b', 4, 'b', 'a'])->countValues()->result()
79 | );
80 | }
81 |
82 | public function testDiffAssoc()
83 | {
84 | $array2 = ['a' => 2, 'b' => 2];
85 | $this->assertEquals(
86 | ['c' => 3],
87 | arrayed(['a' => 2, 'c' => 3, 'b' => 2])->diffAssoc($array2)->result()
88 | );
89 | }
90 |
91 | public function testDiff()
92 | {
93 | $array2 = ['a', 'b'];
94 | $this->assertEquals(
95 | ['c'],
96 | arrayed(['a', 'c', 'b'])->diff($array2)->values()->result()
97 | );
98 | }
99 |
100 | public function testKeysExists()
101 | {
102 | $this->assertEquals(
103 | true,
104 | arrayed(['a' => 'b', 'c' => 'd'])->keysExists(['a', 'c'])
105 | );
106 | }
107 |
108 | public function testReverse()
109 | {
110 | $this->assertEquals(
111 | ['c' => 'd', 'a' => 'b'],
112 | arrayed(['a' => 'b', 'c' => 'd'])->reverse()->result()
113 | );
114 | }
115 |
116 | public function testDiffUassoc()
117 | {
118 | $first = ['a' => 'b', 'c' => 'd'];
119 | $second = ['2' => 'b', 'c' => 'd'];
120 | $third = ['2' => 'b', 'k' => 'd'];
121 | $callback = function ($first, $second) {
122 | return $first === $second;
123 | };
124 |
125 | $this->assertEquals(
126 | array_diff_uassoc($first, $second, $callback),
127 | arrayed($first)->diffUassoc($callback, $second)->result()
128 | );
129 |
130 | $this->assertEquals(
131 | array_diff_uassoc($first, $second, $third, $callback),
132 | arrayed($first)->diffUassoc($callback, $second, $third)->result()
133 | );
134 | }
135 |
136 | public function testDiffKey()
137 | {
138 | $first = ['a' => 'b', 'c' => 'd'];
139 | $second = ['2' => 'b', 'c' => 'd'];
140 | $third = ['2' => 'b', 'k' => 'd', 'm' => 'a'];
141 | $fourth = ['m' => 'b', 'h' => 'd', 's' => 'a'];
142 |
143 | $this->assertEquals(
144 | array_diff_key($first, $second),
145 | arrayed($first)->diffKey($second)->result()
146 | );
147 |
148 | $this->assertEquals(
149 | array_diff_key($first, $second, $third, $fourth),
150 | arrayed($first)->diffKey($second, $third, $fourth)->result()
151 | );
152 | }
153 |
154 | public function testWalk(): void
155 | {
156 | $data = ['a' => 'b', 'c' => 'd'];
157 |
158 | $this->assertEquals(
159 | ['a' => 'b-1', 'c' => 'd-1'],
160 | arrayed($data)->walk(function ($value, $key) {
161 | return $value . '-1';
162 | })
163 | ->result()
164 | );
165 | }
166 |
167 | public function testWalkRecursive(): void
168 | {
169 | $data = ['a' => 'b', 'c' => ['d' => 'e']];
170 |
171 | $this->assertEquals(
172 | ['a' => 'b-1', 'c' => ['d' => 'e-1']],
173 | arrayed($data)
174 | ->walkRecursive(function ($value, $key) {
175 | return $value . '-1';
176 | })
177 | ->result()
178 | );
179 | }
180 |
181 | public function testUnImplementedArrayPrefixFunction()
182 | {
183 | // array_combine
184 | $keys = ['a', 'b'];
185 | $values = ['name', 'data'];
186 |
187 | $this->assertEquals(
188 | array_combine($keys, $values),
189 | arrayed($keys)->combine($values)->result()
190 | );
191 |
192 | // array_pop
193 | $data = ['a' => 'b', 'c' => 'd'];
194 |
195 | $this->assertEquals(
196 | 'd',
197 | arrayed($data)->pop(),
198 | );
199 |
200 | // array_shift.
201 | $this->assertEquals(
202 | 'b',
203 | $arr = arrayed($data)->shift(),
204 | );
205 | }
206 |
207 | public function testHead(): void
208 | {
209 | $data = ['a', 'b', 'c', 'd'];
210 |
211 | $this->assertSame(
212 | 'a',
213 | arrayed($data)->head(),
214 | );
215 |
216 | $data = ['a' => 'b', 'c' => 'd'];
217 |
218 | $this->assertSame(
219 | 'b',
220 | arrayed($data)->head(),
221 | );
222 |
223 | // Test empty.
224 | $this->expectException(\InvalidArgumentException::class);
225 |
226 | arrayed([])->head();
227 | }
228 |
229 | public function testTail(): void
230 | {
231 | $data = ['a', 'b', 'c', 'd'];
232 |
233 | $this->assertSame(
234 | ['b', 'c', 'd'],
235 | arrayed($data)->tail()->result(),
236 | );
237 |
238 | $data = ['a' => 'b', 'c' => 'd'];
239 |
240 | $this->assertSame(
241 | ['c' => 'd'],
242 | arrayed($data)->tail()->result(),
243 | );
244 |
245 | // Test empty.
246 | $this->expectException(\InvalidArgumentException::class);
247 |
248 | arrayed([])->tail();
249 | }
250 |
251 | public function testSearch(): void
252 | {
253 | $data = ['a', 'b', 'c', 'd'];
254 |
255 | $this->assertSame(
256 | 1,
257 | arrayed($data)->search('b'),
258 | );
259 |
260 | // When there is no matching value.
261 | $this->assertEquals(
262 | null,
263 | arrayed($data)->search('z'),
264 | );
265 |
266 | // With default value.
267 | $this->assertEquals(
268 | false,
269 | arrayed($data)->search('z', true, false),
270 | );
271 |
272 | // With callback.
273 | $this->assertEquals(
274 | 1,
275 | arrayed($data)->search(fn($value) => $value === 'b'),
276 | );
277 |
278 | // Empty with default.
279 | $this->assertEquals(
280 | 'no',
281 | arrayed([])->search(
282 | fn($value) => $value === 'b',
283 | true,
284 | 'no',
285 | ),
286 | );
287 |
288 | // With key, value, in callback.
289 | $this->assertEquals(
290 | 2,
291 | arrayed($data)->search(
292 | fn($value, $key) => $value === 'c' && $key == 2,
293 | ),
294 | );
295 |
296 | // Ensure initial result is not overwritten.
297 | $arrayed = arrayed($data);
298 |
299 | $searchResult = $arrayed->search(fn($value, $key) => $value === 'c' && $key === 2);
300 |
301 | $this->assertEquals(
302 | 2,
303 | $searchResult,
304 | );
305 |
306 | $this->assertEquals(
307 | ['a', 'b', 'c', 'd'],
308 | $arrayed->result(),
309 | );
310 | }
311 | }
312 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | ## About Arrayed
15 |
16 | Simple PHP Array(ed) in object oriented way wrapping [PHP Arrays](https://www.php.net/manual/en/ref.array.php) in a consistent manner.
17 | > No advanced stuff, just wrap PHP array_* functions and a little more. Do it Like a PRO :ok:
18 |
19 | > Looking for PHP Array on Steroid? See: https://laravel.com/docs/collections
20 |
21 | ## Quick Usage
22 |
23 | ```php
24 | arrayed(1, 2, 'ninja')
25 | ->filter(fn($val) => is_int($val)) // [1,2]
26 | ->map(fn($val) => $val + 1) // [2, 3]
27 | ->flip() // [0, 1]
28 | ->values() // [0, 1]
29 | ->sum(); // 1
30 | ```
31 |
32 | Instead of:
33 |
34 | ```php
35 | $result = array_filter([1, 2, 'ninja'], fn($val) => is_int($val));
36 | $result = array_map(fn($val) => $val + 1, $result);
37 | $result = array_flip($result);
38 | $result = array_values($result);
39 | $result = array_sum($result);
40 | ```
41 | > PS: You can still use the old `function() { return v; }`, `fn()` is the new short arrow function in PHP 7.4+ See: https://www.php.net/manual/en/functions.arrow.php
42 |
43 | ## Installation
44 |
45 | ```shell script
46 | composer require transprime-research/arrayed
47 | ```
48 |
49 | ## Requirement
50 | Minimum Requirement
51 | - PHP 7.2 +
52 | - Composer
53 |
54 | - For using `collect()` method, requires `illuminate\support` >= 5.5
55 | > Additionally on Laravel App, if `arrayed.php`'s config file doesn't get added automatically then run `php artisan vendor:publish --tag=arrayed` after installation.
56 |
57 | ## Other Usages
58 |
59 | Arrayed can be instantiated in 3 ways:
60 |
61 | ```php
62 | use Transprime\Arrayed\Arrayed;
63 |
64 | // Nifty
65 | arrayed(1, 2)->count();
66 |
67 | // Easier
68 | Arrayed::on(1, 2)->count();
69 |
70 | // Normal with (new instance)
71 | (new Arrayed(1,2))->count();
72 | ```
73 |
74 | Initial values can be passed in two ways:
75 |
76 | ```php
77 | //Non associative
78 | arrayed(1, 2);
79 |
80 | //OR
81 | arrayed([1, 2]);
82 |
83 | // For associative array, only this way
84 | arrayed(['a' => 1, 'b' => 2]);
85 | ```
86 |
87 | #### With Laravel & Laravel Collection
88 |
89 | Laravel Collections
90 |
91 | New: `collect()` method :tada:
92 |
93 | ```php
94 | arrayed(1,2)->collect(); // instance of Illuminate/Support/Collection
95 | arrayed(1,2)->collect(3, 4); //merged with first one to give [1, 2, 3, 4]
96 | ```
97 | > In the future, changing the default Collection class will possible by editing `config/arrayed.php`'s collection_class value
98 |
99 | Others:
100 |
101 | ```php
102 | collect(arrayed(1, 2, 3, 4));
103 |
104 | // Or
105 | new Collection(arrayed(1, 2, 3, 4));
106 |
107 | // Or
108 | Collection::make(arrayed(1, 2, 3, 4));
109 | ```
110 |
111 | Laravel Response accepts `Arrayed`:
112 |
113 | ```php
114 | response()->json(arrayed(1, 2, 3)->flip());
115 | ```
116 |
117 | #### Special methods
118 |
119 | New :tada: `tap()` method allows other actions on the last resulting `Arrayed` instance without mutating the last `Arrayed` result:
120 |
121 | ```php
122 | arrayed(1, 2, 3)
123 | ->tap(function ($arrd) {
124 | logger('Array has '.$arrd->count());
125 | });
126 | ```
127 |
128 | ## Others
129 |
130 | If any operation normally returns an array, the return value will give `Arrayed` instance so that other methods can be chained on them otherwise a non-array value is returned as can be seen that `sum()` returns an integer in the example below:
131 |
132 | Example:
133 |
134 | ```php
135 | arrayed(['a' => 1, 'b' => 2])
136 | ->values() // returns array, we can chain
137 | ->sum(); // returns an integer, we cannot chain
138 | ```
139 |
140 | You can work on a result (if its an array'ed value) by passing a closure/callable function to `result()` method:
141 |
142 | ```php
143 | arrayed(['a' => 'name', 'b' => 'age'])
144 | ->values()
145 | ->result(fn($val) => implode(',', $val)); //'name,age'
146 |
147 | //Or
148 |
149 | arrayed(['a' => 'name', 'b' => 'age'])
150 | ->values()(fn($val) => implode(',', $val)); //'name,age'
151 | ```
152 |
153 | Get the original array data with `raw()` method
154 |
155 | ```php
156 | arrayed([1, 2])->raw(); //[1,2]
157 | ```
158 |
159 | #### Piped calls
160 | As at now not all `array_*` functions have been implemented.
161 | `pipe()` method helps to call custom function on the array result.
162 |
163 | Such as `array_unique` used in this way:
164 |
165 | ```php
166 | arrayed(['a' => 'www', 'b' => 'dot', 'c' => 'www'])
167 | ->pipe('array_unique') // data is piped forward to `array_unique`
168 | ->flip()
169 | ->values()(); //['a', 'b']
170 | ```
171 | > The pipe method makes use of [Piper](https://github.com/transprime-research/piper) - A PHP functional pipe'ing
172 | > See `\Transprime\Arrayed\Tests\ArrayedTest`
173 |
174 | #### Proxied calls
175 |
176 | `array_*` methods that are not yet implemented are automatically proxied to call an array method with the assumption that they accept initial array first. Example is this:
177 |
178 | ```php
179 | // ->combine() method is not yet implemented
180 |
181 | arrayed(['a', 'b'])
182 | ->combine(['name', 'data'])
183 | ->result(); //['a' => 'name', 'b' => 'data']
184 | ```
185 |
186 | ## Coming Soon
187 |
188 | - Implement other `array_*` methods
189 |
190 | - pipe into Collection with `collectPipe`
191 |
192 | ```php
193 | use Illuminate\Support\Collection;
194 |
195 | arrayed(1,2,3)->collectPipe(function (Collection $collected) {
196 | return $collected->take(2)->all();
197 | })->keys();
198 | ```
199 |
200 | > Api implementation to be decided
201 |
202 | ## APIs
203 |
204 | These are the API's available:
205 |
206 | ```php
207 | static Arrayed::on(...$values): ArrayedInterface; //new instance of Arrayed
208 |
209 | Arrayed::map($callback): ArrayedInterface;
210 |
211 | Arrayed::filter($callback = null, int $flag = 0): ArrayedInterface;
212 |
213 | Arrayed::reduce($function, $initial = null): ArrayedInterface;
214 |
215 | Arrayed::merge(array $array2 = null, ...$_): ArrayedInterface;
216 |
217 | Arrayed::mergeRecursive(...$_): ArrayedInterface;
218 |
219 | Arrayed::flip(): ArrayedInterface;
220 |
221 | Arrayed::intersect(array $array2, ...$_): ArrayedInterface;
222 |
223 | Arrayed::values(): ArrayedInterface;
224 |
225 | Arrayed::keys($overwrite = true): ArrayedInterface;
226 |
227 | Arrayed::offsetGet($offset);
228 |
229 | Arrayed::offsetSet($offset, $value): ArrayedInterface;
230 |
231 | Arrayed::offsetUnset($offset): ArrayedInterface;
232 |
233 | Arrayed::sum(): int;
234 |
235 | Arrayed::contains($needle, bool $strict = false): bool;
236 |
237 | Arrayed::isArray(): bool;
238 |
239 | Arrayed::keyExists($key): bool;
240 |
241 | Arrayed::offsetExists($offset): bool;
242 |
243 | Arrayed::empty(): bool;
244 |
245 | Arrayed::count(): int;
246 |
247 | Arrayed::pipe(callable $action, ...$parameters);
248 |
249 | Arrayed::result(callable $callable = null);
250 |
251 | Arrayed::raw(): array;
252 |
253 | Arrayed::initial(): array; // Deprecated, use raw() instead
254 |
255 | Arrayed::tap(Closure $closure): ArrayedInterface;
256 |
257 | Arrayed::copy(): ArrayedInterface;
258 |
259 | Arrayed::collect(...$with): array;
260 |
261 | // Other Array_* methods
262 |
263 | Arrayed::changeKeyCase(int $case = null): ArrayedInterface;
264 |
265 | Arrayed::chunk(int $size, bool $preserve_keys = false): ArrayedInterface;
266 |
267 | Arrayed::column($column, $index_key = null): ArrayedInterface;
268 |
269 | Arrayed::countValues(): ArrayedInterface;
270 |
271 | Arrayed::diffAssoc(array $array2, array ...$_): ArrayedInterface;
272 |
273 | Arrayed::diff(array $array2, array ...$_): ArrayedInterface;
274 |
275 | Arrayed::reverse(bool $preserve_keys = false): ArrayedInterface;
276 |
277 | Arrayed::diffUassoc(callable $key_compare_func, array $array2, array ...$_): ArrayedInterface;
278 |
279 | Arrayed::diffKey(array $array2, array ...$_): ArrayedInterface;
280 |
281 | ```
282 |
283 | ## Additional Information
284 |
285 | This package is part of a series of "Code Dare"
286 |
287 | See other packages in this series here:
288 |
289 | - https://github.com/transprime-research/piper [A functional PHP pipe in object-oriented way]
290 | - https://github.com/omitobi/conditional [A smart PHP if...elseif...else statement]
291 | - https://github.com/transprime-research/attempt [A smart PHP try...catch statement]
292 | - https://github.com/omitobi/corbonate [A smart Carbon + Collection package]
293 | - https://github.com/omitobi/laravel-habitue [Jsonable Http Request(er) package with Collections response]
294 |
295 | ## Similar packages
296 |
297 | - https://github.com/cocur/chain - Very identical, but without Piper
298 | - https://github.com/bocharsky-bw/Arrayzy - Identical but with more actions and features
299 | - https://github.com/voku/Arrayy - Perform more than just an OOP style on Arrays
300 | - https://github.com/dantodev/php-array-tools - array tools plus collections
301 | - https://github.com/minwork/array - Pack of advanced PHP array functions
302 | - https://github.com/mblarsen/arrgh - A Sane PHP Array library with advance functions
303 | - More at: https://www.google.com/search?q=php+array+github
304 |
305 | ## Licence
306 |
307 | MIT (See LICENCE file)
308 |
--------------------------------------------------------------------------------
/tests/ArrayedTest.php:
--------------------------------------------------------------------------------
1 | assertIsObject(new Arrayed());
15 | }
16 |
17 | public function testIsArrayed()
18 | {
19 | $this->assertInstanceOf(ArrayedInterface::class, new Arrayed());
20 | $this->assertInstanceOf(ArrayedInterface::class, arrayed());
21 | $this->assertInstanceOf(ArrayedInterface::class, Arrayed::on());
22 | }
23 |
24 | public function testInitialDataIsCorrectlyRetrieved()
25 | {
26 | $data = ['1', 2];
27 | $data2 = ['1', 2];
28 |
29 | $this->assertSame(arrayed($data)->keys()->raw(), $data);
30 | $this->assertSame(arrayed(...$data2)->keys()->raw(), $data2);
31 | }
32 |
33 | public function testSum()
34 | {
35 | $this->assertEquals(3, arrayed(1, 2)->sum());
36 | $this->assertEquals(
37 | 5,
38 | arrayed(1, 2, 'ninja')
39 | ->filter(function ($val) {
40 | return is_int($val);
41 | })
42 | ->map(function ($val) {
43 | return $val + 1;
44 | })
45 | ->sum()
46 | );
47 | }
48 |
49 | public function testPassingAnArray()
50 | {
51 | $this->assertEquals(
52 | 5,
53 | arrayed([1, 2, 'ninja'])
54 | ->filter(function ($val) {
55 | return is_int($val);
56 | })
57 | ->map(function ($val) {
58 | return $val + 1;
59 | })
60 | ->sum()
61 | );
62 | }
63 |
64 | public function testReduce()
65 | {
66 | $this->assertEquals(
67 | 6,
68 | arrayed([1, 2, 3])
69 | ->reduce(function ($acc, $item) {
70 | return $acc + $item;
71 | }, 0)()
72 | );
73 |
74 | $this->assertEquals(
75 | 7,
76 | arrayed(1, 2)
77 | ->map(function ($i) {
78 | return $i + 1;
79 | })
80 | ->reduce(function ($v, $i) {
81 | return $v + $i;
82 | }, 2)()
83 | );
84 | }
85 |
86 | public function testOffsetMethods()
87 | {
88 | $this->assertEquals(
89 | 1,
90 | arrayed(['a' => 1, 'b' => 2])
91 | ->offsetGet('a')
92 | );
93 |
94 | $this->assertEquals(
95 | ['z' => 1],
96 | arrayed(['a' => ['z' => 1], 'b' => 2])
97 | ->offsetGet('a')()
98 | );
99 |
100 | $this->assertTrue(
101 | arrayed(['a' => ['z' => 1], 'b' => 2])
102 | ->offsetExists('b')
103 | );
104 |
105 | $this->assertEquals(
106 | 3,
107 | arrayed(['a' => ['z' => 1], 'b' => 2])
108 | ->offsetSet('c', 3)
109 | ->count()
110 | );
111 |
112 | $this->assertEquals(
113 | ['b' => 2],
114 | arrayed(['a' => ['z' => 1], 'b' => 2])
115 | ->offsetUnset('a')()
116 | );
117 | }
118 |
119 | public function testMergeMethod()
120 | {
121 | $this->assertCount(
122 | 4,
123 | arrayed(['a' => 1, 'b' => 2])
124 | ->merge(['z' => 26])
125 | ->merge(['c' => 2])()
126 | );
127 |
128 | $this->assertCount(
129 | 4,
130 | arrayed(['a' => 1, 'b' => 2])
131 | ->merge(['z' => 26], ['c' => 2])()
132 | );
133 |
134 | $names = arrayed(['cdd']);
135 | $names = arrayed($names)
136 | ->merge(['abc']);
137 |
138 | $this->assertEquals(
139 | array_merge(['cdd'], ['abc']),
140 | $names->toArray(),
141 | );
142 | }
143 |
144 | public function testAccessibleArray()
145 | {
146 | $this->assertCount(
147 | 2,
148 | arrayed(['a' => 1, 'b' => 2])
149 | );
150 |
151 | $this->assertEquals(
152 | 2,
153 | arrayed(['a' => 1, 'b' => 2])['b']
154 | );
155 |
156 | // Until its PHP 7.4
157 | // $this->assertCount(
158 | // 2,
159 | // [...arrayed([1, 2])]
160 | // );
161 |
162 | [$a,] = arrayed([1, 2]);
163 | $this->assertEquals(
164 | 1,
165 | $a
166 | );
167 |
168 | $this->assertTrue(
169 | arrayed([])->empty()
170 | );
171 | }
172 |
173 | public function testMergeRecursiveMethod()
174 | {
175 | $this->assertCount(
176 | 2,
177 | arrayed(['a' => 1, 'b' => 2])
178 | ->merge(['b' => 4])
179 | ->mergeRecursive(['b' => 5])
180 | ->offsetGet('b') //[4, 5]]
181 | );
182 | }
183 |
184 | public function testFlipMethod()
185 | {
186 | $this->assertEquals(
187 | 'b',
188 | arrayed(['a' => 1, 'b' => 2])
189 | ->flip()
190 | ->offsetGet(2) //b
191 | );
192 | }
193 |
194 | public function testIntersectMethod()
195 | {
196 | $this->assertCount(
197 | 1,
198 | arrayed(['a' => 'z', 'b' => 'y'])
199 | ->flip()
200 | ->intersect(['z' => 'a'])
201 | );
202 |
203 | $this->assertCount(
204 | 2,
205 | arrayed(['a' => 'z', 'b' => 'y', 'c'])
206 | ->intersect(arrayed(['a' => 'z', 'c', 'm'])())
207 | );
208 |
209 | $this->assertCount(
210 | 1,
211 | arrayed(['a' => 'z', 'b' => 'y', 'c'])
212 | ->flip()
213 | ->intersect(['a', 0], [0])
214 | );
215 |
216 | $this->assertCount(
217 | 1,
218 | arrayed(['a' => 'z', 'b' => 'y', 'c'])
219 | ->flip()
220 | ->intersect(['a', 0])
221 | ->intersect([0])
222 | );
223 | }
224 |
225 | public function testValuesMethod()
226 | {
227 | $this->assertEquals(
228 | ['a', 'b'],
229 | arrayed(['a' => 'z', 'b' => 'y'])
230 | ->flip()
231 | ->values()()
232 | );
233 |
234 | $this->assertSameSize(
235 | ['a', 'b'],
236 | arrayed(['a' => 'z', 'b' => 'y'])
237 | ->flip()
238 | ->values()
239 | );
240 | }
241 |
242 | public function testKeysMethod()
243 | {
244 | $this->assertEquals(
245 | ['z', 'y'],
246 | arrayed(['a' => 'z', 'b' => 'y'])
247 | ->flip()
248 | ->keys()()
249 | );
250 | }
251 |
252 | public function testContainsMethod()
253 | {
254 | $this->assertTrue(
255 | arrayed(['a' => 'z', 'b' => 'y'])
256 | ->contains('y')
257 | );
258 |
259 | $this->assertTrue(
260 | arrayed(['a' => 'www', 'b' => 'dot', 'c' => null])
261 | ->contains('')
262 | );
263 |
264 | $this->assertFalse(
265 | arrayed(['a' => 'www', 'b' => 'dot', 'c' => null])
266 | ->contains('', true)
267 | );
268 | }
269 |
270 | public function testUsingArrayedAsConstructorValues()
271 | {
272 | $this->assertEquals(
273 | 5,
274 | arrayed(\arrayed(1), \arrayed(2))
275 | ->map(function ($i) {
276 | return $i[0] + 1;
277 | })
278 | ->sum()
279 | );
280 | }
281 |
282 | public function testWithPiper()
283 | {
284 | $this->assertEquals(
285 | ['c' => 'com'],
286 | arrayed(['a' => 'www', 'b' => 'dot'])
287 | ->flip()
288 | ->pipe('array_diff', ['www' => 'a', 'c' => 'com'])()
289 | );
290 |
291 | $this->assertEquals(
292 | ['com' => 1],
293 | arrayed(['a' => 'www', 'b' => 'dot'])
294 | ->flip()
295 | ->pipe('array_diff', ['www' => 'a', 'c' => 'com'])
296 | ->pipe('array_count_values')()
297 | );
298 |
299 | $this->assertEquals(
300 | ['a', 'b'],
301 | arrayed(['a' => 'www', 'b' => 'dot', 'c' => 'www'])
302 | ->pipe('array_unique')
303 | ->flip()
304 | ->values()()
305 | );
306 | }
307 |
308 | public function testExtraCallableOnResultMethod()
309 | {
310 | $this->assertEquals(
311 | 'name,age',
312 | arrayed(['a' => 'name', 'b' => 'age'])
313 | ->values()
314 | ->result(function ($val) {
315 | return implode(',', $val);
316 | })
317 | );
318 |
319 | $this->assertEquals(
320 | 'name,age',
321 | arrayed(['a' => 'name', 'b' => 'age'])
322 | ->values()(function ($val) {
323 | return implode(',', $val);
324 | })
325 | );
326 |
327 | $this->assertEquals(
328 | 'nameage',
329 | arrayed(['a' => 'name', 'b' => 'age'])
330 | ->values()
331 | ->result('implode')
332 | );
333 | }
334 |
335 | public function testJsonable()
336 | {
337 | $data = ['a' => 1, 'b' => 2];
338 |
339 | $this->assertJson((string) arrayed($data));
340 | $this->assertStringContainsString((string) arrayed($data), json_encode($data));
341 | $this->assertEquals(json_encode($data), arrayed($data));
342 | $this->assertSame(json_encode($data), json_encode(arrayed($data)));
343 | }
344 |
345 | public function testCopy()
346 | {
347 | $arrayed = arrayed(1, 2, 3);
348 |
349 | $this->assertEquals($arrayed, $arrayed->copy());
350 | $this->assertNotSame($arrayed, $arrayed->copy());
351 | }
352 |
353 | public function testTap()
354 | {
355 | $res = [];
356 | $arrayed = arrayed(1, 2, 3)
357 | ->tap(function ($arrd) use (&$res) {
358 | $res = $arrd->reverse();
359 | });
360 |
361 | $this->assertEquals($arrayed[0], $res[2]);
362 | }
363 |
364 | public function testCollect()
365 | {
366 | $this->assertIsObject(
367 | arrayed(1, 2, 3)
368 | ->collect()
369 | );
370 |
371 | $this->assertEquals(
372 | 6,
373 | arrayed(1, 2, 3)
374 | ->collect(2, 3, 4)
375 | ->count()
376 | );
377 | }
378 | }
379 |
--------------------------------------------------------------------------------