├── .gitignore
├── .gitmodules
├── .travis.yml
├── CREDITS
├── EXPERIMENTAL
├── LICENSE
├── README.md
├── collection.c
├── collection.php
├── config.m4
├── config.w32
├── example
├── all.php
├── avg.php
├── chunk.php
├── collapse.php
├── combine.php
├── concat.php
├── contains.php
├── count.php
├── diff.php
├── diffAssoc.php
├── every.php
├── except.php
├── filter.php
├── first.php
├── firstWhere.php
├── flatMap.php
├── flatten.php
├── flip.php
├── forget.php
├── forpage.php
├── get.php
├── groupBy.php
├── has.php
├── implode.php
├── init.php
├── intersect.php
├── intersectByKeys.php
├── isEmpty.php
├── isNotEmpty.php
├── key_by.php
├── keys.php
├── last.php
├── map.php
├── mapToGroups.php
├── max.php
└── toarray.php
├── image
└── cover.jpg
├── php_collection.h
├── src
├── common.c
├── common.h
├── exception.c
├── include.h
├── kernel.c
└── method.c
├── tests
├── all.phpt
├── avg.phpt
├── chunk.phpt
├── collapse.phpt
├── combine.phpt
├── concat.phpt
├── contains.phpt
├── count.phpt
├── diff.phpt
├── diff_assoc.phpt
├── every.phpt
├── except.phpt
├── filter.phpt
├── first.phpt
├── first_where.phpt
├── flat_map.phpt
├── flatten.phpt
├── flip.phpt
├── for_page.phpt
├── forget.phpt
├── get.phpt
├── group_by.phpt
├── has.phpt
├── implode.phpt
├── init.phpt
├── intersect.phpt
├── intersect_by_key.phpt
├── is_empty.phpt
├── is_not_empty.phpt
├── key_by.phpt
├── keys.phpt
├── last.phpt
├── load.phpt
├── map.phpt
├── map_to_groups.phpt
├── max.phpt
└── toarray.phpt
└── travis
└── run-test.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | .deps
2 | *.lo
3 | *.la
4 | .libs
5 | acinclude.m4
6 | aclocal.m4
7 | autom4te.cache
8 | build
9 | config.guess
10 | config.h
11 | config.h.in
12 | config.log
13 | config.nice
14 | config.status
15 | config.sub
16 | configure
17 | configure.in
18 | include
19 | install-sh
20 | libtool
21 | ltmain.sh
22 | Makefile
23 | Makefile.fragments
24 | Makefile.global
25 | Makefile.objects
26 | missing
27 | mkinstalldirs
28 | modules
29 | run-tests.php
30 | tests/*/*.diff
31 | tests/*/*.out
32 | tests/*/*.php
33 | tests/*/*.exp
34 | tests/*/*.log
35 | tests/*/*.sh
36 | /.vscode
37 | .idea/
38 | CMakeLists.txt
39 | cmake-build-debug/
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/viest/php-ext-collection/8bf52852a2160186a74acd825be8b692b0685aa0/.gitmodules
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | compiler:
4 | - gcc
5 | - clang
6 |
7 | os:
8 | - linux
9 |
10 | php:
11 | - 7.0
12 | - 7.1
13 | - 7.2
14 |
15 | notifications:
16 | email: dev@service.viest.me
17 |
18 | before_script:
19 | - phpize && ./configure && make clean && make
20 |
21 | branches:
22 | only:
23 | - master
24 | - refactoring
25 | script:
26 | - ./travis/run-test.sh
--------------------------------------------------------------------------------
/CREDITS:
--------------------------------------------------------------------------------
1 | collection
2 |
--------------------------------------------------------------------------------
/EXPERIMENTAL:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/viest/php-ext-collection/8bf52852a2160186a74acd825be8b692b0685aa0/EXPERIMENTAL
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 viest
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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 | ## 介绍:
10 | `vcollect` 是一个PHP c extension,提供流畅、便利的数组数据操作。
11 |
12 | *******
13 |
14 | ## 安装:
15 |
16 | #### 1、Clone
17 |
18 | 定位于PHP下的ext目录,执行
19 | ```bash
20 | https://github.com/viest/php-ext-collection
21 | ```
22 |
23 | #### 2、编译安装
24 |
25 | 在扩展目录内,执行
26 | ```bash
27 | phpize
28 | ./configure
29 | make && make install
30 | ```
31 |
32 | #### 3、修改ini
33 |
34 | 在php.ini文件中加入`extension = collection.so`
35 |
36 | ## 使用
37 |
38 | #### 创建集合
39 |
40 | ```php
41 | $collection = \Vtiful\Kernel\Collection::init([1]);
42 | ```
43 |
44 | #### Documention
45 |
46 | [wiki](https://github.com/VikinDev/v-collect/wiki)
47 |
48 | ## License
49 |
50 | MIT
--------------------------------------------------------------------------------
/collection.c:
--------------------------------------------------------------------------------
1 | /*
2 | +----------------------------------------------------------------------+
3 | | Collection Extension |
4 | +----------------------------------------------------------------------+
5 | | Copyright (c) 2016-2018 The Viest |
6 | +----------------------------------------------------------------------+
7 | | http://www.viest.me |
8 | +----------------------------------------------------------------------+
9 | | Author: viest |
10 | +----------------------------------------------------------------------+
11 | */
12 |
13 | #ifdef HAVE_CONFIG_H
14 | #include "config.h"
15 | #endif
16 |
17 | #include "php.h"
18 | #include "php_ini.h"
19 | #include "ext/standard/info.h"
20 | #include "php_collection.h"
21 |
22 | #include "src/include.h"
23 |
24 | /* {{{ PHP_MINIT_FUNCTION
25 | */
26 | PHP_MINIT_FUNCTION(collection)
27 | {
28 | COLLECTION_STARTUP_MODULE(kernel);
29 | COLLECTION_STARTUP_MODULE(exception);
30 |
31 | return SUCCESS;
32 | }
33 | /* }}} */
34 |
35 | /* {{{ PHP_MSHUTDOWN_FUNCTION
36 | */
37 | PHP_MSHUTDOWN_FUNCTION(collection)
38 | {
39 | return SUCCESS;
40 | }
41 | /* }}} */
42 |
43 | /* {{{ PHP_RINIT_FUNCTION
44 | */
45 | PHP_RINIT_FUNCTION(collection)
46 | {
47 | #if defined(COMPILE_DL_COLLECTION) && defined(ZTS)
48 | ZEND_TSRMLS_CACHE_UPDATE();
49 | #endif
50 | return SUCCESS;
51 | }
52 | /* }}} */
53 |
54 | /* {{{ PHP_RSHUTDOWN_FUNCTION
55 | */
56 | PHP_RSHUTDOWN_FUNCTION(collection)
57 | {
58 | return SUCCESS;
59 | }
60 | /* }}} */
61 |
62 | /* {{{ PHP_MINFO_FUNCTION
63 | */
64 | PHP_MINFO_FUNCTION(collection)
65 | {
66 | php_info_print_table_start();
67 | php_info_print_table_header(2, "collection support", "enabled");
68 | php_info_print_table_end();
69 |
70 | #if defined(PHP_COLLECTION_VERSION)
71 | php_info_print_table_row(2, "Collection Version", PHP_COLLECTION_VERSION);
72 | #endif
73 |
74 | php_info_print_table_end();
75 | }
76 | /* }}} */
77 |
78 | /* {{{ collection_functions[]
79 | */
80 | const zend_function_entry collection_functions[] = {
81 | PHP_FE_END /* Must be the last line in collection_functions[] */
82 | };
83 | /* }}} */
84 |
85 | /* {{{ collection_module_entry
86 | */
87 | zend_module_entry collection_module_entry = {
88 | STANDARD_MODULE_HEADER,
89 | "collection",
90 | collection_functions,
91 | PHP_MINIT(collection),
92 | PHP_MSHUTDOWN(collection),
93 | PHP_RINIT(collection),
94 | PHP_RSHUTDOWN(collection),
95 | PHP_MINFO(collection),
96 | PHP_COLLECTION_VERSION,
97 | STANDARD_MODULE_PROPERTIES
98 | };
99 | /* }}} */
100 |
101 | #ifdef COMPILE_DL_COLLECTION
102 | #ifdef ZTS
103 | ZEND_TSRMLS_CACHE_DEFINE()
104 | #endif
105 | ZEND_GET_MODULE(collection)
106 | #endif
107 |
108 | /*
109 | * Local variables:
110 | * tab-width: 4
111 | * c-basic-offset: 4
112 | * End:
113 | * vim600: noet sw=4 ts=4 fdm=marker
114 | * vim<600: noet sw=4 ts=4
115 | */
116 |
--------------------------------------------------------------------------------
/collection.php:
--------------------------------------------------------------------------------
1 | ";
3 |
4 | if(!extension_loaded('vcollect')) {
5 | dl('vcollect.' . PHP_SHLIB_SUFFIX);
6 | }
7 | $module = 'vcollect';
8 | $functions = get_extension_funcs($module);
9 | echo "Functions available in the test extension:$br\n";
10 | foreach($functions as $func) {
11 | echo $func."$br\n";
12 | }
13 | echo "$br\n";
14 | $function = 'confirm_' . $module . '_compiled';
15 | if (extension_loaded($module)) {
16 | $str = $function($module);
17 | } else {
18 | $str = "Module $module is not compiled into PHP";
19 | }
20 | echo "$str\n";
21 | ?>
22 |
--------------------------------------------------------------------------------
/config.m4:
--------------------------------------------------------------------------------
1 | PHP_ARG_WITH(collection, for collection support,
2 | [ --with-collection Include collection support])
3 |
4 | if test "$PHP_COLLECTION" != "no"; then
5 | PHP_ADD_EXTENSION_DEP(collection, ds)
6 |
7 | PHP_NEW_EXTENSION(collection, collection.c src/kernel.c src/method.c src/exception.c src/common.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
8 |
9 | PHP_ADD_BUILD_DIR([$ext_builddir/src])
10 | fi
--------------------------------------------------------------------------------
/config.w32:
--------------------------------------------------------------------------------
1 | // $Id$
2 | // vim:ft=javascript
3 |
4 | // If your extension references something external, use ARG_WITH
5 | // ARG_WITH("vcollect", "for vcollect support", "no");
6 |
7 | // Otherwise, use ARG_ENABLE
8 | // ARG_ENABLE("vcollect", "enable vcollect support", "no");
9 |
10 | if (PHP_VCOLLECT != "no") {
11 | EXTENSION("vcollect", "vcollect_application.c vcollect_common.c vcollect.c", PHP_EXTNAME_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
12 | }
13 |
14 |
--------------------------------------------------------------------------------
/example/all.php:
--------------------------------------------------------------------------------
1 | all();
8 |
9 | var_dump($result1);
--------------------------------------------------------------------------------
/example/avg.php:
--------------------------------------------------------------------------------
1 | avg();
8 |
9 | var_dump($result1);
10 |
11 | $collection2 = \Vtiful\Kernel\Collection::init([
12 | ['name' => 'vikin', 'age' => 20],
13 | ['name' => 'viest', 'age' => 30]
14 | ]);
15 |
16 | $result2 = $collection2->avg('age');
17 |
18 | var_dump($result2);
--------------------------------------------------------------------------------
/example/chunk.php:
--------------------------------------------------------------------------------
1 | chunk(4);
8 |
9 | var_dump($result);
--------------------------------------------------------------------------------
/example/collapse.php:
--------------------------------------------------------------------------------
1 | collapse();
8 |
9 | var_dump($result1);
10 |
11 | var_dump($result1->count());
12 | var_dump($result1->toArray());
--------------------------------------------------------------------------------
/example/combine.php:
--------------------------------------------------------------------------------
1 | combine(['George', 29]);
6 |
7 | var_dump($result1);
--------------------------------------------------------------------------------
/example/concat.php:
--------------------------------------------------------------------------------
1 | concat(['address'])->concat([12])->concat([
6 | 'obj' => new \stdClass()
7 | ]);
8 |
9 | var_dump($result1);
--------------------------------------------------------------------------------
/example/contains.php:
--------------------------------------------------------------------------------
1 | 'Desk', 'price' => 100]);
4 |
5 | $true = $collection->contains('Desk');
6 |
7 | var_dump($true);
8 |
9 | $false = $collection->contains('New York');
10 |
11 | var_dump($false);
12 |
13 | $collection = \Vtiful\Kernel\Collection::init([
14 | ['product' => 'Desk', 'price' => 200, 'VV'],
15 | ['product' => 'Chair', 'price' => 100, 'BB'],
16 | ]);
17 |
18 | $true2 = $collection->contains('product', 'Desk');
19 |
20 | var_dump($true2);
21 |
22 | $false2 = $collection->contains('product', 'Bookcase');
23 |
24 | var_dump($false2);
25 |
26 |
--------------------------------------------------------------------------------
/example/count.php:
--------------------------------------------------------------------------------
1 | count();
8 |
9 | var_dump($result);
--------------------------------------------------------------------------------
/example/diff.php:
--------------------------------------------------------------------------------
1 | diff([
8 | 2, 4, 6, 8
9 | ]);
10 |
11 | var_dump($result);
--------------------------------------------------------------------------------
/example/diffAssoc.php:
--------------------------------------------------------------------------------
1 | 'orange',
5 | 'type' => 'fruit',
6 | 'remain' => 6
7 | ]);
8 |
9 | $diff = $collection->diffAssoc([
10 | 'color' => 'yellow',
11 | 'type' => 'fruit',
12 | 'remain' => 3,
13 | 'used' => 6
14 | ]);
15 |
16 | var_dump($diff);
--------------------------------------------------------------------------------
/example/every.php:
--------------------------------------------------------------------------------
1 | every(function ($value, $key) {
8 | return $value > 0;
9 | });
10 |
11 | var_dump($result);
--------------------------------------------------------------------------------
/example/except.php:
--------------------------------------------------------------------------------
1 | 1,
5 | 'price' => 100,
6 | 'discount' => false,
7 | ]);
8 |
9 | $filtered = $collection->except([
10 | 'price',
11 | 'discount',
12 | ]);
13 |
14 | var_dump($filtered);
--------------------------------------------------------------------------------
/example/filter.php:
--------------------------------------------------------------------------------
1 | filter(function ($value, $key) {
9 | return $value > 2;
10 | });
11 |
12 | var_dump($callbackRes);
13 |
14 |
15 | // 没有传递回调函数
16 | $collection2 = \Vtiful\Kernel\Collection::init([
17 | 1, 2, 3, null, false, '', 0, []
18 | ]);
19 |
20 | $noCallback = $collection2->filter();
21 |
22 | var_dump($noCallback);
--------------------------------------------------------------------------------
/example/first.php:
--------------------------------------------------------------------------------
1 | first(function ($value, $key) {
8 | return $value > 2;
9 | });
10 |
11 | $noCollback = $collection->first();
12 |
13 | var_dump($collbackRes);
14 | var_dump($noCollback);
15 |
--------------------------------------------------------------------------------
/example/firstWhere.php:
--------------------------------------------------------------------------------
1 | 'Regena', 'age' => 12],
5 | ['name' => 'Linda', 'age' => 14],
6 | ['name' => 'Diego', 'age' => 23],
7 | ['name' => 'Linda', 'age' => 84],
8 | ]);
9 |
10 | $result1 = $collection->firstWhere('name', 'Linda');
11 | $result2 = $collection->firstWhere('age', '>=', 18);
12 |
13 | var_dump($result1);
14 | var_dump($result2);
--------------------------------------------------------------------------------
/example/flatMap.php:
--------------------------------------------------------------------------------
1 | 'Sally'],
5 | ['school' => 'Arkansas'],
6 | ['age' => 28]
7 | ]);
8 |
9 | $flattened = $collection->flatMap(function ($values) {
10 | return array_map('strtoupper', $values);
11 | });
12 |
13 | var_dump($flattened);
14 |
--------------------------------------------------------------------------------
/example/flatten.php:
--------------------------------------------------------------------------------
1 | 'viest',
5 | 'languages' => [
6 | 'php', 'c'
7 | ]
8 | ]);
9 |
10 | $flattened = $collection1->flatten();
11 |
12 | var_dump($flattened);
13 |
14 | $collection2 = \Vtiful\Kernel\Collection::init([
15 | 'Apple' => [
16 | ['name' => 'iPhone 6S', 'brand' => 'Apple'],
17 | ],
18 | 'Samsung' => [
19 | ['name' => 'Galaxy S7', 'brand' => 'Samsung']
20 | ],
21 | ]);
22 |
23 | $products = $collection2->flatten(2);
24 |
25 | var_dump($products);
--------------------------------------------------------------------------------
/example/flip.php:
--------------------------------------------------------------------------------
1 | 'taylor',
5 | 'framework' => 'laravel'
6 | ]);
7 |
8 | $flipped = $collection->flip();
9 |
10 | var_dump($flipped);
--------------------------------------------------------------------------------
/example/forget.php:
--------------------------------------------------------------------------------
1 | 'viest',
5 | 'extension' => 'collection'
6 | ]);
7 |
8 | $result = $collection->forget('name');
9 |
10 | var_dump($result);
--------------------------------------------------------------------------------
/example/forpage.php:
--------------------------------------------------------------------------------
1 | forPage(2, 3);
8 |
9 | var_dump($chunk);
--------------------------------------------------------------------------------
/example/get.php:
--------------------------------------------------------------------------------
1 | 'viest',
5 | 'extension' => 'collection',
6 | ]);
7 |
8 | $name = $collection->get('name');
9 | $null = $collection->get('age');
10 | $age = $collection->get('age', 22);
11 |
12 | var_dump($name, $null, $age);
--------------------------------------------------------------------------------
/example/groupBy.php:
--------------------------------------------------------------------------------
1 | 'account-x10', 'product' => 'Chair'],
5 | ['account_id' => 'account-x10', 'product' => 'Bookcase'],
6 | ['account_id' => 'account-x11', 'product' => 'Desk'],
7 | ]);
8 |
9 | $grouped = $collection->groupBy(function ($item, $key) {
10 | return substr($item['account_id'], -3);
11 | });
12 |
13 | var_dump($grouped->toArray());
14 |
15 | $grouped = $collection->groupBy('account_id');
16 |
17 | var_dump($grouped->toArray());
--------------------------------------------------------------------------------
/example/has.php:
--------------------------------------------------------------------------------
1 | 'viest',
5 | 'age' => 21
6 | ]);
7 |
8 | $true = $collection->has('age');
9 | $false = $collection->has('address');
10 |
11 | var_dump($true, $false);
--------------------------------------------------------------------------------
/example/implode.php:
--------------------------------------------------------------------------------
1 | implode('-');
8 |
9 | var_dump($result1);
10 |
11 | $collection2 = \Vtiful\Kernel\Collection::init([
12 | ['name' => 'viest', 'age' => 21],
13 | ['name' => 'vikin', 'age' => 20],
14 | ['name' => 'wjx', 'age' => 22],
15 | ]);
16 |
17 | $result2 = $collection2->implode('name', '-');
18 |
19 | var_dump($result2);
--------------------------------------------------------------------------------
/example/init.php:
--------------------------------------------------------------------------------
1 | intersect([2, 7, 5, 9, 10, 'b']);
6 |
7 | var_dump($intersect->toArray());
--------------------------------------------------------------------------------
/example/intersectByKeys.php:
--------------------------------------------------------------------------------
1 | 'UX301', 'type' => 'screen', 'year' => 2009
5 | ]);
6 |
7 | $intersect = $collection->intersectByKeys([
8 | 'reference' => 'UX404', 'type' => 'tab', 'year' => 2011
9 | ]);
10 |
11 | var_dump($intersect);
--------------------------------------------------------------------------------
/example/isEmpty.php:
--------------------------------------------------------------------------------
1 | isEmpty();
6 |
7 | $collection2 = \Vtiful\Kernel\Collection::init([]);
8 |
9 | $false = $collection2->isEmpty();
10 |
11 | var_dump($true, $false);
--------------------------------------------------------------------------------
/example/isNotEmpty.php:
--------------------------------------------------------------------------------
1 | isNotEmpty();
6 |
7 | $collection2 = \Vtiful\Kernel\Collection::init([]);
8 |
9 | $true = $collection2->isNotEmpty();
10 |
11 | var_dump($false, $true);
--------------------------------------------------------------------------------
/example/key_by.php:
--------------------------------------------------------------------------------
1 | 'prod-100', 'name' => 'Desk'],
5 | ['product_id' => 'prod-200', 'name' => 'Chair'],
6 | ]);
7 |
8 | $keyed1 = $collection1->keyBy('product_id');
9 |
10 | $collection2 = \Vtiful\Kernel\Collection::init([
11 | ['product_id' => 'prod-100', 'name' => 'Desk'],
12 | ['product_id' => 'prod-200', 'name' => 'Chair'],
13 | ]);
14 |
15 | $keyed2 = $collection2->keyBy(function ($item) {
16 | return strtoupper($item['product_id']);
17 | });
18 |
19 | var_dump($keyed1, $keyed2);
--------------------------------------------------------------------------------
/example/keys.php:
--------------------------------------------------------------------------------
1 | ['product_id' => 'prod-100', 'name' => 'Desk'],
5 | 'prod-200' => ['product_id' => 'prod-200', 'name' => 'Chair'],
6 | ]);
7 |
8 | $keys = $collection->keys();
9 |
10 | var_dump($keys);
--------------------------------------------------------------------------------
/example/last.php:
--------------------------------------------------------------------------------
1 | last(function ($value, $key) {
6 | return $value < 3;
7 | });
8 |
9 | $defaultLast = $collection->last();
10 |
11 |
12 | var_dump($callbackLast, $defaultLast);
--------------------------------------------------------------------------------
/example/map.php:
--------------------------------------------------------------------------------
1 | map(function ($item, $key) {
6 | return $item * 2;
7 | });
8 |
9 | var_dump($multiplied);
--------------------------------------------------------------------------------
/example/mapToGroups.php:
--------------------------------------------------------------------------------
1 | 'John Doe',
6 | 'department' => 'Sales',
7 | ],[
8 | 'name' => 'Jane Doe',
9 | 'department' => 'Sales',
10 | ],[
11 | 'name' => 'Johnny Doe',
12 | 'department' => 'Marketing',
13 | ]
14 | ]);
15 |
16 | $grouped = $collection->mapToGroups(function ($item, $key) {
17 | return [$item['department'] => $item['name']];
18 | });
19 |
20 | var_dump($grouped->toArray());
--------------------------------------------------------------------------------
/example/max.php:
--------------------------------------------------------------------------------
1 | max();
6 |
7 | var_dump($default);
8 |
9 | $collection2 = \Vtiful\Kernel\Collection::init([
10 | ['foo' => 10],
11 | ['foo' => 50],
12 | ['foo' => 20],
13 | ]);
14 |
15 | $defaultKey = $collection2->max('foo');
16 |
17 | var_dump($defaultKey);
--------------------------------------------------------------------------------
/example/toarray.php:
--------------------------------------------------------------------------------
1 | toArray();
8 |
9 | var_dump($result);
--------------------------------------------------------------------------------
/image/cover.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/viest/php-ext-collection/8bf52852a2160186a74acd825be8b692b0685aa0/image/cover.jpg
--------------------------------------------------------------------------------
/php_collection.h:
--------------------------------------------------------------------------------
1 | /*
2 | +----------------------------------------------------------------------+
3 | | Collection Extension |
4 | +----------------------------------------------------------------------+
5 | | Copyright (c) 2016-2018 The Viest |
6 | +----------------------------------------------------------------------+
7 | | http://www.viest.me |
8 | +----------------------------------------------------------------------+
9 | | Author: viest |
10 | +----------------------------------------------------------------------+
11 | */
12 |
13 | #ifndef PHP_COLLECTION_H
14 | #define PHP_COLLECTION_H
15 |
16 | extern zend_module_entry collection_module_entry;
17 | #define phpext_collection_ptr &collection_module_entry
18 |
19 | #define PHP_COLLECTION_VERSION "0.1.0"
20 |
21 | #ifdef PHP_WIN32
22 | # define PHP_COLLECTION_API __declspec(dllexport)
23 | #elif defined(__GNUC__) && __GNUC__ >= 4
24 | # define PHP_COLLECTION_API __attribute__ ((visibility("default")))
25 | #else
26 | # define PHP_COLLECTION_API
27 | #endif
28 |
29 | #ifdef ZTS
30 | #include "TSRM.h"
31 | #endif
32 |
33 | #define COLLECTION_STARTUP_MODULE(module) ZEND_MODULE_STARTUP_N(vtiful_collection_##module)(INIT_FUNC_ARGS_PASSTHRU)
34 | #define COLLECTION_STARTUP_FUNCTION(module) ZEND_MINIT_FUNCTION(vtiful_collection_##module)
35 |
36 | #if defined(ZTS) && defined(COMPILE_DL_COLLECTION)
37 | ZEND_TSRMLS_CACHE_EXTERN()
38 | #endif
39 |
40 | PHP_MINIT_FUNCTION(collection);
41 | PHP_MSHUTDOWN_FUNCTION(collection);
42 | PHP_RINIT_FUNCTION(collection);
43 | PHP_RSHUTDOWN_FUNCTION(collection);
44 | PHP_MINFO_FUNCTION(collection);
45 |
46 | #endif
47 |
48 |
49 | /*
50 | * Local variables:
51 | * tab-width: 4
52 | * c-basic-offset: 4
53 | * End:
54 | * vim600: noet sw=4 ts=4 fdm=marker
55 | * vim<600: noet sw=4 ts=4
56 | */
57 |
--------------------------------------------------------------------------------
/src/common.c:
--------------------------------------------------------------------------------
1 | /*
2 | +----------------------------------------------------------------------+
3 | | Collection Extension |
4 | +----------------------------------------------------------------------+
5 | | Copyright (c) 2016-2018 The Viest |
6 | +----------------------------------------------------------------------+
7 | | http://www.viest.me |
8 | +----------------------------------------------------------------------+
9 | | Author: viest |
10 | +----------------------------------------------------------------------+
11 | */
12 |
13 | #include "include.h"
14 | #include "common.h"
15 |
16 | double average_no_column(zend_array *current)
17 | {
18 | double sum = 0;
19 |
20 | ZEND_HASH_FOREACH_VAL(current, zval* value)
21 | if (Z_TYPE_P(value) == IS_LONG) {
22 | sum += Z_LVAL_P(value);
23 | } else if (Z_TYPE_P(value) == IS_DOUBLE) {
24 | sum += Z_DVAL_P(value);
25 | }
26 | ZEND_HASH_FOREACH_END();
27 |
28 | return sum;
29 | }
30 |
31 | double average_column(zend_array *current, zend_string *column)
32 | {
33 | double sum = 0;
34 |
35 | zval args[2], ret_val;
36 |
37 | ZVAL_ARR(&args[0], current);
38 | ZVAL_STR(&args[1], column);
39 |
40 | call_internal_function(INTERNAL_FUN(column), 2, args, &ret_val);
41 |
42 | if (Z_TYPE(ret_val) == IS_ARRAY) {
43 | sum = average_no_column(Z_ARRVAL(ret_val));
44 | }
45 |
46 | zval_ptr_dtor(&ret_val);
47 |
48 | return sum;
49 | }
50 |
51 | void collection_chunk(zend_array *current, zend_long length, zval *object)
52 | {
53 | zval args[2], ret_val;
54 |
55 | ZVAL_ARR (&args[0], current);
56 | ZVAL_LONG(&args[1], length);
57 |
58 | call_internal_function(INTERNAL_FUN(chunk), 2, args, &ret_val);
59 |
60 | UPDATE_OBJ_COLLECTION(object, &ret_val);
61 |
62 | zval_ptr_dtor(&ret_val);
63 | }
64 |
65 | void collection_collapse(zend_array *z_array_p, zval *ret_val)
66 | {
67 | ZEND_HASH_FOREACH_VAL(z_array_p, zval *zval_p)
68 | if (Z_TYPE_P(zval_p) == IS_ARRAY) {
69 | collection_collapse(Z_ARRVAL_P(zval_p), ret_val);
70 | } else {
71 | add_next_index_zval(ret_val, zval_p);
72 | }
73 | ZEND_HASH_FOREACH_END();
74 | }
75 |
76 | void collection_combine(zend_array *current_collection, zval *z_arr_val, zval *ret_val)
77 | {
78 | zend_long z_arr_val_length = ZVAL_ARRAY_COUNT(z_arr_val);
79 |
80 | ZEND_HASH_FOREACH_BUCKET(current_collection, Bucket *bucket)
81 | if (bucket->h < z_arr_val_length) {
82 | ZVAL_ARRAY_INSERT_BUCKET_KEY_ZVAL_VAL(ret_val, bucket, z_arr_val);
83 | }
84 | ZEND_HASH_FOREACH_END();
85 | }
86 |
87 | void collection_concat(zend_array *current_collection, zval *z_arr, zval *ret_val)
88 | {
89 | zend_hash_copy(Z_ARRVAL_P(ret_val), current_collection, zval_add_ref);
90 |
91 | ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(z_arr), zval *val)
92 | GC_ZVAL_ADDREF(val);
93 | add_next_index_zval(ret_val, val);
94 | ZEND_HASH_FOREACH_END();
95 | }
96 |
97 | void collection_in_array_val(zend_array *current_collection, zval *search_val, zval *ret_val)
98 | {
99 | if (Z_TYPE_P(search_val) == IS_LONG) {
100 | ZEND_HASH_FOREACH_VAL(current_collection, zval *val)
101 | if (fast_equal_check_long(search_val, val)) {
102 | ZVAL_TRUE(ret_val);
103 | return;
104 | }
105 | ZEND_HASH_FOREACH_END();
106 | } else if (Z_TYPE_P(search_val) == IS_STRING) {
107 | ZEND_HASH_FOREACH_VAL(current_collection, zval *val)
108 | if (fast_equal_check_string(search_val, val)) {
109 | ZVAL_TRUE(ret_val);
110 | return;
111 | }
112 | ZEND_HASH_FOREACH_END();
113 | } else {
114 | ZEND_HASH_FOREACH_VAL(current_collection, zval *val)
115 | if (fast_equal_check_function(search_val, val)) {
116 | ZVAL_TRUE(ret_val);
117 | return;
118 | }
119 | ZEND_HASH_FOREACH_END();
120 | }
121 |
122 | ZVAL_FALSE(ret_val);
123 | }
124 |
125 | int zval_equal(zval *z1, zval *z2)
126 | {
127 | if (Z_TYPE_P(z1) == IS_LONG && Z_TYPE_P(z2) == IS_LONG) {
128 | if (fast_equal_check_long(z1, z2)) {
129 | return 1;
130 | }
131 | } else if (Z_TYPE_P(z1) == IS_STRING && Z_TYPE_P(z2) == IS_STRING) {
132 | if (fast_equal_check_string(z1, z2)) {
133 | return 1;
134 | }
135 | } else {
136 | if (fast_equal_check_function(z1, z2)) {
137 | return 1;
138 | }
139 | }
140 |
141 | return 0;
142 | }
143 |
144 | void collection_in_array_kv(zend_array *current_collection, zval *search_key, zval *search_val, zval *ret_val)
145 | {
146 | zval *find_res = NULL;
147 |
148 | ZEND_HASH_FOREACH_VAL(current_collection, zval *val)
149 | if (Z_TYPE_P(val) == IS_ARRAY) {
150 | if (Z_TYPE_P(search_key) == IS_LONG) {
151 | find_res = zend_hash_index_find(Z_ARR_P(val), Z_LVAL_P(search_key));
152 | } else {
153 | find_res = zend_hash_find(Z_ARR_P(val), Z_STR_P(search_key));
154 | }
155 |
156 | if (find_res != NULL && zval_equal(find_res, search_val) == 1) {
157 | ZVAL_TRUE(ret_val);
158 | return;
159 |
160 | }
161 | }
162 | ZEND_HASH_FOREACH_END();
163 |
164 | ZVAL_FALSE(ret_val);
165 | }
166 |
167 | void collection_diff(zend_array *current_collection, zval *search_val, zval *ret_val)
168 | {
169 | zval args[2];
170 |
171 | ZVAL_ARR (&args[0], current_collection);
172 | ZVAL_COPY(&args[1], search_val);
173 |
174 | GC_ZVAL_ADDREF(&args[0]);
175 |
176 | call_internal_function(INTERNAL_FUN(diff), 2, args, ret_val);
177 | }
178 |
179 | void collection_diff_assoc(zend_array *current_collection, zval *search_val, zval *ret_val)
180 | {
181 | zval args[2];
182 |
183 | ZVAL_ARR (&args[0], current_collection);
184 | ZVAL_COPY(&args[1], search_val);
185 |
186 | GC_ZVAL_ADDREF(&args[0]);
187 |
188 | call_internal_function(INTERNAL_FUN(diff_assoc), 2, args, ret_val);
189 | }
190 |
191 | void collection_except(zend_array *current_collection, zval *excluded_keys, zval *ret_val)
192 | {
193 | zend_hash_copy(Z_ARR_P(ret_val), current_collection, zval_add_ref);
194 |
195 | ZEND_HASH_FOREACH_VAL(Z_ARR_P(excluded_keys), zval *val)
196 | if (Z_TYPE_P(val) == IS_LONG) {
197 | if (zend_hash_index_exists(current_collection, Z_LVAL_P(val))) {
198 | zend_hash_index_del(Z_ARR_P(ret_val), Z_LVAL_P(val));
199 | }
200 | } else {
201 | if (zend_hash_exists(current_collection, Z_STR_P(val))) {
202 | zend_hash_del(Z_ARR_P(ret_val), Z_STR_P(val));
203 | }
204 | }
205 | ZEND_HASH_FOREACH_END();
206 | }
207 |
208 | void collection_flatten(zend_array *current_collection, zend_long depth, zval *ret_val)
209 | {
210 | ZEND_HASH_FOREACH_VAL(current_collection, zval *val)
211 | if (Z_TYPE_P(val) == IS_ARRAY && depth > 0) {
212 | collection_flatten(Z_ARR_P(val), depth - 1, ret_val);
213 | } else {
214 | add_next_index_zval(ret_val, val);
215 | GC_ZVAL_ADDREF(val);
216 | }
217 | ZEND_HASH_FOREACH_END();
218 | }
219 |
220 | void collection_flip(zend_array *current_collection, zval *ret_val)
221 | {
222 | zval args[1];
223 |
224 | ZVAL_ARR(&args[0], current_collection);
225 |
226 | GC_ZVAL_ADDREF(&args[0]);
227 |
228 | call_internal_function(INTERNAL_FUN(flip), 1, args, ret_val);
229 | }
230 |
231 | void collection_for_page(zend_array *current_collection, zend_long page, zend_long number, zval *ret_val)
232 | {
233 | int64_t start_index;
234 | int64_t end_index = page * number;
235 |
236 | for (start_index = end_index - number; start_index < end_index; ++start_index) {
237 | add_next_index_zval(ret_val, &(current_collection->arData[start_index].val));
238 |
239 | }
240 | }
241 |
242 | void collection_group(zval *foreach_val, zval *tmp, zend_string *group_by_where, zval *group_key, zval *result)
243 | {
244 | if (Z_TYPE_P(foreach_val) == IS_ARRAY) {
245 | zval *group_current_list = NULL, *_group_key = NULL;
246 |
247 | if (group_key != NULL) {
248 | _group_key = group_key;
249 | }
250 |
251 | if (group_by_where != NULL) {
252 | COLLECTION_STR_FIND(Z_ARR_P(foreach_val), group_by_where, _group_key);
253 | }
254 |
255 | COLLECTION_STR_FIND(Z_ARR_P(result), Z_STR_P(_group_key), group_current_list);
256 |
257 | GC_ZVAL_ADDREF(foreach_val);
258 |
259 | if (group_current_list == NULL) {
260 | COLLECTION_INIT(tmp);
261 | add_next_index_zval(tmp, foreach_val);
262 | zend_hash_add(Z_ARRVAL_P(result), Z_STR_P(_group_key), tmp);
263 | ZVAL_NULL(tmp);
264 | } else {
265 | add_next_index_zval(group_current_list, foreach_val);
266 | }
267 | }
268 | }
269 |
270 | void collection_implode(zend_array *current_collection, zend_string *str, zend_string *result)
271 | {
272 | char *c_char_p = NULL;
273 | zend_string *z_str_p = NULL;
274 |
275 | c_char_p = ZSTR_VAL(result);
276 | *c_char_p = 0;
277 |
278 | ZEND_HASH_FOREACH_VAL(current_collection, zval *val)
279 | z_str_p = Z_STR_P(val);
280 | memcpy(c_char_p, ZSTR_VAL(z_str_p), ZSTR_LEN(z_str_p));
281 | c_char_p += ZSTR_LEN(z_str_p);
282 | memcpy(c_char_p, ZSTR_VAL(str), ZSTR_LEN(str));
283 | c_char_p += ZSTR_LEN(str);
284 | ZEND_HASH_FOREACH_END();
285 | }
286 |
287 | int collection_compare(const void *a, const void *b)
288 | {
289 | zval result;
290 | zval *first = NULL, *second = NULL;
291 |
292 | first = &((Bucket *)a)->val;
293 | second = &((Bucket *)b)->val;
294 |
295 | if (UNEXPECTED(Z_TYPE_P(first) == IS_INDIRECT)) {
296 | first = Z_INDIRECT_P(first);
297 | }
298 | if (UNEXPECTED(Z_TYPE_P(second) == IS_INDIRECT)) {
299 | second = Z_INDIRECT_P(second);
300 | }
301 | if (compare_function(&result, first, second) == FAILURE) {
302 | return 0;
303 | }
304 |
305 | ZEND_ASSERT(Z_TYPE(result) == IS_LONG);
306 | return ZEND_NORMALIZE_BOOL(Z_LVAL(result));
307 | }
308 |
309 | int collection_compare_by_key(const void *a, const void *b, const void *key)
310 | {
311 | zval result;
312 | zval *first_arr = NULL, *second_arr = NULL, *first = NULL, *second = NULL;
313 |
314 | first_arr = &((Bucket *)a)->val;
315 | second_arr = &((Bucket *)b)->val;
316 |
317 | if (Z_TYPE_P(first_arr) == IS_ARRAY) {
318 | first = zend_hash_find(Z_ARR_P(first_arr), (zend_string *)key);
319 | } else {
320 | first = first_arr;
321 | }
322 |
323 | if (Z_TYPE_P(second_arr) == IS_ARRAY) {
324 | second = zend_hash_find(Z_ARR_P(second_arr), (zend_string *)key);
325 | } else {
326 | second = second_arr;
327 | }
328 |
329 | if (UNEXPECTED(Z_TYPE_P(first) == IS_INDIRECT)) {
330 | first = Z_INDIRECT_P(first);
331 | }
332 | if (UNEXPECTED(Z_TYPE_P(second) == IS_INDIRECT)) {
333 | second = Z_INDIRECT_P(second);
334 | }
335 | if (compare_function(&result, first, second) == FAILURE) {
336 | return 0;
337 | }
338 |
339 | ZEND_ASSERT(Z_TYPE(result) == IS_LONG);
340 | return ZEND_NORMALIZE_BOOL(Z_LVAL(result));
341 | }
342 |
343 | zval* ZEND_FASTCALL zend_hash_key_minmax(const HashTable *ht, const zend_string *key, compare_key_func_t compar, uint32_t flag)
344 | {
345 | uint32_t idx;
346 | Bucket *p, *res;
347 |
348 | if (ht->nNumOfElements == 0 ) {
349 | return NULL;
350 | }
351 |
352 | idx = 0;
353 | while (1) {
354 | if (idx == ht->nNumUsed) {
355 | return NULL;
356 | }
357 | if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) break;
358 | idx++;
359 | }
360 | res = ht->arData + idx;
361 | for (; idx < ht->nNumUsed; idx++) {
362 | p = ht->arData + idx;
363 | if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
364 |
365 | if (flag) {
366 | if (compar(res, p, key) < 0) { /* max */
367 | res = p;
368 | }
369 | } else {
370 | if (compar(res, p, key) > 0) { /* min */
371 | res = p;
372 | }
373 | }
374 | }
375 |
376 | if (Z_TYPE_P(&res->val) == IS_ARRAY) {
377 | return zend_hash_str_find_ind(Z_ARR(res->val), ZSTR_VAL(key), ZSTR_LEN(key));
378 | } else {
379 | return &res->val;
380 | }
381 | }
382 |
383 | int zval_comparison_operations(zend_string *operator, zval *left, zval *right)
384 | {
385 | if (strcmp(operator->val, "==") == 0) {
386 | if (zval_equal(left, right)) {
387 | return 1;
388 | }
389 |
390 | return 0;
391 | }
392 |
393 | if (strcmp(operator->val, "!=") == 0) {
394 | if (zval_equal(left, right)) {
395 | return 0;
396 | }
397 |
398 | return 1;
399 | }
400 |
401 | if (strcmp(operator->val, ">=") == 0) {
402 | if (EXPECTED(Z_TYPE_P(left) == IS_LONG)) {
403 | if (EXPECTED(Z_TYPE_P(right) == IS_LONG)) {
404 | return (Z_LVAL_P(left) >= Z_LVAL_P(right));
405 | } else if (EXPECTED(Z_TYPE_P(right) == IS_DOUBLE)) {
406 | return ((double)Z_LVAL_P(left) >= Z_DVAL_P(right));
407 | }
408 | } else if (EXPECTED(Z_TYPE_P(left) == IS_DOUBLE)) {
409 | if (EXPECTED(Z_TYPE_P(right) == IS_DOUBLE)) {
410 | return (Z_DVAL_P(left) >= Z_DVAL_P(right));
411 | } else if (EXPECTED(Z_TYPE_P(right) == IS_LONG)) {
412 | return (Z_DVAL_P(left) >= ((double)Z_LVAL_P(right)));
413 | }
414 | }
415 |
416 | return 0;
417 | }
418 |
419 | if (strcmp(operator->val, "<=") == 0) {
420 | if (EXPECTED(Z_TYPE_P(left) == IS_LONG)) {
421 | if (EXPECTED(Z_TYPE_P(right) == IS_LONG)) {
422 | return (Z_LVAL_P(left) <= Z_LVAL_P(right));
423 | } else if (EXPECTED(Z_TYPE_P(right) == IS_DOUBLE)) {
424 | return ((double)Z_LVAL_P(left) <= Z_DVAL_P(right));
425 | }
426 | } else if (EXPECTED(Z_TYPE_P(left) == IS_DOUBLE)) {
427 | if (EXPECTED(Z_TYPE_P(right) == IS_DOUBLE)) {
428 | return (Z_DVAL_P(left) <= Z_DVAL_P(right));
429 | } else if (EXPECTED(Z_TYPE_P(right) == IS_LONG)) {
430 | return (Z_DVAL_P(left) <= ((double)Z_LVAL_P(right)));
431 | }
432 | }
433 |
434 | return 0;
435 | }
436 |
437 | if (strcmp(operator->val, ">") == 0) {
438 | if (EXPECTED(Z_TYPE_P(left) == IS_LONG)) {
439 | if (EXPECTED(Z_TYPE_P(right) == IS_LONG)) {
440 | return (Z_LVAL_P(left) > Z_LVAL_P(right));
441 | } else if (EXPECTED(Z_TYPE_P(right) == IS_DOUBLE)) {
442 | return ((double)Z_LVAL_P(left) > Z_DVAL_P(right));
443 | }
444 | } else if (EXPECTED(Z_TYPE_P(left) == IS_DOUBLE)) {
445 | if (EXPECTED(Z_TYPE_P(right) == IS_DOUBLE)) {
446 | return (Z_DVAL_P(left) > Z_DVAL_P(right));
447 | } else if (EXPECTED(Z_TYPE_P(right) == IS_LONG)) {
448 | return (Z_DVAL_P(left) > ((double)Z_LVAL_P(right)));
449 | }
450 | }
451 |
452 | return 0;
453 | }
454 |
455 | if (strcmp(operator->val, "<") == 0) {
456 | if (EXPECTED(Z_TYPE_P(left) == IS_LONG)) {
457 | if (EXPECTED(Z_TYPE_P(right) == IS_LONG)) {
458 | return (Z_LVAL_P(left) < Z_LVAL_P(right));
459 | } else if (EXPECTED(Z_TYPE_P(right) == IS_DOUBLE)) {
460 | return ((double)Z_LVAL_P(left) < Z_DVAL_P(right));
461 | }
462 | } else if (EXPECTED(Z_TYPE_P(left) == IS_DOUBLE)) {
463 | if (EXPECTED(Z_TYPE_P(right) == IS_DOUBLE)) {
464 | return (Z_DVAL_P(left) < Z_DVAL_P(right));
465 | } else if (EXPECTED(Z_TYPE_P(right) == IS_LONG)) {
466 | return (Z_DVAL_P(left) < ((double)Z_LVAL_P(right)));
467 | }
468 | }
469 |
470 | return 0;
471 | }
472 |
473 | return 0;
474 | }
475 |
476 | void call_internal_function(const char *function_name, uint32_t param_count, zval *params, zval *ret_val)
477 | {
478 | int index;
479 | zval z_f_name;
480 |
481 | ZVAL_STRINGL(&z_f_name, function_name, strlen(function_name));
482 |
483 | call_user_function(EG(function_table), NULL, &z_f_name, ret_val, param_count, params);
484 |
485 | if (Z_ISUNDEF_P(ret_val)) {
486 | ZVAL_NULL(ret_val);
487 | }
488 |
489 | for (index = 0; index < (int)param_count; index++) {
490 | VC_ZVAL_DTOR(params[index]);
491 | }
492 |
493 | VC_ZVAL_DTOR(z_f_name);
494 | }
--------------------------------------------------------------------------------
/src/common.h:
--------------------------------------------------------------------------------
1 | /*
2 | +----------------------------------------------------------------------+
3 | | Collection Extension |
4 | +----------------------------------------------------------------------+
5 | | Copyright (c) 2016-2018 The Viest |
6 | +----------------------------------------------------------------------+
7 | | http://www.viest.me |
8 | +----------------------------------------------------------------------+
9 | | Author: viest |
10 | +----------------------------------------------------------------------+
11 | */
12 |
13 | #ifndef PHP_EXT_COLLECTION_COMMON_H
14 | #define PHP_EXT_COLLECTION_COMMON_H
15 |
16 | #define VAL_IN_COLLECTION(cc, search, ret) \
17 | collection_in_array_val(cc, search, ret)
18 |
19 | #define KV_IN_COLLECTION(cc, k, v, ret) \
20 | collection_in_array_kv(cc, k, v, ret)
21 |
22 | #define INTERNAL_ARR "array_"
23 | #define INTERNAL_FUN(m) INTERNAL_ARR#m
24 |
25 | typedef int (*compare_key_func_t)(const void *, const void *, const void *);
26 |
27 | void call_internal_function(const char *function_name, uint32_t param_count, zval params[], zval *ret_val);
28 |
29 | zval* ZEND_FASTCALL zend_hash_key_minmax(const HashTable *ht, const zend_string *key, compare_key_func_t compar, uint32_t flag);
30 |
31 | int zval_equal(zval *z1, zval *z2);
32 | int zval_comparison_operations(zend_string *operator, zval *left, zval *right);
33 |
34 | double average_no_column(zend_array *current);
35 | double average_column(zend_array *current, zend_string *column);
36 | void collection_chunk(zend_array *current, zend_long length, zval *object);
37 | void collection_collapse(zend_array *z_array_p, zval *ret_val);
38 | void collection_combine(zend_array *current_collection, zval *z_arr_val, zval *ret_val);
39 | void collection_concat(zend_array *current_collection, zval *z_arr, zval *ret_val);
40 | void collection_in_array_val(zend_array *current_collection, zval *search_val, zval *ret_val);
41 | void collection_in_array_kv(zend_array *current_collection, zval *search_key, zval *search_val, zval *ret_val);
42 | void collection_diff(zend_array *current_collection, zval *search_val, zval *ret_val);
43 | void collection_diff_assoc(zend_array *current_collection, zval *search_val, zval *ret_val);
44 | void collection_except(zend_array *current_collection, zval *excluded_keys, zval *ret_val);
45 | void collection_flatten(zend_array *current_collection, zend_long depth, zval *ret_val);
46 | void collection_flip(zend_array *current_collection, zval *ret_val);
47 | void collection_for_page(zend_array *current_collection, zend_long page, zend_long number, zval *ret_val);
48 | void collection_group(zval *foreach_val, zval *tmp, zend_string *group_by_where, zval *group_key, zval *result);
49 | void collection_implode(zend_array *current_collection, zend_string *str, zend_string *result);
50 | int collection_compare(const void *a, const void *b);
51 | int collection_compare_by_key(const void *a, const void *b, const void *key);
52 |
53 | #endif
54 |
--------------------------------------------------------------------------------
/src/exception.c:
--------------------------------------------------------------------------------
1 | /*
2 | +----------------------------------------------------------------------+
3 | | Collection Extension |
4 | +----------------------------------------------------------------------+
5 | | Copyright (c) 2016-2018 The Viest |
6 | +----------------------------------------------------------------------+
7 | | http://www.viest.me |
8 | +----------------------------------------------------------------------+
9 | | Author: viest |
10 | +----------------------------------------------------------------------+
11 | */
12 |
13 | #include "include.h"
14 |
15 | zend_class_entry *vtiful_collection_exception_ce;
16 |
17 | /** {{{ exception_methods
18 | */
19 | zend_function_entry exception_methods[] = {
20 | PHP_FE_END
21 | };
22 | /* }}} */
23 |
24 | /** {{{ COLLECTION_STARTUP_FUNCTION
25 | */
26 | COLLECTION_STARTUP_FUNCTION(exception) {
27 | zend_class_entry ce;
28 |
29 | INIT_NS_CLASS_ENTRY(ce, "Vtiful\\Kernel\\Collection", "Exception", exception_methods);
30 |
31 | vtiful_collection_exception_ce = zend_register_internal_class_ex(&ce, zend_ce_exception);
32 |
33 | return SUCCESS;
34 | }
35 | /* }}} */
36 |
--------------------------------------------------------------------------------
/src/include.h:
--------------------------------------------------------------------------------
1 | /*
2 | +----------------------------------------------------------------------+
3 | | Collection Extension |
4 | +----------------------------------------------------------------------+
5 | | Copyright (c) 2016-2018 The Viest |
6 | +----------------------------------------------------------------------+
7 | | http://www.viest.me |
8 | +----------------------------------------------------------------------+
9 | | Author: viest |
10 | +----------------------------------------------------------------------+
11 | */
12 |
13 | #ifndef PHP_EXT_COLLECTION_INCLUDE_H
14 | #define PHP_EXT_COLLECTION_INCLUDE_H
15 |
16 | #include
17 |
18 | #include "ext/standard/php_var.h"
19 |
20 | #include "zend_types.h"
21 | #include "zend_exceptions.h"
22 | #include "zend.h"
23 | #include "zend_API.h"
24 | #include "php.h"
25 |
26 | #include "../php_collection.h"
27 |
28 | // Class
29 | extern zend_class_entry *vtiful_collection_ce;
30 | extern zend_class_entry *vtiful_collection_exception_ce;
31 |
32 | // Startup Module
33 | COLLECTION_STARTUP_FUNCTION(exception);
34 | COLLECTION_STARTUP_FUNCTION(kernel);
35 |
36 | // Kernel Class Method
37 | PHP_METHOD(vtiful_collection, __construct);
38 | PHP_METHOD(vtiful_collection, __clone);
39 | PHP_METHOD(vtiful_collection, init);
40 | PHP_METHOD(vtiful_collection, map);
41 | PHP_METHOD(vtiful_collection, all);
42 | PHP_METHOD(vtiful_collection, avg);
43 | PHP_METHOD(vtiful_collection, chunk);
44 | PHP_METHOD(vtiful_collection, collapse);
45 | PHP_METHOD(vtiful_collection, count);
46 | PHP_METHOD(vtiful_collection, toArray);
47 | PHP_METHOD(vtiful_collection, combine);
48 | PHP_METHOD(vtiful_collection, concat);
49 | PHP_METHOD(vtiful_collection, contains);
50 | PHP_METHOD(vtiful_collection, diff);
51 | PHP_METHOD(vtiful_collection, diffAssoc);
52 | PHP_METHOD(vtiful_collection, every);
53 | PHP_METHOD(vtiful_collection, except);
54 | PHP_METHOD(vtiful_collection, filter);
55 | PHP_METHOD(vtiful_collection, first);
56 | PHP_METHOD(vtiful_collection, firstWhere);
57 | PHP_METHOD(vtiful_collection, flatMap);
58 | PHP_METHOD(vtiful_collection, flatten);
59 | PHP_METHOD(vtiful_collection, flip);
60 | PHP_METHOD(vtiful_collection, forget);
61 | PHP_METHOD(vtiful_collection, forPage);
62 | PHP_METHOD(vtiful_collection, get);
63 | PHP_METHOD(vtiful_collection, groupBy);
64 | PHP_METHOD(vtiful_collection, has);
65 | PHP_METHOD(vtiful_collection, implode);
66 | PHP_METHOD(vtiful_collection, intersect);
67 | PHP_METHOD(vtiful_collection, intersectByKeys);
68 | PHP_METHOD(vtiful_collection, isEmpty);
69 | PHP_METHOD(vtiful_collection, isNotEmpty);
70 | PHP_METHOD(vtiful_collection, keyBy);
71 | PHP_METHOD(vtiful_collection, keys);
72 | PHP_METHOD(vtiful_collection, last);
73 | PHP_METHOD(vtiful_collection, mapToGroups);
74 | PHP_METHOD(vtiful_collection, max);
75 |
76 | // PHP Compatible
77 | #ifndef GC_ADDREF
78 | #define GC_ADDREF(p) ++(&(p->gc))->refcount
79 | #endif
80 |
81 | #define GC_ZVAL_ADDREF(zval_p) \
82 | do { \
83 | zend_refcounted *gc = Z_COUNTED_P(zval_p); \
84 | uint32_t t = Z_TYPE_INFO_P(zval_p); \
85 | if((t & (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT)) != 0) { \
86 | GC_REFCOUNT(gc)++; \
87 | } \
88 | } while (0)
89 |
90 | #define VC_ZVAL_DTOR(zval) zval_ptr_dtor(&zval);
91 |
92 | // Define
93 | #define CURRENT_COLLECTION \
94 | Z_OBJ_HT_P(getThis())->get_properties(getThis())
95 |
96 | #define CURRENT_COLLECTION_COUNT \
97 | zend_hash_num_elements(CURRENT_COLLECTION)
98 |
99 | #define ZVAL_ARRAY_COUNT(zval_p) \
100 | zend_hash_num_elements(Z_ARR_P(zval_p))
101 |
102 | #define COLLECTION_INDEX_ZVAL(zval_p, index) \
103 | &Z_ARR_P(zval_p)->arData[index].val
104 |
105 | #define COLLECTION_INIT(zval_p) \
106 | do { \
107 | array_init(zval_p); \
108 | } while (0)
109 |
110 | #define COLLECTION_TMP(zval_p) \
111 | zval collection_tmp; \
112 | zval_p = &collection_tmp; \
113 | array_init(&collection_tmp);
114 |
115 |
116 | #define COLLECTION_ADD_INDEX_ZVAL(collection_zval_p, zval_p) \
117 | add_next_index_zval(collection_zval_p, zval_p);
118 |
119 | #define COLLECTION_STRING_DELETE(collection_array_p, zs_key) \
120 | zend_hash_del(collection_array_p, zs_key);
121 |
122 | #define COLLECTION_INDEX_DELETE(collection_array_p, ulong_key) \
123 | zend_hash_index_del(collection_array_p, ulong_key);
124 |
125 | #define COLLECTION_INIT_IN_CURRENT(zval_p) \
126 | COLLECTION_INIT(zval_p); \
127 | zend_hash_copy(Z_ARR_P(zval_p), CURRENT_COLLECTION, zval_add_ref);
128 |
129 | #define COLLECTION_UPDATE(array_p, bucket, new_zval_p) \
130 | ZVAL_COPY_VALUE(&(Z_ARR_P(array_p)->arData[bucket->h].val), new_zval_p)
131 |
132 | #define NEW_ZVAL_OBJ(zval_p) \
133 | do { \
134 | object_init_ex(zval_p, vtiful_collection_ce); \
135 | } while (0)
136 |
137 | #define UPDATE_OBJ_COLLECTION(zo_p, z_collection_p) \
138 | do { \
139 | if (Z_TYPE_P(z_collection_p) == IS_ARRAY) { \
140 | zend_object *obj = Z_OBJ_P(zo_p); \
141 | GC_ZVAL_ADDREF(z_collection_p); \
142 | obj->properties = Z_ARRVAL_P(z_collection_p); \
143 | } \
144 | } while (0)
145 |
146 | #define NEW_COLLECTION_OBJ(ret_val, collection) \
147 | NEW_ZVAL_OBJ(ret_val); \
148 | UPDATE_OBJ_COLLECTION(ret_val, collection);
149 |
150 | #define INIT_FCALL(arg_num, ret_val_p) \
151 | zval args[arg_num]; \
152 | fci.param_count = arg_num; \
153 | fci.retval = ret_val_p; \
154 | fci.params = args;
155 |
156 | #define FCALL_DTOR(arg_num) \
157 | int i = 0; \
158 | for (i; i < arg_num; i++) { \
159 | VC_ZVAL_DTOR(args[i]) \
160 | }
161 |
162 | #define FCALL_TWO_ARGS(bucket) \
163 | ZVAL_COPY_VALUE(&args[0], &bucket->val); \
164 | if (bucket->key) { \
165 | ZVAL_STR(&args[1], bucket->key); \
166 | } else { \
167 | ZVAL_LONG(&args[1], bucket->h); \
168 | } \
169 | zend_call_function(&fci, &fci_cache);
170 |
171 | #define FCALL_ONE_ARGS(bucket) \
172 | ZVAL_COPY_VALUE(&args[0], &bucket->val); \
173 | zend_call_function(&fci, &fci_cache);
174 |
175 | #define ARRAY_INDEX_FIND(zval_p, index, zval_result_p) \
176 | do { \
177 | ZVAL_COPY(zval_result_p, &(Z_ARR_P(zval_p)->arData[index].val));\
178 | } while (0)
179 |
180 | #define ARRAY_STR_FIND(zval_p, zs_key_p, zval_result_p) \
181 | do { \
182 | zval_result_p = zend_hash_find(Z_ARR_P(zval_p), zs_key_p); \
183 | } while (0)
184 |
185 | #define COLLECTION_INDEX_FIND(collection, index, zval_result_p) \
186 | do { \
187 | if (index < collection->nNumOfElements) { \
188 | zval_result_p = &(collection->arData[index].val); \
189 | } \
190 | } while (0)
191 |
192 | #define COLLECTION_STR_FIND(collection, zs_key_p, zval_result_p) \
193 | do { \
194 | zval_result_p = zend_hash_find(collection, zs_key_p); \
195 | } while (0)
196 |
197 | #define ZVAL_ARRAY_INSERT_BUCKET_KEY_ZVAL_VAL(zval_p, bucket, zval_val_p) \
198 | do { \
199 | zval value; \
200 | if (Z_TYPE(bucket->val) == IS_STRING) { \
201 | ARRAY_INDEX_FIND(zval_val_p, bucket->h, &value); \
202 | zend_hash_str_update(Z_ARR_P(zval_p), Z_STRVAL(bucket->val), Z_STRLEN(bucket->val), &value); \
203 | } \
204 | if (Z_TYPE(bucket->val) == IS_LONG) { \
205 | ARRAY_INDEX_FIND(zval_val_p, bucket->h, &value); \
206 | zend_hash_index_update(Z_ARR_P(zval_p), Z_LVAL(bucket->val), &value); \
207 | } \
208 | } while(0)
209 |
210 | #define ZVAL_IS_NOT_ARRAY_SO_CONTINUE(zval_p) \
211 | if (Z_TYPE_P(value) != IS_ARRAY) continue;
212 |
213 | #define RETURN_THIS \
214 | ZVAL_COPY(return_value, getThis());
215 |
216 | #endif
217 |
--------------------------------------------------------------------------------
/src/kernel.c:
--------------------------------------------------------------------------------
1 | /*
2 | +----------------------------------------------------------------------+
3 | | Collection Extension |
4 | +----------------------------------------------------------------------+
5 | | Copyright (c) 2016-2018 The Viest |
6 | +----------------------------------------------------------------------+
7 | | http://www.viest.me |
8 | +----------------------------------------------------------------------+
9 | | Author: viest |
10 | +----------------------------------------------------------------------+
11 | */
12 |
13 | #include "include.h"
14 |
15 | zend_class_entry *vtiful_collection_ce;
16 |
17 | /* {{{ ARG_INFO
18 | */
19 | ZEND_BEGIN_ARG_INFO_EX(collection_init_arginfo, 0, 0, 1)
20 | ZEND_ARG_INFO(0, collection)
21 | ZEND_END_ARG_INFO()
22 |
23 | ZEND_BEGIN_ARG_INFO_EX(collection_map_arginfo, 0, 0, 1)
24 | ZEND_ARG_INFO(0, callback)
25 | ZEND_END_ARG_INFO()
26 |
27 | ZEND_BEGIN_ARG_INFO_EX(collection_avg_arginfo, 0, 0, 0)
28 | ZEND_ARG_INFO(0, column)
29 | ZEND_END_ARG_INFO()
30 |
31 | ZEND_BEGIN_ARG_INFO_EX(collection_chunk_arginfo, 0, 0, 1)
32 | ZEND_ARG_INFO(0, length)
33 | ZEND_END_ARG_INFO()
34 |
35 | ZEND_BEGIN_ARG_INFO_EX(collection_combine_arginfo, 0, 0, 1)
36 | ZEND_ARG_INFO(0, array)
37 | ZEND_END_ARG_INFO()
38 |
39 | ZEND_BEGIN_ARG_INFO_EX(collection_concat_arginfo, 0, 0, 1)
40 | ZEND_ARG_INFO(0, array)
41 | ZEND_END_ARG_INFO()
42 |
43 | ZEND_BEGIN_ARG_INFO_EX(collection_contains_arginfo, 0, 0, 1)
44 | ZEND_ARG_INFO(0, key)
45 | ZEND_ARG_INFO(0, val)
46 | ZEND_END_ARG_INFO()
47 |
48 | ZEND_BEGIN_ARG_INFO_EX(collection_diff_arginfo, 0, 0, 1)
49 | ZEND_ARG_INFO(0, array)
50 | ZEND_END_ARG_INFO()
51 |
52 | ZEND_BEGIN_ARG_INFO_EX(collection_every_arginfo, 0, 0, 1)
53 | ZEND_ARG_INFO(0, callback)
54 | ZEND_END_ARG_INFO()
55 |
56 | ZEND_BEGIN_ARG_INFO_EX(collection_except_arginfo, 0, 0, 1)
57 | ZEND_ARG_INFO(0, excluded_keys)
58 | ZEND_END_ARG_INFO()
59 |
60 | ZEND_BEGIN_ARG_INFO_EX(collection_filter_arginfo, 0, 0, 0)
61 | ZEND_ARG_INFO(0, callback)
62 | ZEND_END_ARG_INFO()
63 |
64 | ZEND_BEGIN_ARG_INFO_EX(collection_first_arginfo, 0, 0, 0)
65 | ZEND_ARG_INFO(0, callback)
66 | ZEND_END_ARG_INFO()
67 |
68 | ZEND_BEGIN_ARG_INFO_EX(collection_first_where_arginfo, 0, 0, 2)
69 | ZEND_ARG_INFO(0, column)
70 | ZEND_ARG_INFO(0, val)
71 | ZEND_ARG_INFO(0, symbol)
72 | ZEND_END_ARG_INFO()
73 |
74 | ZEND_BEGIN_ARG_INFO_EX(collection_flat_map_arginfo, 0, 0, 1)
75 | ZEND_ARG_INFO(0, callback)
76 | ZEND_END_ARG_INFO()
77 |
78 | ZEND_BEGIN_ARG_INFO_EX(collection_flatten_arginfo, 0, 0, 0)
79 | ZEND_ARG_INFO(0, callback)
80 | ZEND_END_ARG_INFO()
81 |
82 | ZEND_BEGIN_ARG_INFO_EX(collection_forget_arginfo, 0, 0, 1)
83 | ZEND_ARG_INFO(0, key)
84 | ZEND_END_ARG_INFO()
85 |
86 | ZEND_BEGIN_ARG_INFO_EX(collection_for_page_arginfo, 0, 0, 2)
87 | ZEND_ARG_INFO(0, page)
88 | ZEND_ARG_INFO(0, number)
89 | ZEND_END_ARG_INFO()
90 |
91 | ZEND_BEGIN_ARG_INFO_EX(collection_get_arginfo, 0, 0, 1)
92 | ZEND_ARG_INFO(0, key)
93 | ZEND_ARG_INFO(0, default_val)
94 | ZEND_END_ARG_INFO()
95 |
96 | ZEND_BEGIN_ARG_INFO_EX(collection_group_by_arginfo, 0, 0, 1)
97 | ZEND_ARG_INFO(0, key)
98 | ZEND_END_ARG_INFO()
99 |
100 | ZEND_BEGIN_ARG_INFO_EX(collection_has_arginfo, 0, 0, 1)
101 | ZEND_ARG_INFO(0, key)
102 | ZEND_END_ARG_INFO()
103 |
104 | ZEND_BEGIN_ARG_INFO_EX(collection_implode_arginfo, 0, 0, 1)
105 | ZEND_ARG_INFO(0, key)
106 | ZEND_ARG_INFO(0, str)
107 | ZEND_END_ARG_INFO()
108 |
109 | ZEND_BEGIN_ARG_INFO_EX(collection_intersect_arginfo, 0, 0, 1)
110 | ZEND_ARG_INFO(0, array)
111 | ZEND_END_ARG_INFO()
112 |
113 | ZEND_BEGIN_ARG_INFO_EX(collection_intersect_keys_arginfo, 0, 0, 1)
114 | ZEND_ARG_INFO(0, array)
115 | ZEND_END_ARG_INFO()
116 |
117 | ZEND_BEGIN_ARG_INFO_EX(collection_key_by_arginfo, 0, 0, 1)
118 | ZEND_ARG_INFO(0, key)
119 | ZEND_END_ARG_INFO()
120 |
121 | ZEND_BEGIN_ARG_INFO_EX(collection_last_arginfo, 0, 0, 0)
122 | ZEND_ARG_INFO(0, callback)
123 | ZEND_END_ARG_INFO()
124 |
125 | ZEND_BEGIN_ARG_INFO_EX(collection_map_group_arginfo, 0, 0, 1)
126 | ZEND_ARG_INFO(0, callback)
127 | ZEND_END_ARG_INFO()
128 |
129 | ZEND_BEGIN_ARG_INFO_EX(collection_max_arginfo, 0, 0, 0)
130 | ZEND_ARG_INFO(0, key)
131 | ZEND_END_ARG_INFO()
132 | /* }}} */
133 |
134 | /** {{{ collection_methods
135 | */
136 | zend_function_entry collection_methods[] = {
137 | PHP_ME(vtiful_collection, __construct, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_CTOR)
138 | PHP_ME(vtiful_collection, __clone, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
139 | PHP_ME(vtiful_collection, init, collection_init_arginfo, ZEND_ACC_PUBLIC |ZEND_ACC_STATIC)
140 | PHP_ME(vtiful_collection, map, collection_map_arginfo, ZEND_ACC_PUBLIC)
141 | PHP_ME(vtiful_collection, all, NULL, ZEND_ACC_PUBLIC)
142 | PHP_ME(vtiful_collection, avg, collection_avg_arginfo, ZEND_ACC_PUBLIC)
143 | PHP_ME(vtiful_collection, chunk, collection_chunk_arginfo, ZEND_ACC_PUBLIC)
144 | PHP_ME(vtiful_collection, collapse, NULL, ZEND_ACC_PUBLIC)
145 | PHP_ME(vtiful_collection, count, NULL, ZEND_ACC_PUBLIC)
146 | PHP_ME(vtiful_collection, toArray, NULL, ZEND_ACC_PUBLIC)
147 | PHP_ME(vtiful_collection, combine, collection_combine_arginfo, ZEND_ACC_PUBLIC)
148 | PHP_ME(vtiful_collection, concat, collection_concat_arginfo, ZEND_ACC_PUBLIC)
149 | PHP_ME(vtiful_collection, contains, collection_contains_arginfo, ZEND_ACC_PUBLIC)
150 | PHP_ME(vtiful_collection, diff, collection_diff_arginfo, ZEND_ACC_PUBLIC)
151 | PHP_ME(vtiful_collection, diffAssoc, collection_diff_arginfo, ZEND_ACC_PUBLIC)
152 | PHP_ME(vtiful_collection, every, collection_every_arginfo, ZEND_ACC_PUBLIC)
153 | PHP_ME(vtiful_collection, except, collection_except_arginfo, ZEND_ACC_PUBLIC)
154 | PHP_ME(vtiful_collection, filter, collection_filter_arginfo, ZEND_ACC_PUBLIC)
155 | PHP_ME(vtiful_collection, first, collection_first_arginfo, ZEND_ACC_PUBLIC)
156 | PHP_ME(vtiful_collection, firstWhere, collection_first_where_arginfo, ZEND_ACC_PUBLIC)
157 | PHP_ME(vtiful_collection, flatMap, collection_flat_map_arginfo, ZEND_ACC_PUBLIC)
158 | PHP_ME(vtiful_collection, flatten, collection_flatten_arginfo, ZEND_ACC_PUBLIC)
159 | PHP_ME(vtiful_collection, flip, NULL, ZEND_ACC_PUBLIC)
160 | PHP_ME(vtiful_collection, forget, collection_forget_arginfo, ZEND_ACC_PUBLIC)
161 | PHP_ME(vtiful_collection, forPage, collection_for_page_arginfo, ZEND_ACC_PUBLIC)
162 | PHP_ME(vtiful_collection, get, collection_get_arginfo, ZEND_ACC_PUBLIC)
163 | PHP_ME(vtiful_collection, groupBy, collection_group_by_arginfo, ZEND_ACC_PUBLIC)
164 | PHP_ME(vtiful_collection, has, collection_has_arginfo, ZEND_ACC_PUBLIC)
165 | PHP_ME(vtiful_collection, implode, collection_implode_arginfo, ZEND_ACC_PUBLIC)
166 | PHP_ME(vtiful_collection, intersect, collection_intersect_arginfo, ZEND_ACC_PUBLIC)
167 | PHP_ME(vtiful_collection, intersectByKeys, collection_intersect_keys_arginfo, ZEND_ACC_PUBLIC)
168 | PHP_ME(vtiful_collection, isEmpty, NULL, ZEND_ACC_PUBLIC)
169 | PHP_ME(vtiful_collection, isNotEmpty, NULL, ZEND_ACC_PUBLIC)
170 | PHP_ME(vtiful_collection, keyBy, collection_key_by_arginfo, ZEND_ACC_PUBLIC)
171 | PHP_ME(vtiful_collection, keys, NULL, ZEND_ACC_PUBLIC)
172 | PHP_ME(vtiful_collection, last, collection_last_arginfo, ZEND_ACC_PUBLIC)
173 | PHP_ME(vtiful_collection, mapToGroups, collection_map_group_arginfo, ZEND_ACC_PUBLIC)
174 | PHP_ME(vtiful_collection, max, collection_max_arginfo, ZEND_ACC_PUBLIC)
175 | PHP_FE_END
176 | };
177 | /* }}} */
178 |
179 | /** {{{ COLLECTION_STARTUP_FUNCTION
180 | */
181 | COLLECTION_STARTUP_FUNCTION(kernel)
182 | {
183 | zend_class_entry ce;
184 |
185 | INIT_NS_CLASS_ENTRY(ce, "Vtiful\\Kernel", "Collection", collection_methods);
186 |
187 | vtiful_collection_ce = zend_register_internal_class(&ce);
188 |
189 | return SUCCESS;
190 | }
191 | /* }}} */
192 |
--------------------------------------------------------------------------------
/src/method.c:
--------------------------------------------------------------------------------
1 | /*
2 | +----------------------------------------------------------------------+
3 | | Collection Extension |
4 | +----------------------------------------------------------------------+
5 | | Copyright (c) 2016-2018 The Viest |
6 | +----------------------------------------------------------------------+
7 | | http://www.viest.me |
8 | +----------------------------------------------------------------------+
9 | | Author: viest |
10 | +----------------------------------------------------------------------+
11 | */
12 |
13 | #include "include.h"
14 | #include "common.h"
15 |
16 | /** {{{ \Vtiful\Kernel\Collection::__construct()
17 | */
18 | PHP_METHOD(vtiful_collection, __construct)
19 | {
20 |
21 | }
22 | /* }}} */
23 |
24 | /** {{{ \Vtiful\Kernel\Collection::__clone()
25 | */
26 | PHP_METHOD(vtiful_collection, __clone)
27 | {
28 |
29 | }
30 | /* }}} */
31 |
32 | /** {{{ \Vtiful\Kernel\Collection::init([array $collection])
33 | */
34 | PHP_METHOD(vtiful_collection, init)
35 | {
36 | zval *collection = NULL;
37 |
38 | ZEND_PARSE_PARAMETERS_START(0, 1)
39 | Z_PARAM_OPTIONAL
40 | Z_PARAM_ARRAY(collection)
41 | ZEND_PARSE_PARAMETERS_END();
42 |
43 | NEW_COLLECTION_OBJ(return_value, collection);
44 | }
45 | /* }}} */
46 |
47 | /** {{{ \Vtiful\Kernel\Collection::map(closures $callback)
48 | */
49 | PHP_METHOD(vtiful_collection, map)
50 | {
51 | zval fcall_result, result;
52 | zend_fcall_info fci = empty_fcall_info;
53 | zend_fcall_info_cache fci_cache = empty_fcall_info_cache;
54 |
55 | ZEND_PARSE_PARAMETERS_START(1, 1)
56 | Z_PARAM_FUNC(fci, fci_cache)
57 | ZEND_PARSE_PARAMETERS_END();
58 |
59 | INIT_FCALL(2, &fcall_result)
60 |
61 | COLLECTION_INIT(&result);
62 |
63 | ZEND_HASH_FOREACH_BUCKET(CURRENT_COLLECTION, Bucket* bucket)
64 | FCALL_TWO_ARGS(bucket)
65 | COLLECTION_ADD_INDEX_ZVAL(&result, &fcall_result)
66 | ZEND_HASH_FOREACH_END();
67 |
68 | NEW_COLLECTION_OBJ(return_value, &result);
69 |
70 | VC_ZVAL_DTOR(result);
71 | }
72 | /* }}} */
73 |
74 | /** {{{ \Vtiful\Kernel\Collection::all()
75 | */
76 | PHP_METHOD(vtiful_collection, all)
77 | {
78 | GC_ADDREF(CURRENT_COLLECTION);
79 |
80 | ZVAL_ARR(return_value, CURRENT_COLLECTION);
81 | }
82 | /* }}} */
83 |
84 | /** {{{ \Vtiful\Kernel\Collection::avg([string $key])
85 | */
86 | PHP_METHOD(vtiful_collection, avg)
87 | {
88 | zend_string *column = NULL;
89 |
90 | ZEND_PARSE_PARAMETERS_START(0, 1)
91 | Z_PARAM_OPTIONAL
92 | Z_PARAM_STR(column)
93 | ZEND_PARSE_PARAMETERS_END();
94 |
95 | double sum = 0;
96 |
97 | if (column == NULL) {
98 | sum = average_no_column(CURRENT_COLLECTION);
99 | } else {
100 | sum = average_column(CURRENT_COLLECTION, column);
101 | }
102 |
103 | ZVAL_DOUBLE(return_value, (sum/zend_hash_num_elements(CURRENT_COLLECTION)))
104 | }
105 | /* }}} */
106 |
107 | /** {{{ \Vtiful\Kernel\Collection::chunk(int $length)
108 | */
109 | PHP_METHOD(vtiful_collection, chunk)
110 | {
111 | zend_long length;
112 |
113 | ZEND_PARSE_PARAMETERS_START(1, 1)
114 | Z_PARAM_LONG(length)
115 | ZEND_PARSE_PARAMETERS_END();
116 |
117 | if (length < 1) {
118 | zend_throw_exception(vtiful_collection_exception_ce, "Parameter cannot be less than 1", 10);
119 | }
120 |
121 | NEW_ZVAL_OBJ(return_value);
122 |
123 | collection_chunk(CURRENT_COLLECTION, length, return_value);
124 | }
125 | /* }}} */
126 |
127 | /** {{{ \Vtiful\Kernel\Collection::collapse()
128 | */
129 | PHP_METHOD(vtiful_collection, collapse)
130 | {
131 | zval result;
132 |
133 | COLLECTION_INIT(&result);
134 |
135 | collection_collapse(CURRENT_COLLECTION, &result);
136 |
137 | NEW_COLLECTION_OBJ(return_value, &result);
138 |
139 | VC_ZVAL_DTOR(result);
140 | }
141 | /* }}} */
142 |
143 | /** {{{ \Vtiful\Kernel\Collection::count()
144 | */
145 | PHP_METHOD(vtiful_collection, count)
146 | {
147 | ZVAL_LONG(return_value, CURRENT_COLLECTION_COUNT);
148 | }
149 | /* }}} */
150 |
151 | /** {{{ \Vtiful\Kernel\Collection::toArray()
152 | */
153 | PHP_METHOD(vtiful_collection, toArray)
154 | {
155 | ZVAL_ARR(return_value, CURRENT_COLLECTION);
156 |
157 | GC_ZVAL_ADDREF(return_value);
158 | }
159 | /* }}} */
160 |
161 | /** {{{ \Vtiful\Kernel\Collection::combine(array $arrVal)
162 | */
163 | PHP_METHOD(vtiful_collection, combine)
164 | {
165 | zval result, *val = NULL;
166 |
167 | ZEND_PARSE_PARAMETERS_START(1, 1)
168 | Z_PARAM_ARRAY(val)
169 | ZEND_PARSE_PARAMETERS_END();
170 |
171 | COLLECTION_INIT(&result);
172 |
173 | collection_combine(CURRENT_COLLECTION, val, &result);
174 |
175 | NEW_COLLECTION_OBJ(return_value, &result);
176 |
177 | VC_ZVAL_DTOR(result);
178 | }
179 | /* }}} */
180 |
181 | /** {{{ \Vtiful\Kernel\Collection::concat(array $arrVal)
182 | */
183 | PHP_METHOD(vtiful_collection, concat)
184 | {
185 | zval result, *val = NULL;
186 |
187 | ZEND_PARSE_PARAMETERS_START(1, 1)
188 | Z_PARAM_ARRAY(val)
189 | ZEND_PARSE_PARAMETERS_END();
190 |
191 | COLLECTION_INIT(&result);
192 |
193 | collection_concat(CURRENT_COLLECTION, val, &result);
194 |
195 | NEW_COLLECTION_OBJ(return_value, &result);
196 |
197 | VC_ZVAL_DTOR(result);
198 | }
199 | /* }}} */
200 |
201 | /** {{{ \Vtiful\Kernel\Collection::contains(string $value[, string $value])
202 | */
203 | PHP_METHOD(vtiful_collection, contains)
204 | {
205 | zval *key = NULL, *val = NULL;
206 |
207 | ZEND_PARSE_PARAMETERS_START(1, 2)
208 | Z_PARAM_ZVAL(key)
209 | Z_PARAM_OPTIONAL
210 | Z_PARAM_ZVAL(val)
211 | ZEND_PARSE_PARAMETERS_END();
212 |
213 | if (val == NULL) {
214 | VAL_IN_COLLECTION(CURRENT_COLLECTION, key, return_value);
215 | } else {
216 | KV_IN_COLLECTION(CURRENT_COLLECTION, key, val, return_value);
217 | }
218 | }
219 | /* }}} */
220 |
221 | /** {{{ \Vtiful\Kernel\Collection::diff(array $array)
222 | */
223 | PHP_METHOD(vtiful_collection, diff)
224 | {
225 | zval result, *val = NULL;
226 |
227 | ZEND_PARSE_PARAMETERS_START(1, 1)
228 | Z_PARAM_ARRAY(val)
229 | ZEND_PARSE_PARAMETERS_END();
230 |
231 | collection_diff(CURRENT_COLLECTION, val, &result);
232 |
233 | NEW_COLLECTION_OBJ(return_value, &result);
234 |
235 | VC_ZVAL_DTOR(result);
236 | }
237 | /* }}} */
238 |
239 | /** {{{ \Vtiful\Kernel\Collection::diffAssoc(array $array)
240 | */
241 | PHP_METHOD(vtiful_collection, diffAssoc)
242 | {
243 | zval result, *val = NULL;
244 |
245 | ZEND_PARSE_PARAMETERS_START(1, 1)
246 | Z_PARAM_ARRAY(val)
247 | ZEND_PARSE_PARAMETERS_END();
248 |
249 | collection_diff_assoc(CURRENT_COLLECTION, val, &result);
250 |
251 | NEW_COLLECTION_OBJ(return_value, &result);
252 |
253 | VC_ZVAL_DTOR(result);
254 | }
255 | /* }}} */
256 |
257 | /** {{{ \Vtiful\Kernel\Collection::every(closures $callback)
258 | */
259 | PHP_METHOD(vtiful_collection, every)
260 | {
261 | zval fcall_result;
262 | zend_fcall_info fci = empty_fcall_info;
263 | zend_fcall_info_cache fci_cache = empty_fcall_info_cache;
264 |
265 | ZEND_PARSE_PARAMETERS_START(1, 1)
266 | Z_PARAM_FUNC(fci, fci_cache)
267 | ZEND_PARSE_PARAMETERS_END();
268 |
269 | INIT_FCALL(2, &fcall_result)
270 |
271 | ZEND_HASH_FOREACH_BUCKET(CURRENT_COLLECTION, Bucket* bucket)
272 | FCALL_TWO_ARGS(bucket)
273 |
274 | if (Z_TYPE_INFO(fcall_result) == IS_FALSE) {
275 | ZVAL_FALSE(return_value);
276 | break;
277 | }
278 | ZEND_HASH_FOREACH_END();
279 |
280 | ZVAL_TRUE(return_value);
281 | }
282 | /* }}} */
283 |
284 | /** {{{ \Vtiful\Kernel\Collection::except(array $excludedKeys)
285 | */
286 | PHP_METHOD(vtiful_collection, except)
287 | {
288 | zval result, *excluded_keys = NULL;
289 |
290 | ZEND_PARSE_PARAMETERS_START(1,1)
291 | Z_PARAM_ARRAY(excluded_keys)
292 | ZEND_PARSE_PARAMETERS_END();
293 |
294 | COLLECTION_INIT(&result);
295 |
296 | collection_except(CURRENT_COLLECTION, excluded_keys, &result);
297 |
298 | NEW_COLLECTION_OBJ(return_value, &result);
299 |
300 | VC_ZVAL_DTOR(result);
301 | }
302 | /* }}} */
303 |
304 | /** {{{ \Vtiful\Kernel\Collection::filter(closures $callback)
305 | */
306 | PHP_METHOD(vtiful_collection, filter)
307 | {
308 | zval fcall_result, result;
309 | zend_fcall_info fci = empty_fcall_info;
310 | zend_fcall_info_cache fci_cache = empty_fcall_info_cache;
311 |
312 | ZEND_PARSE_PARAMETERS_START(0, 1)
313 | Z_PARAM_OPTIONAL
314 | Z_PARAM_FUNC(fci, fci_cache)
315 | ZEND_PARSE_PARAMETERS_END();
316 |
317 | COLLECTION_INIT(&result);
318 |
319 | if (ZEND_NUM_ARGS() < 1) {
320 | ZEND_HASH_FOREACH_BUCKET(CURRENT_COLLECTION, Bucket* bucket)
321 | ZVAL_COPY(&fcall_result, &bucket->val);
322 | convert_to_boolean(&fcall_result);
323 | if (Z_TYPE_INFO(fcall_result) == IS_FALSE) {
324 | continue;
325 | }
326 | add_next_index_zval(&result, &bucket->val);
327 | ZEND_HASH_FOREACH_END();
328 | } else {
329 | INIT_FCALL(2, &fcall_result)
330 | ZEND_HASH_FOREACH_BUCKET(CURRENT_COLLECTION, Bucket* bucket)
331 | FCALL_TWO_ARGS(bucket)
332 | if (Z_TYPE_INFO(fcall_result) == IS_FALSE) {
333 | continue;
334 | }
335 | add_next_index_zval(&result, &bucket->val);
336 | ZEND_HASH_FOREACH_END();
337 | }
338 |
339 | NEW_COLLECTION_OBJ(return_value, &result);
340 |
341 | VC_ZVAL_DTOR(result);
342 | }
343 | /* }}} */
344 |
345 | /** {{{ \Vtiful\Kernel\Collection::first([closures $callback])
346 | */
347 | PHP_METHOD(vtiful_collection, first)
348 | {
349 | zend_fcall_info fci = empty_fcall_info;
350 | zend_fcall_info_cache fci_cache = empty_fcall_info_cache;
351 |
352 | ZEND_PARSE_PARAMETERS_START(0, 1)
353 | Z_PARAM_OPTIONAL
354 | Z_PARAM_FUNC(fci, fci_cache)
355 | ZEND_PARSE_PARAMETERS_END();
356 |
357 | if (ZEND_NUM_ARGS() < 1) {
358 | ZVAL_COPY(return_value, &(CURRENT_COLLECTION->arData[0].val));
359 | } else {
360 | zval fcall_result;
361 |
362 | INIT_FCALL(2, &fcall_result)
363 |
364 | ZEND_HASH_FOREACH_BUCKET(CURRENT_COLLECTION, Bucket* bucket)
365 | FCALL_TWO_ARGS(bucket)
366 |
367 | if (Z_TYPE_INFO(fcall_result) == IS_TRUE) {
368 | ZVAL_COPY(return_value, &(bucket->val));
369 | break;
370 | }
371 | ZEND_HASH_FOREACH_END();
372 | }
373 | }
374 | /* }}} */
375 |
376 |
377 | /** {{{ \Vtiful\Kernel\Collection::firstWhere(mixed $column, mixed $val)
378 | */
379 | PHP_METHOD(vtiful_collection, firstWhere)
380 | {
381 | zval result, *find_res = NULL, *symbol = NULL;
382 | zend_string *column = NULL, *val = NULL;
383 |
384 | ZEND_PARSE_PARAMETERS_START(2, 3)
385 | Z_PARAM_STR(column)
386 | Z_PARAM_STR(val)
387 | Z_PARAM_OPTIONAL
388 | Z_PARAM_ZVAL(symbol)
389 | ZEND_PARSE_PARAMETERS_END();
390 |
391 | if (ZEND_NUM_ARGS() == 2) {
392 | zval zval_zstr;
393 |
394 | ZEND_HASH_FOREACH_VAL(CURRENT_COLLECTION, zval *value)
395 | ZVAL_IS_NOT_ARRAY_SO_CONTINUE(value)
396 |
397 | ARRAY_STR_FIND(value, column, find_res);
398 |
399 | if (find_res != NULL) {
400 | ZVAL_STR(&zval_zstr, val);
401 | if (zval_equal(find_res, &zval_zstr)) {
402 | ZVAL_COPY(&result, value);
403 | break;
404 | }
405 | }
406 | ZEND_HASH_FOREACH_END();
407 |
408 | VC_ZVAL_DTOR(zval_zstr);
409 | } else if (ZEND_NUM_ARGS() == 3) {
410 | ZEND_HASH_FOREACH_VAL(CURRENT_COLLECTION, zval *value)
411 | ZVAL_IS_NOT_ARRAY_SO_CONTINUE(value)
412 |
413 | ARRAY_STR_FIND(value, column, find_res);
414 |
415 | if (find_res != NULL) {
416 | if (zval_comparison_operations(val, find_res, symbol)) {
417 | ZVAL_COPY(&result, value);
418 | break;
419 | }
420 | }
421 | ZEND_HASH_FOREACH_END();
422 | }
423 |
424 | NEW_COLLECTION_OBJ(return_value, &result);
425 |
426 | VC_ZVAL_DTOR(result);
427 | }
428 | /* }}} */
429 |
430 | /** {{{ \Vtiful\Kernel\Collection::flatMap(closures $callback)
431 | */
432 | PHP_METHOD(vtiful_collection, flatMap)
433 | {
434 | zval fcall_result, result;
435 | zend_fcall_info fci = empty_fcall_info;
436 | zend_fcall_info_cache fci_cache = empty_fcall_info_cache;
437 |
438 | ZEND_PARSE_PARAMETERS_START(1, 1)
439 | Z_PARAM_FUNC(fci, fci_cache)
440 | ZEND_PARSE_PARAMETERS_END();
441 |
442 | INIT_FCALL(1, &fcall_result);
443 |
444 | COLLECTION_INIT_IN_CURRENT(&result);
445 |
446 | ZEND_HASH_FOREACH_BUCKET(CURRENT_COLLECTION, Bucket *bucket)
447 | FCALL_ONE_ARGS(bucket);
448 | COLLECTION_UPDATE(&result, bucket, &fcall_result);
449 | FCALL_DTOR(1);
450 | ZEND_HASH_FOREACH_END();
451 |
452 | NEW_COLLECTION_OBJ(return_value, &result);
453 |
454 | VC_ZVAL_DTOR(result);
455 | }
456 | /* }}} */
457 |
458 | /** {{{ \Vtiful\Kernel\Collection::flatten([int $depth])
459 | */
460 | PHP_METHOD(vtiful_collection, flatten)
461 | {
462 | zval result;
463 | zend_long depth = 1;
464 |
465 | ZEND_PARSE_PARAMETERS_START(0, 1)
466 | Z_PARAM_OPTIONAL
467 | Z_PARAM_LONG(depth)
468 | ZEND_PARSE_PARAMETERS_END();
469 |
470 | COLLECTION_INIT(&result);
471 |
472 | collection_flatten(CURRENT_COLLECTION, depth, &result);
473 |
474 | NEW_COLLECTION_OBJ(return_value, &result);
475 |
476 | VC_ZVAL_DTOR(result);
477 | }
478 | /* }}} */
479 |
480 | /** {{{ \Vtiful\Kernel\Collection::flip()
481 | */
482 | PHP_METHOD(vtiful_collection, flip)
483 | {
484 | zval result;
485 |
486 | collection_flip(CURRENT_COLLECTION, &result);
487 |
488 | NEW_COLLECTION_OBJ(return_value, &result);
489 |
490 | VC_ZVAL_DTOR(result);
491 | }
492 | /* }}} */
493 |
494 | /** {{{ \Vtiful\Kernel\Collection::forget(string $key)
495 | */
496 | PHP_METHOD(vtiful_collection, forget)
497 | {
498 | zend_string *key = NULL;
499 |
500 | ZEND_PARSE_PARAMETERS_START(1, 1)
501 | Z_PARAM_STR(key)
502 | ZEND_PARSE_PARAMETERS_END();
503 |
504 | COLLECTION_STRING_DELETE(CURRENT_COLLECTION, key);
505 |
506 | RETURN_THIS
507 | }
508 | /* }}} */
509 |
510 | /** {{{ \Vtiful\Kernel\Collection::forPage(int $page, int $number)
511 | */
512 | PHP_METHOD(vtiful_collection, forPage)
513 | {
514 | zval result;
515 | zend_long page, number;
516 |
517 | ZEND_PARSE_PARAMETERS_START(2, 2)
518 | Z_PARAM_LONG(page)
519 | Z_PARAM_LONG(number)
520 | ZEND_PARSE_PARAMETERS_END();
521 |
522 | COLLECTION_INIT(&result);
523 |
524 | collection_for_page(CURRENT_COLLECTION, page, number, &result);
525 |
526 | NEW_COLLECTION_OBJ(return_value, &result);
527 |
528 | VC_ZVAL_DTOR(result);
529 | }
530 | /* }}} */
531 |
532 | /** {{{ \Vtiful\Kernel\Collection::get(mixed $key [, mixed $default])
533 | */
534 | PHP_METHOD(vtiful_collection, get)
535 | {
536 | zval *key, *default_val = NULL, *find_result = NULL;
537 |
538 | ZEND_PARSE_PARAMETERS_START(1, 2)
539 | Z_PARAM_ZVAL(key)
540 | Z_PARAM_OPTIONAL
541 | Z_PARAM_ZVAL(default_val)
542 | ZEND_PARSE_PARAMETERS_END();
543 |
544 | if (Z_TYPE_P(key) == IS_LONG) {
545 | COLLECTION_INDEX_FIND(CURRENT_COLLECTION, Z_LVAL_P(key), find_result);
546 | }
547 |
548 | if (Z_TYPE_P(key) == IS_STRING) {
549 | COLLECTION_STR_FIND(CURRENT_COLLECTION, Z_STR_P(key), find_result);
550 | }
551 |
552 | if (find_result == NULL || Z_TYPE_P(find_result) == IS_NULL) {
553 | if (ZEND_NUM_ARGS() < 2) {
554 | ZVAL_NULL(return_value);
555 | } else {
556 | ZVAL_COPY(return_value, default_val);
557 | }
558 | } else {
559 | ZVAL_COPY(return_value, find_result);
560 | }
561 | }
562 | /* }}} */
563 |
564 | /** {{{ \Vtiful\Kernel\Collection::groupBy(mixed $key)
565 | */
566 | PHP_METHOD(vtiful_collection, groupBy)
567 | {
568 | zval result;
569 |
570 | zend_string *key = NULL;
571 |
572 | zend_fcall_info fci = empty_fcall_info;
573 | zend_fcall_info_cache fci_cache = empty_fcall_info_cache;
574 |
575 | ZEND_PARSE_PARAMETERS_START(1, 1)
576 | _real_arg++;
577 | if (Z_TYPE_P(_real_arg) == IS_STRING) {
578 | _real_arg--;
579 | Z_PARAM_STR(key);
580 | }
581 | if (Z_TYPE_P(_real_arg) == IS_OBJECT) {
582 | _real_arg--;
583 | Z_PARAM_FUNC(fci, fci_cache);
584 | }
585 | ZEND_PARSE_PARAMETERS_END();
586 |
587 | COLLECTION_INIT(&result);
588 |
589 | if (key == NULL) {
590 | zval fcall_res;
591 |
592 | INIT_FCALL(2, &fcall_res);
593 |
594 | ZEND_HASH_FOREACH_BUCKET(CURRENT_COLLECTION, Bucket *bucket)
595 | FCALL_TWO_ARGS(bucket);
596 | collection_group(&(bucket->val), return_value, NULL, &fcall_res, &result);
597 | VC_ZVAL_DTOR(fcall_res);
598 | ZEND_HASH_FOREACH_END();
599 | } else {
600 | ZEND_HASH_FOREACH_VAL(CURRENT_COLLECTION, zval *value)
601 | collection_group(value, return_value, key, NULL, &result);
602 | ZEND_HASH_FOREACH_END();
603 | }
604 |
605 | NEW_COLLECTION_OBJ(return_value, &result);
606 |
607 | VC_ZVAL_DTOR(result);
608 | }
609 | /* }}} */
610 |
611 | /** {{{ \Vtiful\Kernel\Collection::hash(mixed $key)
612 | */
613 | PHP_METHOD(vtiful_collection, has)
614 | {
615 | zval *key = NULL, *find_res = NULL;
616 |
617 | ZEND_PARSE_PARAMETERS_START(1, 1)
618 | Z_PARAM_ZVAL(key)
619 | ZEND_PARSE_PARAMETERS_END();
620 |
621 | if (Z_TYPE_P(key) == IS_STRING) {
622 | COLLECTION_STR_FIND(CURRENT_COLLECTION, Z_STR_P(key), find_res);
623 | }
624 |
625 | if (Z_TYPE_P(key) == IS_LONG) {
626 | COLLECTION_INDEX_FIND(CURRENT_COLLECTION, Z_LVAL_P(key), find_res);
627 | }
628 |
629 | if (find_res == NULL) {
630 | ZVAL_FALSE(return_value);
631 | return;
632 | }
633 |
634 | ZVAL_TRUE(return_value);
635 | }
636 | /* }}} */
637 |
638 | /** {{{ \Vtiful\Kernel\Collection::implode(mixed $key, string $str)
639 | */
640 | PHP_METHOD(vtiful_collection, implode)
641 | {
642 | zend_string *key = NULL, *str = NULL, *result = NULL, *z_str_p = NULL;
643 | size_t element_char_len = 0, elements_len = 0, new_string_len = 0;
644 | zval tmp_zval_array;
645 |
646 | ZEND_PARSE_PARAMETERS_START(1, 2)
647 | Z_PARAM_STR(key)
648 | Z_PARAM_OPTIONAL
649 | Z_PARAM_STR(str)
650 | ZEND_PARSE_PARAMETERS_END();
651 |
652 | COLLECTION_INIT(&tmp_zval_array);
653 |
654 | elements_len = zend_hash_num_elements(CURRENT_COLLECTION);
655 |
656 | if (str == NULL) {
657 | ZEND_HASH_FOREACH_VAL(CURRENT_COLLECTION, zval *val)
658 | z_str_p = _zval_get_string_func(val);
659 | element_char_len += ZSTR_LEN(z_str_p);
660 | add_next_index_str(&tmp_zval_array, z_str_p);
661 | ZEND_HASH_FOREACH_END();
662 | } else {
663 | zval *find_result = NULL;
664 |
665 | ZEND_HASH_FOREACH_VAL(CURRENT_COLLECTION, zval *val)
666 | if (Z_TYPE_P(val) != IS_ARRAY) {
667 | continue;
668 | }
669 | COLLECTION_STR_FIND(Z_ARR_P(val), key, find_result);
670 | z_str_p = _zval_get_string_func(find_result);
671 | element_char_len += ZSTR_LEN(z_str_p);
672 | add_next_index_str(&tmp_zval_array, z_str_p);
673 | ZEND_HASH_FOREACH_END();
674 | }
675 |
676 | if (ZEND_NUM_ARGS() < 2) {
677 | new_string_len = element_char_len+(ZSTR_LEN(key)*elements_len)-ZSTR_LEN(key);
678 | result = zend_string_safe_alloc(elements_len - 1, ZSTR_LEN(key), element_char_len, 0);
679 | collection_implode(Z_ARR(tmp_zval_array), key, result);
680 | ZSTR_VAL(result)[new_string_len] = '\0';
681 | } else {
682 | new_string_len = element_char_len+(ZSTR_LEN(str)*elements_len)-ZSTR_LEN(str);
683 | result = zend_string_safe_alloc(elements_len - 1, ZSTR_LEN(str), element_char_len, 0);
684 | collection_implode(Z_ARR(tmp_zval_array), str, result);
685 | ZSTR_VAL(result)[new_string_len] = '\0';
686 | }
687 |
688 | ZVAL_STR(return_value, result);
689 |
690 | VC_ZVAL_DTOR(tmp_zval_array);
691 | }
692 | /* }}} */
693 |
694 | /** {{{ \Vtiful\Kernel\Collection::intersect(array $array)
695 | */
696 | PHP_METHOD(vtiful_collection, intersect)
697 | {
698 | zval *array = NULL, *find_res = NULL;
699 | zval total, screening, result;
700 | size_t current_length = 0;
701 |
702 | ZEND_PARSE_PARAMETERS_START(1, 1)
703 | Z_PARAM_ARRAY(array)
704 | ZEND_PARSE_PARAMETERS_END();
705 |
706 | COLLECTION_INIT_IN_CURRENT(&total);
707 |
708 | current_length = CURRENT_COLLECTION_COUNT;
709 |
710 | ZEND_HASH_FOREACH_VAL(Z_ARR_P(array), zval *val)
711 | add_index_zval(&total, ++current_length, val);
712 | GC_ZVAL_ADDREF(val);
713 | ZEND_HASH_FOREACH_END();
714 |
715 | COLLECTION_INIT(&screening);
716 | COLLECTION_INIT(&result);
717 |
718 | ZEND_HASH_FOREACH_VAL(Z_ARR(total), zval *val)
719 | if (Z_TYPE_P(val) == IS_STRING) {
720 | zend_string *tmp = Z_STR_P(val);
721 |
722 | find_res = zend_hash_find(Z_ARR(screening), tmp);
723 |
724 | if (find_res == NULL) {
725 | add_assoc_long_ex(&screening, ZSTR_VAL(tmp), ZSTR_LEN(tmp), 1);
726 | } else {
727 | add_next_index_zval(&result, val);
728 | }
729 | }
730 |
731 | if (Z_TYPE_P(val) == IS_LONG) {
732 | find_res = zend_hash_index_find(Z_ARR(screening), Z_LVAL_P(val));
733 |
734 | if (find_res == NULL) {
735 | add_index_long(&screening, Z_LVAL_P(val), 1);
736 | } else {
737 | add_next_index_zval(&result, val);
738 | }
739 | }
740 | ZEND_HASH_FOREACH_END();
741 |
742 | NEW_COLLECTION_OBJ(return_value, &result);
743 |
744 | VC_ZVAL_DTOR(screening);
745 | VC_ZVAL_DTOR(result);
746 | VC_ZVAL_DTOR(total);
747 | }
748 | /* }}} */
749 |
750 | /** {{{ \Vtiful\Kernel\Collection::intersectByKeys(array $array)
751 | */
752 | PHP_METHOD(vtiful_collection, intersectByKeys)
753 | {
754 | zval *array = NULL, *find_res = NULL;
755 | zval result;
756 |
757 | ZEND_PARSE_PARAMETERS_START(1, 1)
758 | Z_PARAM_ARRAY(array)
759 | ZEND_PARSE_PARAMETERS_END();
760 |
761 | COLLECTION_INIT(&result);
762 |
763 | ZEND_HASH_FOREACH_KEY_VAL(Z_ARR_P(array), zend_ulong long_key, zend_string *str_key, zval *val)
764 | if (str_key == NULL) {
765 | find_res = zend_hash_index_find(CURRENT_COLLECTION, long_key);
766 | } else {
767 | find_res = zend_hash_find(CURRENT_COLLECTION, str_key);
768 | }
769 |
770 | if (find_res != NULL) {
771 | if (str_key == NULL) {
772 | add_index_zval(&result, long_key, find_res);
773 | } else {
774 | add_assoc_zval_ex(&result, ZSTR_VAL(str_key), ZSTR_LEN(str_key), find_res);
775 | }
776 |
777 | GC_ZVAL_ADDREF(find_res);
778 | }
779 | ZEND_HASH_FOREACH_END();
780 |
781 | NEW_COLLECTION_OBJ(return_value, &result);
782 |
783 | VC_ZVAL_DTOR(result);
784 | }
785 | /* }}} */
786 |
787 | /** {{{ \Vtiful\Kernel\Collection::isEmpty()
788 | */
789 | PHP_METHOD(vtiful_collection, isEmpty)
790 | {
791 | if (CURRENT_COLLECTION_COUNT) {
792 | RETURN_TRUE;
793 | }
794 |
795 | RETURN_FALSE;
796 | }
797 | /* }}} */
798 |
799 | /** {{{ \Vtiful\Kernel\Collection::isNotEmpty()
800 | */
801 | PHP_METHOD(vtiful_collection, isNotEmpty)
802 | {
803 | if (CURRENT_COLLECTION_COUNT) {
804 | RETURN_FALSE;
805 | }
806 |
807 | RETURN_TRUE;
808 | }
809 | /* }}} */
810 |
811 | /** {{{ \Vtiful\Kernel\Collection::keyBy(string $key)
812 | */
813 | PHP_METHOD(vtiful_collection, keyBy)
814 | {
815 | zval result;
816 |
817 | zend_string *key = NULL;
818 |
819 | zend_fcall_info fci = empty_fcall_info;
820 | zend_fcall_info_cache fci_cache = empty_fcall_info_cache;
821 |
822 | ZEND_PARSE_PARAMETERS_START(1, 1)
823 | _real_arg++;
824 | if (Z_TYPE_P(_real_arg) == IS_STRING) {
825 | _real_arg--;
826 | Z_PARAM_STR(key);
827 | }
828 | if (Z_TYPE_P(_real_arg) == IS_OBJECT) {
829 | _real_arg--;
830 | Z_PARAM_FUNC(fci, fci_cache);
831 | }
832 | ZEND_PARSE_PARAMETERS_END();
833 |
834 | COLLECTION_INIT(&result);
835 |
836 | if (key) {
837 | zval *find_res = NULL;
838 |
839 | ZEND_HASH_FOREACH_VAL(CURRENT_COLLECTION, zval *val)
840 | if (Z_TYPE_P(val) != IS_ARRAY)
841 | continue;
842 | COLLECTION_STR_FIND(Z_ARR_P(val), key, find_res);
843 | if (find_res == NULL)
844 | continue;
845 | if (Z_TYPE_P(find_res) == IS_STRING)
846 | add_assoc_zval_ex(&result, Z_STRVAL_P(find_res), Z_STRLEN_P(find_res), val);
847 | GC_ZVAL_ADDREF(val);
848 | ZEND_HASH_FOREACH_END();
849 | } else {
850 | zval fcall_res;
851 |
852 | INIT_FCALL(1, &fcall_res);
853 |
854 | ZEND_HASH_FOREACH_BUCKET(CURRENT_COLLECTION, Bucket *bucket)
855 | if (Z_TYPE(bucket->val) != IS_ARRAY)
856 | continue;
857 | FCALL_ONE_ARGS(bucket);
858 | add_assoc_zval_ex(&result, Z_STRVAL(fcall_res), Z_STRLEN(fcall_res), &bucket->val);
859 | VC_ZVAL_DTOR(fcall_res);
860 | GC_ZVAL_ADDREF(&bucket->val);
861 | ZEND_HASH_FOREACH_END();
862 | }
863 |
864 | NEW_COLLECTION_OBJ(return_value, &result);
865 |
866 | VC_ZVAL_DTOR(result);
867 | }
868 | /* }}} */
869 |
870 | /** {{{ \Vtiful\Kernel\Collection::keys()
871 | */
872 | PHP_METHOD(vtiful_collection, keys)
873 | {
874 | zval result;
875 |
876 | COLLECTION_INIT(&result);
877 |
878 | ZEND_HASH_FOREACH_KEY(CURRENT_COLLECTION, zend_ulong long_key, zend_string *str_key)
879 | if (str_key) {
880 | add_next_index_str(&result, str_key);
881 | } else {
882 | add_next_index_long(&result, long_key);
883 | }
884 | ZEND_HASH_FOREACH_END();
885 |
886 | NEW_COLLECTION_OBJ(return_value, &result);
887 |
888 | VC_ZVAL_DTOR(result);
889 | }
890 | /* }}} */
891 |
892 | /** {{{ \Vtiful\Kernel\Collection::last([callback $callback])
893 | */
894 | PHP_METHOD(vtiful_collection, last)
895 | {
896 | zend_fcall_info fci = empty_fcall_info;
897 | zend_fcall_info_cache fci_cache = empty_fcall_info_cache;
898 |
899 | ZEND_PARSE_PARAMETERS_START(0, 1)
900 | Z_PARAM_OPTIONAL
901 | Z_PARAM_FUNC(fci, fci_cache);
902 | ZEND_PARSE_PARAMETERS_END();
903 |
904 | if (fci.size) {
905 | zval fcall_res;
906 | INIT_FCALL(2, &fcall_res);
907 | ZEND_HASH_FOREACH_BUCKET(CURRENT_COLLECTION, Bucket *bucket)
908 | FCALL_TWO_ARGS(bucket);
909 | if (Z_TYPE(fcall_res) == IS_TRUE)
910 | ZVAL_COPY(return_value, &bucket->val);
911 | ZEND_HASH_FOREACH_END();
912 | } else {
913 | zval *find_res;
914 | COLLECTION_INDEX_FIND(CURRENT_COLLECTION, CURRENT_COLLECTION_COUNT-1, find_res);
915 | ZVAL_COPY(return_value, find_res);
916 | }
917 | }
918 | /* }}} */
919 |
920 | /** {{{ \Vtiful\Kernel\Collection::mapToGroups(callback $callback)
921 | */
922 | PHP_METHOD(vtiful_collection, mapToGroups)
923 | {
924 | zval fcall_res, result;
925 | zval *find_res = NULL, *new_val = NULL;
926 | zend_string *str_key = NULL;
927 | zend_ulong long_key;
928 | zend_fcall_info fci = empty_fcall_info;
929 | zend_fcall_info_cache fci_cache = empty_fcall_info_cache;
930 |
931 | ZEND_PARSE_PARAMETERS_START(1, 1)
932 | Z_PARAM_FUNC(fci, fci_cache);
933 | ZEND_PARSE_PARAMETERS_END();
934 |
935 | COLLECTION_INIT(&result);
936 | INIT_FCALL(2, &fcall_res);
937 |
938 | ZEND_HASH_FOREACH_BUCKET(CURRENT_COLLECTION, Bucket *bucket)
939 | FCALL_TWO_ARGS(bucket);
940 | if (Z_TYPE(fcall_res) != IS_ARRAY)
941 | continue;
942 |
943 | zend_hash_get_current_key(Z_ARR(fcall_res), &str_key, &long_key);
944 |
945 | if(str_key) {
946 | COLLECTION_STR_FIND(Z_ARR(result), str_key, find_res);
947 | if (find_res == NULL) {
948 | COLLECTION_TMP(find_res);
949 | }
950 | new_val = COLLECTION_INDEX_ZVAL(&fcall_res, 0);
951 | zend_hash_next_index_insert(Z_ARR_P(find_res), new_val);
952 | zend_hash_add(Z_ARR(result), str_key, find_res);
953 | zend_string_release(str_key);
954 | } else {
955 | COLLECTION_INDEX_FIND(Z_ARR(result), long_key, find_res);
956 | if (find_res == NULL) {
957 | COLLECTION_TMP(find_res);
958 | }
959 | new_val = COLLECTION_INDEX_ZVAL(&fcall_res, long_key);
960 | zend_hash_next_index_insert(Z_ARR_P(find_res), new_val);
961 | zend_hash_index_add(Z_ARR(result), long_key, find_res);
962 | }
963 | GC_ZVAL_ADDREF(new_val);
964 | VC_ZVAL_DTOR(fcall_res);
965 | ZEND_HASH_FOREACH_END();
966 |
967 | NEW_COLLECTION_OBJ(return_value, &result);
968 | VC_ZVAL_DTOR(result);
969 | }
970 | /* }}} */
971 |
972 | /** {{{ \Vtiful\Kernel\Collection::max([string $key])
973 | */
974 | PHP_METHOD(vtiful_collection, max)
975 | {
976 | zval *result = NULL;
977 | zend_string *key = NULL;
978 |
979 | ZEND_PARSE_PARAMETERS_START(0, 1)
980 | Z_PARAM_OPTIONAL
981 | Z_PARAM_STR(key);
982 | ZEND_PARSE_PARAMETERS_END();
983 |
984 | if (ZEND_NUM_ARGS() < 1) {
985 | result = zend_hash_minmax(CURRENT_COLLECTION, collection_compare, 1);
986 | } else {
987 | result = zend_hash_key_minmax(CURRENT_COLLECTION, key, collection_compare_by_key, 1);
988 | }
989 |
990 | ZVAL_COPY(return_value, result);
991 | }
992 | /* }}} */
--------------------------------------------------------------------------------
/tests/all.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | all();
12 |
13 | var_dump($result);
14 | ?>
15 | --EXPECT--
16 | array(5) {
17 | [0]=>
18 | int(1)
19 | [1]=>
20 | int(2)
21 | [2]=>
22 | int(3)
23 | [3]=>
24 | int(4)
25 | [4]=>
26 | int(5)
27 | }
28 |
29 |
30 |
--------------------------------------------------------------------------------
/tests/avg.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | avg();
9 | $collection2 = \Vtiful\Kernel\Collection::init([
10 | ['name' => 'vikin', 'age' => 20],
11 | ['name' => 'viest', 'age' => 30]
12 | ]);
13 | $result2 = $collection2->avg('age');
14 |
15 | var_dump($result1);
16 | var_dump($result2);
17 | ?>
18 | --EXPECT--
19 | float(3)
20 | float(25)
21 |
--------------------------------------------------------------------------------
/tests/chunk.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | chunk(4);
12 |
13 | var_dump($result);
14 | ?>
15 | --EXPECT--
16 | object(Vtiful\Kernel\Collection)#2 (2) {
17 | [0]=>
18 | array(4) {
19 | [0]=>
20 | int(1)
21 | [1]=>
22 | int(2)
23 | [2]=>
24 | int(3)
25 | [3]=>
26 | int(4)
27 | }
28 | [1]=>
29 | array(1) {
30 | [0]=>
31 | int(5)
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/tests/collapse.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | collapse();
12 |
13 | var_dump($result);
14 | ?>
15 | --EXPECT--
16 | object(Vtiful\Kernel\Collection)#2 (4) {
17 | [0]=>
18 | int(1)
19 | [1]=>
20 | int(2)
21 | [2]=>
22 | int(3)
23 | [3]=>
24 | int(4)
25 | }
26 |
--------------------------------------------------------------------------------
/tests/combine.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | combine(['George', 29]);
9 |
10 | var_dump($result);
11 | ?>
12 | --EXPECT--
13 | object(Vtiful\Kernel\Collection)#2 (2) {
14 | ["name"]=>
15 | string(6) "George"
16 | ["age"]=>
17 | int(29)
18 | }
19 |
--------------------------------------------------------------------------------
/tests/concat.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | concat(['address'])->concat([12])->concat([
9 | 'obj' => new \stdClass()
10 | ]);
11 |
12 | var_dump($result);
13 | ?>
14 | --EXPECT--
15 | object(Vtiful\Kernel\Collection)#4 (5) {
16 | [0]=>
17 | string(4) "name"
18 | [1]=>
19 | string(3) "age"
20 | [2]=>
21 | string(7) "address"
22 | [3]=>
23 | int(12)
24 | [4]=>
25 | object(stdClass)#2 (0) {
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/tests/contains.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | 'Desk', 'price' => 100]);
8 |
9 | $true = $collection->contains('Desk');
10 |
11 | var_dump($true);
12 |
13 | $false = $collection->contains('New York');
14 |
15 | var_dump($false);
16 |
17 | $collection = \Vtiful\Kernel\Collection::init([
18 | ['product' => 'Desk', 'price' => 200, 'VV'],
19 | ['product' => 'Chair', 'price' => 100, 'BB'],
20 | ]);
21 |
22 | $true2 = $collection->contains('product', 'Desk');
23 |
24 | var_dump($true2);
25 |
26 | $false2 = $collection->contains('product', 'Bookcase');
27 |
28 | var_dump($false2);
29 | ?>
30 | --EXPECT--
31 | bool(true)
32 | bool(false)
33 | bool(true)
34 | bool(false)
35 |
--------------------------------------------------------------------------------
/tests/count.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | count();
9 | var_dump($result);
10 | ?>
11 | --EXPECT--
12 | int(5)
13 |
--------------------------------------------------------------------------------
/tests/diff.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | diff([2, 4, 6, 8]);
9 | var_dump($result);
10 | ?>
11 | --EXPECT--
12 | object(Vtiful\Kernel\Collection)#2 (3) {
13 | [0]=>
14 | int(1)
15 | [2]=>
16 | int(3)
17 | [4]=>
18 | int(5)
19 | }
20 |
--------------------------------------------------------------------------------
/tests/diff_assoc.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | 'orange',
9 | 'type' => 'fruit',
10 | 'remain' => 6
11 | ]);
12 |
13 | $diff = $collection->diffAssoc([
14 | 'color' => 'yellow',
15 | 'type' => 'fruit',
16 | 'remain' => 3,
17 | 'used' => 6
18 | ]);
19 |
20 | var_dump($diff);
21 | ?>
22 | --EXPECT--
23 | object(Vtiful\Kernel\Collection)#2 (2) {
24 | ["color"]=>
25 | string(6) "orange"
26 | ["remain"]=>
27 | int(6)
28 | }
29 |
--------------------------------------------------------------------------------
/tests/every.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | every(function ($value, $key) {
10 | return $value > 0;
11 | });
12 |
13 | var_dump($result);
14 | ?>
15 | --EXPECT--
16 | bool(true)
17 |
--------------------------------------------------------------------------------
/tests/except.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | 1,
9 | 'price' => 100,
10 | 'discount' => false
11 | ]);
12 |
13 | $filtered = $collection->except([
14 | 'price',
15 | 'discount'
16 | ]);
17 |
18 | var_dump($filtered);
19 | ?>
20 | --EXPECT--
21 | object(Vtiful\Kernel\Collection)#2 (1) {
22 | ["product_id"]=>
23 | int(1)
24 | }
25 |
--------------------------------------------------------------------------------
/tests/filter.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | filter(function ($value, $key) {
12 | return $value > 2;
13 | });
14 |
15 | $collection2 = \Vtiful\Kernel\Collection::init([
16 | 1, 2, 3, null, false, '', 0, []
17 | ]);
18 |
19 | $noCallback = $collection2->filter();
20 |
21 | var_dump($callbackRes);
22 | var_dump($noCallback);
23 | ?>
24 | --EXPECT--
25 | object(Vtiful\Kernel\Collection)#3 (2) {
26 | [0]=>
27 | int(3)
28 | [1]=>
29 | int(4)
30 | }
31 | object(Vtiful\Kernel\Collection)#4 (3) {
32 | [0]=>
33 | int(1)
34 | [1]=>
35 | int(2)
36 | [2]=>
37 | int(3)
38 | }
39 |
--------------------------------------------------------------------------------
/tests/first.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | first(function ($value, $key) {
12 | return $value > 2;
13 | });
14 |
15 | $noCollback = $collection->first();
16 |
17 | var_dump($collbackRes);
18 | var_dump($noCollback);
19 | ?>
20 | --EXPECT--
21 | int(3)
22 | int(1)
23 |
--------------------------------------------------------------------------------
/tests/first_where.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | 'Regena', 'age' => 12],
9 | ['name' => 'Linda', 'age' => 14],
10 | ['name' => 'Diego', 'age' => 23],
11 | ['name' => 'Linda', 'age' => 84],
12 | ]);
13 |
14 | $result1 = $collection->firstWhere('name', 'Linda');
15 | $result2 = $collection->firstWhere('age', '>=', 18);
16 |
17 | var_dump($result1);
18 | var_dump($result2);
19 | ?>
20 | --EXPECT--
21 | object(Vtiful\Kernel\Collection)#2 (2) {
22 | ["name"]=>
23 | string(5) "Linda"
24 | ["age"]=>
25 | int(14)
26 | }
27 | object(Vtiful\Kernel\Collection)#3 (2) {
28 | ["name"]=>
29 | string(5) "Diego"
30 | ["age"]=>
31 | int(23)
32 | }
33 |
--------------------------------------------------------------------------------
/tests/flat_map.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | 'Sally'],
9 | ['school' => 'Arkansas'],
10 | ['age' => 28]
11 | ]);
12 |
13 | $flattened = $collection->flatMap(function ($values) {
14 | return array_map('strtoupper', $values);
15 | });
16 |
17 | var_dump($flattened);
18 | ?>
19 | --EXPECT--
20 | object(Vtiful\Kernel\Collection)#3 (3) {
21 | [0]=>
22 | array(1) {
23 | ["name"]=>
24 | string(5) "SALLY"
25 | }
26 | [1]=>
27 | array(1) {
28 | ["school"]=>
29 | string(8) "ARKANSAS"
30 | }
31 | [2]=>
32 | array(1) {
33 | ["age"]=>
34 | string(2) "28"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/tests/flatten.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | 'viest',
9 | 'languages' => [
10 | 'php', 'c'
11 | ]
12 | ]);
13 |
14 | $flattened = $collection1->flatten();
15 |
16 | var_dump($flattened);
17 |
18 | $collection2 = \Vtiful\Kernel\Collection::init([
19 | 'Apple' => [
20 | ['name' => 'iPhone 6S', 'brand' => 'Apple'],
21 | ],
22 | 'Samsung' => [
23 | ['name' => 'Galaxy S7', 'brand' => 'Samsung']
24 | ],
25 | ]);
26 |
27 | $products = $collection2->flatten(2);
28 |
29 | var_dump($products);
30 | ?>
31 | --EXPECT--
32 | object(Vtiful\Kernel\Collection)#2 (3) {
33 | [0]=>
34 | string(5) "viest"
35 | [1]=>
36 | string(3) "php"
37 | [2]=>
38 | string(1) "c"
39 | }
40 | object(Vtiful\Kernel\Collection)#4 (4) {
41 | [0]=>
42 | string(9) "iPhone 6S"
43 | [1]=>
44 | string(5) "Apple"
45 | [2]=>
46 | string(9) "Galaxy S7"
47 | [3]=>
48 | string(7) "Samsung"
49 | }
50 |
--------------------------------------------------------------------------------
/tests/flip.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | 'viest',
9 | 'extension' => 'collection'
10 | ]);
11 |
12 | $flipped = $collection->flip();
13 |
14 | var_dump($flipped);
15 | ?>
16 | --EXPECT--
17 | object(Vtiful\Kernel\Collection)#2 (2) {
18 | ["viest"]=>
19 | string(4) "name"
20 | ["collection"]=>
21 | string(9) "extension"
22 | }
23 |
--------------------------------------------------------------------------------
/tests/for_page.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | forPage(2, 3);
12 |
13 | var_dump($chunk);
14 | ?>
15 | --EXPECT--
16 | object(Vtiful\Kernel\Collection)#2 (3) {
17 | [0]=>
18 | int(4)
19 | [1]=>
20 | int(5)
21 | [2]=>
22 | int(6)
23 | }
24 |
--------------------------------------------------------------------------------
/tests/forget.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | 'viest',
9 | 'extension' => 'collection'
10 | ]);
11 |
12 | $result = $collection->forget('name');
13 |
14 | var_dump($result);
15 | ?>
16 | --EXPECT--
17 | object(Vtiful\Kernel\Collection)#1 (1) {
18 | ["extension"]=>
19 | string(10) "collection"
20 | }
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/tests/get.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | 'viest',
9 | 'extension' => 'collection',
10 | ]);
11 |
12 | $name = $collection->get('name');
13 | $null = $collection->get('age');
14 | $age = $collection->get('age', 22);
15 |
16 | var_dump($name, $null, $age);
17 | ?>
18 | --EXPECT--
19 | string(5) "viest"
20 | NULL
21 | int(22)
22 |
--------------------------------------------------------------------------------
/tests/group_by.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | 'account-x10', 'product' => 'Chair'],
9 | ['account_id' => 'account-x10', 'product' => 'Bookcase'],
10 | ['account_id' => 'account-x11', 'product' => 'Desk'],
11 | ]);
12 |
13 | $grouped = $collection->groupBy(function ($item, $key) {
14 | return substr($item['account_id'], -3);
15 | });
16 |
17 | var_dump($grouped->toArray());
18 |
19 | $grouped = $collection->groupBy('account_id');
20 |
21 | var_dump($grouped->toArray());
22 | ?>
23 | --EXPECT--
24 | array(2) {
25 | ["x10"]=>
26 | array(2) {
27 | [0]=>
28 | array(2) {
29 | ["account_id"]=>
30 | string(11) "account-x10"
31 | ["product"]=>
32 | string(5) "Chair"
33 | }
34 | [1]=>
35 | array(2) {
36 | ["account_id"]=>
37 | string(11) "account-x10"
38 | ["product"]=>
39 | string(8) "Bookcase"
40 | }
41 | }
42 | ["x11"]=>
43 | array(1) {
44 | [0]=>
45 | array(2) {
46 | ["account_id"]=>
47 | string(11) "account-x11"
48 | ["product"]=>
49 | string(4) "Desk"
50 | }
51 | }
52 | }
53 | array(2) {
54 | ["account-x10"]=>
55 | array(2) {
56 | [0]=>
57 | array(2) {
58 | ["account_id"]=>
59 | string(11) "account-x10"
60 | ["product"]=>
61 | string(5) "Chair"
62 | }
63 | [1]=>
64 | array(2) {
65 | ["account_id"]=>
66 | string(11) "account-x10"
67 | ["product"]=>
68 | string(8) "Bookcase"
69 | }
70 | }
71 | ["account-x11"]=>
72 | array(1) {
73 | [0]=>
74 | array(2) {
75 | ["account_id"]=>
76 | string(11) "account-x11"
77 | ["product"]=>
78 | string(4) "Desk"
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/tests/has.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | 'viest',
9 | 'age' => 21
10 | ]);
11 |
12 | $true = $collection->has('age');
13 | $false = $collection->has('address');
14 |
15 | var_dump($true, $false);
16 | ?>
17 | --EXPECT--
18 | bool(true)
19 | bool(false)
20 |
--------------------------------------------------------------------------------
/tests/implode.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | implode('-');
12 |
13 | $collection2 = \Vtiful\Kernel\Collection::init([
14 | ['name' => 'viest', 'age' => 21],
15 | ['name' => 'vikin', 'age' => 20],
16 | ['name' => 'wjx', 'age' => 22],
17 | ]);
18 |
19 | $result2 = $collection2->implode('name', '-');
20 |
21 | var_dump($result1, $result2);
22 | ?>
23 | --EXPECT--
24 | string(3) "1-a"
25 | string(15) "viest-vikin-wjx"
26 |
--------------------------------------------------------------------------------
/tests/init.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection initialization
3 | --SKIPIF--
4 |
5 | --FILE--
6 |
11 | --EXPECT--
12 | object(Vtiful\Kernel\Collection)#1 (1) {
13 | [0]=>
14 | int(1)
15 | }
16 |
--------------------------------------------------------------------------------
/tests/intersect.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | intersect([2, 7, 5, 9, 10, 'b']);
10 |
11 | var_dump($intersect->toArray());
12 | ?>
13 | --EXPECT--
14 | array(2) {
15 | [0]=>
16 | int(2)
17 | [1]=>
18 | int(5)
19 | }
20 |
--------------------------------------------------------------------------------
/tests/intersect_by_key.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | 'UX301', 'type' => 'screen', 'year' => 2009
9 | ]);
10 |
11 | $intersect = $collection->intersectByKeys([
12 | 'reference' => 'UX404', 'type' => 'tab', 'year' => 2011
13 | ]);
14 |
15 | var_dump($intersect);
16 | ?>
17 | --EXPECT--
18 | object(Vtiful\Kernel\Collection)#2 (2) {
19 | ["type"]=>
20 | string(6) "screen"
21 | ["year"]=>
22 | int(2009)
23 | }
24 |
--------------------------------------------------------------------------------
/tests/is_empty.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | isEmpty();
10 |
11 | $collection2 = \Vtiful\Kernel\Collection::init([]);
12 |
13 | $false = $collection2->isEmpty();
14 |
15 | var_dump($true, $false);
16 | ?>
17 | --EXPECT--
18 | bool(true)
19 | bool(false)
20 |
--------------------------------------------------------------------------------
/tests/is_not_empty.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | isNotEmpty();
10 |
11 | $collection2 = \Vtiful\Kernel\Collection::init([]);
12 |
13 | $true = $collection2->isNotEmpty();
14 |
15 | var_dump($false, $true);
16 | ?>
17 | --EXPECT--
18 | bool(false)
19 | bool(true)
--------------------------------------------------------------------------------
/tests/key_by.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | 'prod-100', 'name' => 'Desk'],
9 | ['product_id' => 'prod-200', 'name' => 'Chair'],
10 | ]);
11 |
12 | $keyed1 = $collection1->keyBy('product_id');
13 |
14 | $collection2 = \Vtiful\Kernel\Collection::init([
15 | ['product_id' => 'prod-100', 'name' => 'Desk'],
16 | ['product_id' => 'prod-200', 'name' => 'Chair'],
17 | ]);
18 |
19 | $keyed2 = $collection2->keyBy(function ($item) {
20 | return strtoupper($item['product_id']);
21 | });
22 |
23 | var_dump($keyed1, $keyed2);
24 | ?>
25 | --EXPECT--
26 | object(Vtiful\Kernel\Collection)#2 (2) {
27 | ["prod-100"]=>
28 | array(2) {
29 | ["product_id"]=>
30 | string(8) "prod-100"
31 | ["name"]=>
32 | string(4) "Desk"
33 | }
34 | ["prod-200"]=>
35 | array(2) {
36 | ["product_id"]=>
37 | string(8) "prod-200"
38 | ["name"]=>
39 | string(5) "Chair"
40 | }
41 | }
42 | object(Vtiful\Kernel\Collection)#5 (2) {
43 | ["PROD-100"]=>
44 | array(2) {
45 | ["product_id"]=>
46 | string(8) "prod-100"
47 | ["name"]=>
48 | string(4) "Desk"
49 | }
50 | ["PROD-200"]=>
51 | array(2) {
52 | ["product_id"]=>
53 | string(8) "prod-200"
54 | ["name"]=>
55 | string(5) "Chair"
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/tests/keys.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | ['product_id' => 'prod-100', 'name' => 'Desk'],
9 | 'prod-200' => ['product_id' => 'prod-200', 'name' => 'Chair'],
10 | ]);
11 |
12 | $keys = $collection->keys();
13 |
14 | var_dump($keys);
15 | ?>
16 | --EXPECT--
17 | object(Vtiful\Kernel\Collection)#2 (2) {
18 | [0]=>
19 | string(8) "prod-100"
20 | [1]=>
21 | string(8) "prod-200"
22 | }
23 |
--------------------------------------------------------------------------------
/tests/last.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | last(function ($value, $key) {
10 | return $value < 3;
11 | });
12 |
13 | $defaultLast = $collection->last();
14 |
15 | var_dump($callbackLast, $defaultLast);
16 | ?>
17 | --EXPECT--
18 | int(2)
19 | int(4)
20 |
--------------------------------------------------------------------------------
/tests/load.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check for collection presence
3 | --SKIPIF--
4 |
5 | --FILE--
6 |
9 | --EXPECT--
10 | collection extension is available
11 |
--------------------------------------------------------------------------------
/tests/map.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | map(function ($item, $key) {
9 | return $item * 2;
10 | });
11 | var_dump($multiplied);
12 | ?>
13 | --EXPECT--
14 | object(Vtiful\Kernel\Collection)#3 (5) {
15 | [0]=>
16 | int(2)
17 | [1]=>
18 | int(4)
19 | [2]=>
20 | int(6)
21 | [3]=>
22 | int(8)
23 | [4]=>
24 | int(10)
25 | }
26 |
27 |
--------------------------------------------------------------------------------
/tests/map_to_groups.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | 'John Doe',
10 | 'department' => 'Sales',
11 | ],[
12 | 'name' => 'Jane Doe',
13 | 'department' => 'Sales',
14 | ],[
15 | 'name' => 'Johnny Doe',
16 | 'department' => 'Marketing',
17 | ]
18 | ]);
19 |
20 | $grouped = $collection->mapToGroups(function ($item, $key) {
21 | return [$item['department'] => $item['name']];
22 | });
23 |
24 | var_dump($grouped);
25 | ?>
26 | --EXPECT--
27 | object(Vtiful\Kernel\Collection)#3 (2) {
28 | ["Sales"]=>
29 | array(2) {
30 | [0]=>
31 | string(8) "John Doe"
32 | [1]=>
33 | string(8) "Jane Doe"
34 | }
35 | ["Marketing"]=>
36 | array(1) {
37 | [0]=>
38 | string(10) "Johnny Doe"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/tests/max.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | max();
10 |
11 | $collection2 = \Vtiful\Kernel\Collection::init([
12 | ['foo' => 10],
13 | ['foo' => 50],
14 | ['foo' => 20],
15 | ]);
16 |
17 | $defaultKey = $collection2->max('foo');
18 |
19 | var_dump($default, $defaultKey);
20 | ?>
21 | --EXPECT--
22 | int(6)
23 | int(50)
--------------------------------------------------------------------------------
/tests/toarray.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check Collection operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 | toArray();
9 | var_dump($result);
10 | ?>
11 | --EXPECT--
12 | array(5) {
13 | [0]=>
14 | int(1)
15 | [1]=>
16 | int(2)
17 | [2]=>
18 | int(3)
19 | [3]=>
20 | int(4)
21 | [4]=>
22 | int(5)
23 | }
24 |
25 |
26 |
--------------------------------------------------------------------------------
/travis/run-test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | TEST_DIR="`pwd`/tests/"
3 |
4 | make test
5 |
6 | for file in `find $TEST_DIR -name "*.diff" 2>/dev/null`
7 | do
8 | grep "\-\-XFAIL--" ${file/%diff/phpt} >/dev/null 2>&1
9 | if [ $? -gt 0 ]
10 | then
11 | FAILS[${#FAILS[@]}]="$file"
12 | fi
13 | done
14 |
15 | if [ ${#FAILS[@]} -gt 0 ]
16 | then
17 | for fail in "${FAILS[@]}"
18 | do
19 | sh -xc "cat $fail"
20 | done
21 | exit 1
22 | else
23 | exit 0
24 | fi
--------------------------------------------------------------------------------