diff --git a/collections.c b/collections.c index 97f2266..2033dfd 100644 --- a/collections.c +++ b/collections.c @@ -25,13 +25,16 @@ PHP_MINIT_FUNCTION(collections) { collection_property_name = zend_string_init("_a", strlen("_a"), 1); pair_first_name = zend_string_init("first", strlen("first"), 1); - pair_second_name = zend_string_init("first", strlen("second"), 1); + pair_second_name = zend_string_init("second", strlen("second"), 1); zend_class_entry collection_ce; INIT_CLASS_ENTRY_EX(collection_ce, "Collection", strlen("Collection"), collection_methods); collections_collection_ce = zend_register_internal_class(&collection_ce); + zend_declare_property_null(collections_collection_ce, "_a", strlen("_a"), ZEND_ACC_PRIVATE); zend_class_entry pair_ce; INIT_CLASS_ENTRY_EX(pair_ce, "Pair", strlen("Pair"), pair_methods); collections_pair_ce = zend_register_internal_class(&pair_ce); + zend_declare_property_null(collections_pair_ce, "first", strlen("first"), ZEND_ACC_PUBLIC); + zend_declare_property_null(collections_pair_ce, "second", strlen("second"), ZEND_ACC_PUBLIC); return SUCCESS; } diff --git a/collections_methods.c b/collections_methods.c index 63f2a2e..65c4cfa 100644 --- a/collections_methods.c +++ b/collections_methods.c @@ -29,19 +29,72 @@ #define PHP_COLLECTIONS_ERROR(type, msg) php_error_docref(NULL, type, msg) #define ERR_BAD_ARGUMENT_TYPE() PHP_COLLECTIONS_ERROR(E_WARNING, "Bad argument type") -PHP_METHOD(Collection, __construct) -{ - -} +#define ELEMENTS_VALIDATE(elements) \ + if (IS_COLLECTION(elements)) { \ + zval rv; \ + (elements) = COLLECTION_FETCH(elements); \ + } else if (UNEXPECTED(Z_TYPE_P(elements) != IS_ARRAY)) { \ + ERR_BAD_ARGUMENT_TYPE(); \ + RETVAL_NULL(); \ + } + +#define ARRAY_CLONE(dest, src) \ + zend_array (dest); \ + zend_hash_init(&(dest), zend_hash_num_elements(Z_ARRVAL_P(src)), NULL, ZVAL_PTR_DTOR, 0); \ + zend_hash_copy(&(dest), Z_ARRVAL_P(src), NULL) + +#define RETVAL_NEW_COLLECTION(collection) \ + do { \ + NEW_COLLECTION_OBJ(obj); \ + zval retval; \ + ZVAL_OBJ(&retval, obj); \ + zval property; \ + ZVAL_ARR(&property, collection); \ + COLLECTION_UPDATE(&retval, &property); \ + RETVAL_OBJ(obj); \ + } while (0) + +PHP_METHOD(Collection, __construct) {} PHP_METHOD(Collection, addAll) { - + zval* elements; + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_ZVAL(elements) + ZEND_PARSE_PARAMETERS_END(); + ELEMENTS_VALIDATE(elements); + zval rv; + zval* current = COLLECTION_FETCH_EX(); + ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL_P(elements), zval* val) + zend_hash_next_index_insert(Z_ARRVAL_P(current), val); + ZEND_HASH_FOREACH_END(); + COLLECTION_UPDATE_EX(current); } PHP_METHOD(Collection, all) { - + zend_fcall_info fci; + zend_fcall_info_cache fcc; + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_FUNC(fci, fcc) + ZEND_PARSE_PARAMETERS_END(); + zval params[3], rv, retval; + fci.param_count = 3; + fci.retval = &retval; + fci.params = params; + zval* current = COLLECTION_FETCH_EX(); + ZEND_HASH_FOREACH_BUCKET(Z_ARRVAL_P(current), Bucket* bucket) + ZVAL_COPY(¶ms[0], &bucket->val); + if (bucket->key) + ZVAL_STR(¶ms[1], bucket->key); + else + ZVAL_NULL(¶ms[1]); + ZVAL_LONG(¶ms[2], bucket->h); + zend_call_function(&fci, &fcc); + if (Z_TYPE(retval) == IS_FALSE) + RETURN_FALSE; + ZEND_HASH_FOREACH_END(); + RETURN_TRUE; } PHP_METHOD(Collection, any) @@ -245,13 +298,7 @@ PHP_METHOD(Collection, init) zval retval; ZVAL_OBJ(&retval, obj); if (elements) { - if (IS_COLLECTION(elements)) { - zval rv; - elements = COLLECTION_FETCH(elements); - } else if (UNEXPECTED(Z_TYPE_P(elements) != IS_ARRAY)) { - ERR_BAD_ARGUMENT_TYPE(); - RETVAL_NULL(); - } + ELEMENTS_VALIDATE(elements); COLLECTION_UPDATE(&retval, elements); } else { zval collection; @@ -260,7 +307,7 @@ PHP_METHOD(Collection, init) COLLECTION_UPDATE(&retval, &collection); zval_ptr_dtor(&collection); } - ZVAL_COPY_VALUE(return_value, &retval); + RETVAL_OBJ(obj); } PHP_METHOD(Collection, intersect) diff --git a/stubs/Collection.php b/stubs/Collection.php index 10d1bcf..d0de4b4 100644 --- a/stubs/Collection.php +++ b/stubs/Collection.php @@ -15,14 +15,14 @@ class Collection implements ArrayAccess, Countable * Adds all elements of the given elements collection to this Collection. * * @param array|Collection $elements - * @return bool + * @return void */ function addAll($elements) {} /** * Returns true if all elements match the given predicate. * - * @param callable $predicate ($value, $key) -> bool + * @param callable $predicate ($value, $key, $index) -> bool * @return bool */ function all($predicate) {} @@ -30,7 +30,7 @@ class Collection implements ArrayAccess, Countable /** * Returns true if at least one element matches the given predicate. * - * @param callable $predicate ($value, $key) -> bool + * @param callable $predicate ($value, $key, $index) -> bool * @return bool */ function any($predicate) {} @@ -141,7 +141,7 @@ class Collection implements ArrayAccess, Countable * Returns a collection containing only elements from the given array having distinct keys * returned by the given selector function. * - * @param callable $selector ($value, $key) -> $key + * @param callable $selector ($value, $key, $index) -> $key * @return Collection */ function distinctBy($selector) {} @@ -166,7 +166,7 @@ class Collection implements ArrayAccess, Countable * Returns a collection containing all elements except last elements that satisfy * the given predicate. * - * @param callable $predicate ($value, $key) -> bool + * @param callable $predicate ($value, $key, $index) -> bool * @return Collection */ function dropLastWhile($predicate) {} @@ -175,7 +175,7 @@ class Collection implements ArrayAccess, Countable * Returns a collection containing all elements except first elements that satisfy * the given predicate. * - * @param $predicate $predicate ($value, $key) -> bool + * @param $predicate $predicate ($value, $key, $index) -> bool * @return Collection */ function dropWhile($predicate) {} @@ -193,7 +193,7 @@ class Collection implements ArrayAccess, Countable /** * Returns a collection containing only elements matching the given predicate. * - * @param callable $predicate ($value, $key) -> bool + * @param callable $predicate ($value, $key, $index) -> bool * @return Collection */ function filter($predicate) {} @@ -201,7 +201,7 @@ class Collection implements ArrayAccess, Countable /** * Returns a collection containing only elements not matching the given predicate. * - * @param callable $predicate ($value, $key) -> bool + * @param callable $predicate ($value, $key, $index) -> bool * @return Collection */ function filterNot($predicate) {} @@ -210,7 +210,7 @@ class Collection implements ArrayAccess, Countable * Appends all elements not matching the given predicate to the given destination. * * @param Collection $destination - * @param callable $predicate ($value, $key) -> bool + * @param callable $predicate ($value, $key, $index) -> bool * @return Collection */ function filterNotTo($destination, $predicate) {} @@ -219,7 +219,7 @@ class Collection implements ArrayAccess, Countable * Appends all elements matching the given predicate to the given destination. * * @param Collection $destination - * @param callable $predicate ($value, $key) -> bool + * @param callable $predicate ($value, $key, $index) -> bool * @return Collection */ function filterTo($destination, $predicate) {} @@ -228,7 +228,7 @@ class Collection implements ArrayAccess, Countable * Returns the first element matching the given predicate, or null if no such * element was found. * - * @param callable $predicate ($value, $key) -> bool + * @param callable $predicate ($value, $key, $index) -> bool * @return mixed */ function find($predicate) {} @@ -237,7 +237,7 @@ class Collection implements ArrayAccess, Countable * Returns the last element matching the given predicate, or null if no such * element was found. * - * @param callable $predicate ($value, $key) -> bool + * @param callable $predicate ($value, $key, $index) -> bool * @return mixed */ function findLast($predicate) {} @@ -245,7 +245,7 @@ class Collection implements ArrayAccess, Countable /** * Returns the first element matching the given predicate. * - * @param callable $predicate[optional] ($value, $key) -> bool + * @param callable $predicate[optional] ($value, $key, $index) -> bool * @return mixed */ function first($predicate) {} @@ -254,7 +254,7 @@ class Collection implements ArrayAccess, Countable * Returns a collection of all elements yielded from results of transform function * being invoked on each element of original collection. * - * @param callable $transform ($value, $key) -> array|Collection + * @param callable $transform ($value, $key, $index) -> array|Collection * @return Collection */ function flatMap($transform) {} @@ -264,7 +264,7 @@ class Collection implements ArrayAccess, Countable * original collection, to the given destination. * * @param Collection $destination - * @param callable $transform ($value, $key) -> array|Collection + * @param callable $transform ($value, $key, $index) -> array|Collection * @return Collection */ function flatMapTo($destination, $transform) {} @@ -299,7 +299,7 @@ class Collection implements ArrayAccess, Countable /** * Performs the given action on each element. * - * @param callable $action ($value, $key) -> void + * @param callable $action ($value, $key, $index) -> void * @return void */ function forEach($action) {} @@ -319,7 +319,7 @@ class Collection implements ArrayAccess, Countable * original array by the key returned by the given key_selector function applied to the element * and returns a collection where each group key is associated with a list of corresponding values. * - * @param callable $key_selector ($value, $key) -> $new_key + * @param callable $key_selector ($value, $key, $index) -> $new_key * @param callable $value_transform[optional] ($value) -> $new_value * @return Collection */ @@ -331,7 +331,7 @@ class Collection implements ArrayAccess, Countable * puts to the destination collection each group key associated with a list of corresponding values. * * @param Collection $destination - * @param callable $key_selector ($value, $key) -> $new_key + * @param callable $key_selector ($value, $key, $index) -> $new_key * @param callable $value_transform[optional] ($value) -> $new_value * @return Collection */ @@ -401,7 +401,7 @@ class Collection implements ArrayAccess, Countable /** * Returns the last element matching the given predicate. * - * @param callable $predicate[optional] ($value, $key) -> bool + * @param callable $predicate[optional] ($value, $key, $index) -> bool * @return mixed */ function last($predicate) {} @@ -418,7 +418,7 @@ class Collection implements ArrayAccess, Countable * Returns a collection containing the results of applying the given transform function * to each element in the original collection. * - * @param callable $transform ($value, $key) -> Pair + * @param callable $transform ($value, $key, $index) -> Pair * @return Collection */ function map($transform) {} @@ -427,7 +427,7 @@ class Collection implements ArrayAccess, Countable * Returns a new collection with entries having the keys obtained by applying the transform function * to each keys and values of this collection. * - * @param callable $transform ($value, $key) -> $new_key + * @param callable $transform ($value, $key, $index) -> $new_key * @return Collection */ function mapKeys($transform) {} @@ -437,7 +437,7 @@ class Collection implements ArrayAccess, Countable * transform function to each keys and values of this collections. * * @param Collection $destination - * @param callable $transform ($value, $key) -> $new_key + * @param callable $transform ($value, $key, $index) -> $new_key * @return Collection */ function mapKeysTo($destination, $transform) {} @@ -447,7 +447,7 @@ class Collection implements ArrayAccess, Countable * results to the given destination. * * @param Collection $destination - * @param callable $transform ($value, $key) -> Pair + * @param callable $transform ($value, $key, $index) -> Pair * @return Collection */ function mapTo($destination, $transform) {} @@ -456,7 +456,7 @@ class Collection implements ArrayAccess, Countable * Returns a new collection with entries having the keys of this collection and the values obtained * by applying the transform function to each entry in this collection. * - * @param callable $transform ($value, $key) -> $new_value + * @param callable $transform ($value, $key, $index) -> $new_value * @return Collection */ function mapValues($transform) {} @@ -466,7 +466,7 @@ class Collection implements ArrayAccess, Countable * the values obtained by applying the transform function to each entry in this collection. * * @param Collection $destination - * @param callable $transform ($value, $key) -> $new_value + * @param callable $transform ($value, $key, $index) -> $new_value * @return Collection */ function mapValuesTo($destination, $transform) {} @@ -482,7 +482,7 @@ class Collection implements ArrayAccess, Countable * Returns the first element yielding the largest value of the given function or null if * there are no elements. * - * @param callable $selector ($value, $key) -> $new_value + * @param callable $selector ($value, $key, $index) -> $new_value * @return mixed */ function maxBy($selector) {} @@ -507,7 +507,7 @@ class Collection implements ArrayAccess, Countable * Returns the first element yielding the smallest value of the given function or null if * there are no elements. * - * @param callable $selector ($value, $key) -> $new_value + * @param callable $selector ($value, $key, $index) -> $new_value * @return mixed */ function minBy($selector) {} @@ -576,7 +576,7 @@ class Collection implements ArrayAccess, Countable /** * Returns true if no elements match the given predicate. * - * @param callable $predicate ($value, $key) -> bool + * @param callable $predicate ($value, $key, $index) -> bool * @return bool */ function none($predicate) {} @@ -604,7 +604,7 @@ class Collection implements ArrayAccess, Countable /** * Performs the given action on each element and returns the collection itself afterwards. * - * @param callable $action ($value, $key) -> void + * @param callable $action ($value, $key, $index) -> void * @return Collection */ function onEach($action) {} @@ -621,7 +621,7 @@ class Collection implements ArrayAccess, Countable * elements for which predicate yielded true, while second collection contains elements for * which predicate yielded false. * - * @param callable $predicate ($value, $key) -> bool + * @param callable $predicate ($value, $key, $index) -> bool * @return Pair */ function partition($predicate) {} @@ -697,7 +697,7 @@ class Collection implements ArrayAccess, Countable /** * Removes all elements from this collection that match the given predicate. * - * @param callable $predicate ($value, $key) -> bool + * @param callable $predicate ($value, $key, $index) -> bool * @return bool */ function removeAll($predicate) {} @@ -705,7 +705,7 @@ class Collection implements ArrayAccess, Countable /** * Retains only elements of this collection that match the given predicate. * - * @param callable $predicate ($value, $key) -> bool + * @param callable $predicate ($value, $key, $index) -> bool * @return bool */ function retainAll($predicate) {} @@ -735,7 +735,7 @@ class Collection implements ArrayAccess, Countable * Returns the single element matching the given predicate, or null if there is no or more than * one matching element. * - * @param callable $predicate ($value, $key) -> bool + * @param callable $predicate ($value, $key, $index) -> bool * @return mixed */ function single($predicate) {} @@ -766,7 +766,7 @@ class Collection implements ArrayAccess, Countable * Sorts elements in the collection in-place according to natural sort order of the value returned * by specified selector function. * - * @param callable $selector ($value, $key) -> $new_value + * @param callable $selector ($value, $key, $index) -> $new_value * @return void */ function sortBy($selector) {} @@ -775,7 +775,7 @@ class Collection implements ArrayAccess, Countable * Sorts elements in the collection in-place descending according to natural sort order of the * value returned by specified selector function. * - * @param callable $selector ($value, $key) -> $new_value + * @param callable $selector ($value, $key, $index) -> $new_value * @return void */ function sortByDescending($selector) {} @@ -806,7 +806,7 @@ class Collection implements ArrayAccess, Countable * Returns a collection of all elements sorted according to natural sort order of the * value returned by specified selector function. * - * @param callable $selector ($value, $key) -> $new_value + * @param callable $selector ($value, $key, $index) -> $new_value * @return Collection */ function sortedBy($selector) {} @@ -815,7 +815,7 @@ class Collection implements ArrayAccess, Countable * Returns a collection of all elements sorted descending according to natural sort order * of the value returned by specified selector function. * - * @param callable $selector ($value, $key) -> $new_value + * @param callable $selector ($value, $key, $index) -> $new_value * @return Collection */ function sortedByDescending($selector) {} @@ -823,7 +823,7 @@ class Collection implements ArrayAccess, Countable /** * Returns a collection of all elements sorted descending according to their natural sort order. * - * @param callable $selector ($value, $key) -> $new_value + * @param callable $selector ($value, $key, $index) -> $new_value * @return Collection */ function sortedDescending($selector) {} @@ -855,7 +855,7 @@ class Collection implements ArrayAccess, Countable /** * Returns a collection containing last elements satisfying the given predicate. * - * @param $predicate ($value, $key) -> bool + * @param $predicate ($value, $key, $index) -> bool * @return Collection */ function takeLastWhile($predicate) {} @@ -863,7 +863,7 @@ class Collection implements ArrayAccess, Countable /** * Returns a collection containing first elements satisfying the given predicate. * - * @param $predicate ($value, $key) -> bool + * @param $predicate ($value, $key, $index) -> bool * @return Collection */ function takeWhile($predicate) {} diff --git a/tests/002-add-all.phpt b/tests/002-add-all.phpt new file mode 100644 index 0000000..7936fca --- /dev/null +++ b/tests/002-add-all.phpt @@ -0,0 +1,12 @@ +--TEST-- +Test Collection::addAll(). +--FILE-- +addAll($collection); +if ($array != $collection2->toArray()) + echo 'Collection::addAll() failed.', PHP_EOL; +?> +--EXPECT-- diff --git a/tests/003-all.phpt b/tests/003-all.phpt new file mode 100644 index 0000000..dd6d827 --- /dev/null +++ b/tests/003-all.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Collection::all(). +--FILE-- + 12, + "de" => 5, + "f" => 100 +]); +$result = $collection->all(function ($value) { + return $value < 100; +}); +$result2 = $collection->all(function ($value, $key) { + return strlen($key) < 4; +}); +if ($result || !$result2) + echo 'Collection::all() failed.', PHP_EOL; +?> +--EXPECT--