Skip to content

Commit

Permalink
Introduced iterable type hint instead of array type hint for makeNew
Browse files Browse the repository at this point in the history
  • Loading branch information
aadegbam authored and aadegbam committed Apr 15, 2021
1 parent 4646fb8 commit b9fce3b
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 38 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ $collection = new GenericCollection(
...[$item1, $item2, $item3, $item4, $item5, $item6, $item7, $item8, $item9]
);

// Technique 3: pass the items in an array to the static makeNew helper method
// Technique 3: pass the items in an iterable (such as an array) to the static makeNew helper method
// available in all collection classes
$collection = GenericCollection::makeNew(
[$item1, $item2, $item3, $item4, $item5, $item6, $item7, $item8, $item9]
Expand Down
4 changes: 2 additions & 2 deletions docs/MethodDescriptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -1383,8 +1383,8 @@ A negative integer value will be converted to zero.
------------------------------------------------------------------------------------------------
<div id="CollectionInterface-makeNew"></div>

### static makeNew(array $items=[], bool $preserve_keys=true): \VersatileCollections\CollectionInterface
Creates a new collection from an array.<br>
### static makeNew(iterable $items=[], bool $preserve_keys=true): \VersatileCollections\CollectionInterface
Creates a new collection from an iterable.<br>
THIS IS THE STRONGLY RECOMMENDED WAY TO CREATE COLLECTION OBJECTS (if you forget
to unpack arguments when creating collection objects via the constructor, you
will end up with a collection containing only one item, which is the array
Expand Down
2 changes: 1 addition & 1 deletion docs/MethodsByCategory.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@
* [intersectByKeysAndItems](MethodDescriptions.md#CollectionInterface-intersectByKeysAndItems): Returns a new collection of items from an existing collection whose keys and corresponding items are present in an array of specified items.
* [intersectByKeysAndItemsUsingCallbacks](MethodDescriptions.md#CollectionInterface-intersectByKeysAndItemsUsingCallbacks): Returns a new collection of items from an existing collection whose keys and corresponding items are present in an array of specified items using one specified callback for testing key presence and another specified callback for testing item presence.
* [intersectByKeysUsingCallback](MethodDescriptions.md#CollectionInterface-intersectByKeysUsingCallback): Returns a new collection of items from an existing collection whose keys are present in an array of specified keys using a specified callback for testing key presence.
* [makeNew](MethodDescriptions.md#CollectionInterface-makeNew): Creates a new collection from an array of items. Items must be rightly typed if collection class is strictly typed.
* [makeNew](MethodDescriptions.md#CollectionInterface-makeNew): Creates a new collection from an iterable of items. Items must be rightly typed if collection class is strictly typed.
* [map](MethodDescriptions.md#CollectionInterface-map): Applies a callback to the items in a collection and returns a new collection containing all items in the original collection after applying the callback function to each one. The original collection is not modified.
* [mergeWith](MethodDescriptions.md#CollectionInterface-mergeWith): Adds all specified items to a collection and returns a new collection containing the result. The original collection is not modified. New items with the same keys as existing items will overwrite the existing items.
* [paginate](MethodDescriptions.md#CollectionInterface-paginate): Returns a new collection of at most a specified number of items present in the specified page.
Expand Down
4 changes: 2 additions & 2 deletions docs/SpecificObjectsCollection.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@

> NOTE: **SpecificObjectsCollection** is a final class and was never intended to be extensible. It has a **protected** constructor by design so that its instances cannot be created via the use of the **new** keyword,
instead its instances can only be created by calling either
> * **SpecificObjectsCollection::makeNewForSpecifiedClassName(?string $class_name=null, array $items =[], bool $preserve_keys=true)**
> * or **SpecificObjectsCollection::makeNew(array $items=[], bool $preserve_keys=true)**
> * **SpecificObjectsCollection::makeNewForSpecifiedClassName(?string $class_name=null, iterable $items =[], bool $preserve_keys=true)**
> * or **SpecificObjectsCollection::makeNew(iterable $items=[], bool $preserve_keys=true)**
>
> This is also by design.
Expand Down
4 changes: 2 additions & 2 deletions src/CollectionInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ interface CollectionInterface extends ArrayAccess, Countable, IteratorAggregate
* new \VersatileCollections\NumericsCollection(...[1,2,3])
* vs \VersatileCollections\NumericsCollection::makeNew([1,2,3])
*
* @param array $items an array of items for the new collection to be created.
* @param iterable $items an iterable of items for the new collection to be created.
* @param bool $preserve_keys true if keys in $items will be preserved in the created collection.
*
* @return CollectionInterface newly created collection
Expand All @@ -58,7 +58,7 @@ interface CollectionInterface extends ArrayAccess, Countable, IteratorAggregate
* @noRector \Rector\TypeDeclaration\Rector\ClassMethod\AddArrayReturnDocTypeRector
*
*/
public static function makeNew(array $items=[], bool $preserve_keys=true): CollectionInterface;
public static function makeNew(iterable $items=[], bool $preserve_keys=true): CollectionInterface;

/**
*
Expand Down
10 changes: 6 additions & 4 deletions src/CollectionInterfaceImplementationTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ public function __unset(string $key): void {
* @noinspection PhpIncompatibleReturnTypeInspection
* @psalm-suppress UnsafeInstantiation
*/
public static function makeNew(array $items=[], bool $preserve_keys=true): CollectionInterface {
public static function makeNew(iterable $items=[], bool $preserve_keys=true): CollectionInterface {

if ($preserve_keys === true) {

Expand All @@ -365,9 +365,11 @@ public static function makeNew(array $items=[], bool $preserve_keys=true): Colle
// I use array_values to ensure that all keys
// are numeric. Argument unpacking does not
// work on arrays with one or more string keys.
return new static(...\array_values($items)); // This should be faster than loop above
// since looping triggers offsetSet()
// for each item
return \is_array($items)
? new static(...\array_values($items))
: new static(...\array_values(\iterator_to_array($items))); // These should be faster than loop above
// since looping triggers offsetSet()
// for each item
}

/**
Expand Down
36 changes: 10 additions & 26 deletions src/SpecificObjectsCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ protected function __construct(object ...$objects) {
*
* @param string|null $class_name fully qualified name of the class whose instances or instances of its sub-classes alone would be stored in the collection.
* Set it to null to make the collection work exactly like an instance of ObjectsCollection
* @param array $items an array of objects to be stored in the new collection
* @param iterable $items an iterable of objects to be stored in the new collection
* @param bool $preserve_keys true to use the same keys in $items in the collection, , else false to use sequentially incrementing numeric keys starting from zero
*
*
Expand All @@ -73,45 +73,29 @@ protected function __construct(object ...$objects) {
* @psalm-suppress MoreSpecificReturnType
* @psalm-suppress NoInterfaceProperties
*/
public static function makeNewForSpecifiedClassName(?string $class_name=null, array $items =[], bool $preserve_keys=true): StrictlyTypedCollectionInterface
public static function makeNewForSpecifiedClassName(?string $class_name=null, iterable $items =[], bool $preserve_keys=true): StrictlyTypedCollectionInterface
{

if( $class_name === null ) {

return static::makeNew($items, $preserve_keys); // collection that stores any type of object
}

// Class was specified, create collection for only instances of the
// specified class
// Class was specified, create collection for only instances of the specified class
$new_collection = static::makeNew(); // make an empty collection first
$new_collection->class_name = $class_name;

// if (class_exists($class_name)) {
foreach ($items as $key => $val) {

$new_collection->class_name = $class_name;
if ($preserve_keys) {

foreach ($items as $key => $val) {
$new_collection[$key] = $val;

if ($preserve_keys) {
} else {

$new_collection[$key] = $val;

} else {

$new_collection[] = $val;
}
$new_collection[] = $val;
}

// } else {
//
// $class = static::class;
// $function = __FUNCTION__;
// $msg = "Error in [{$class}::{$function}(...)]: Trying to create a"
// . " new collection that stores only objects of the specified type "
// . "`". $class_name ."` but the specified class not found by `class_exists('$class_name')`.";
//
// throw new Exceptions\SpecifiedClassNotFoundException($msg);
//
// } // if (class_exists($class_name))
}

return $new_collection;
}
Expand Down
35 changes: 35 additions & 0 deletions tests/GenericCollectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,41 @@ public function testThatMakeNewWorksAsExpected() {
$this->assertTrue($collection[0] === 'taylor');
$this->assertTrue($collection[1] === 'abigail');
$this->assertTrue($collection[2] === null);

////////////////////////////////////////////////////////////////////////
// Test with collection from another collection and preserve keys
////////////////////////////////////////////////////////////////////////
$collection = \BaseCollectionTestImplementation::makeNew(['a'=>'taylor', 'b'=>'abigail', null]);
$collectionFromCollection = \BaseCollectionTestImplementation::makeNew($collection);

$this->assertTrue($collectionFromCollection->containsKey('a'));
$this->assertTrue($collectionFromCollection->containsKey('b'));
$this->assertTrue($collectionFromCollection->containsKey(0));
$this->assertTrue($collectionFromCollection->containsItem('taylor'));
$this->assertTrue($collectionFromCollection->containsItem('abigail'));
$this->assertTrue($collectionFromCollection->containsItem(null));
$this->assertTrue($collectionFromCollection['a'] === 'taylor');
$this->assertTrue($collectionFromCollection['b'] === 'abigail');
$this->assertTrue($collectionFromCollection[0] === null);

////////////////////////////////////////////////////////////////////////
// Test with collection from another collection and don't preserve keys
////////////////////////////////////////////////////////////////////////
$collection = \BaseCollectionTestImplementation::makeNew([5=>'taylor', 10=>'abigail', 9=>null], false);
$collectionFromCollection = \BaseCollectionTestImplementation::makeNew($collection);

$this->assertTrue($collectionFromCollection->containsKey(0));
$this->assertTrue($collectionFromCollection->containsKey(1));
$this->assertTrue($collectionFromCollection->containsKey(2));
$this->assertTrue(!$collectionFromCollection->containsKey(10));
$this->assertTrue(!$collectionFromCollection->containsKey(5));
$this->assertTrue(!$collectionFromCollection->containsKey(9));
$this->assertTrue($collectionFromCollection->containsItem('taylor'));
$this->assertTrue($collectionFromCollection->containsItem('abigail'));
$this->assertTrue($collectionFromCollection->containsItem(null));
$this->assertTrue($collectionFromCollection[0] === 'taylor');
$this->assertTrue($collectionFromCollection[1] === 'abigail');
$this->assertTrue($collectionFromCollection[2] === null);
}

public function testThatEmptyConstructorWorksAsExpected() {
Expand Down

0 comments on commit b9fce3b

Please sign in to comment.