Skip to content

Commit

Permalink
Add new functions (#53)
Browse files Browse the repository at this point in the history
* Add new functions

* fix

* remove codeclimate

* codeclimate

* codeclimate

* modifications

* fix

* add test for object keys

* change length of slice to null

* Add ?

* fix
  • Loading branch information
bronek89 authored Dec 11, 2021
1 parent 858dba6 commit ac0120b
Show file tree
Hide file tree
Showing 18 changed files with 465 additions and 46 deletions.
19 changes: 19 additions & 0 deletions .codeclimate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
engines:
phpcodesniffer:
enabled: true
checks:
Generic WhiteSpace ScopeIndent IncorrectExact:
enabled: false
phpmd:
enabled: true
checks:
UnusedLocalVariable:
enabled: false
CleanCode/StaticAccess:
enabled: false

sonar-php:
enabled: true
checks:
php:S1448:
enabled: false
8 changes: 8 additions & 0 deletions examples/example/ArrayValue-skip.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

use GW\Value\Wrap;

$letters = Wrap::array(['a', 'b', 'c', 'd', 'e', 'f', 'g']);

var_export($letters->skip(2)->toArray());
echo PHP_EOL;
15 changes: 15 additions & 0 deletions examples/example/ArrayValue-take.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

use GW\Value\Wrap;

$letters = Wrap::array(['a', 'b', 'c', 'd', 'e', 'f', 'g']);

var_export($letters->skip(2)->take(4)->toArray());
echo PHP_EOL;

var_export($letters->take(3)->toArray());
echo PHP_EOL;

var_export($letters->take(100)->toArray());
echo PHP_EOL;

12 changes: 12 additions & 0 deletions examples/example/AssocValue-keys.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

use GW\Value\Wrap;

$assoc = Wrap::assocArray(['0' => 'zero', '1' => 'one']);

$keys = $assoc
->map(fn(string $val, int $key): string => $val)
->keys()
->toArray();

var_dump($keys);
29 changes: 29 additions & 0 deletions examples/example/IterableValue-keys.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

use GW\Value\Wrap;

$assoc = Wrap::iterable(['0' => 'zero', '1' => 'one']);

$keys = $assoc
->map(fn(string $val, int $key): string => $val)
->keys()
->toArray();

var_dump($keys);

$pairs = [['0', 'zero'], ['1', 'one'], ['1', 'one one']];

$iterator = function () use ($pairs) {
foreach ($pairs as [$key, $item]) {
yield $key => $item;
}
};

$assoc = Wrap::iterable($iterator());

$keys = $assoc
->map(fn(string $val, string $key): string => $val)
->keys()
->toArray();

var_dump($keys);
18 changes: 18 additions & 0 deletions examples/example/IterableValue-take.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

use GW\Value\Wrap;

$range = function (int $start, int $end): iterable {
for ($i = $start; $i <= $end; $i++) {
yield $i;
}
};

var_export(Wrap::iterable($range(0, PHP_INT_MAX))->skip(2)->take(4)->toArray());
echo PHP_EOL;

var_export(Wrap::iterable($range(0, PHP_INT_MAX))->take(3)->toArray());
echo PHP_EOL;

var_export(Wrap::iterable($range(0, PHP_INT_MAX))->skip(5000)->take(2)->toArray());
echo PHP_EOL;
7 changes: 7 additions & 0 deletions spec/AssocArraySpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -422,4 +422,11 @@ function it_does_not_allow_mutations_trough_ArrayAccess()
$this->shouldThrow(\BadMethodCallException::class)->during('offsetSet', ['a', 'mutated 1']);
$this->shouldThrow(\BadMethodCallException::class)->during('offsetUnset', ['a']);
}

function it_handles_numeric_strings_key_as_int_from_array()
{
$this->beConstructedWith(['0' => 'zero', '1' => 'one']);
$this->map(fn(string $val, int $key): string => $val)
->keys()->toArray()->shouldEqual([0, 1]);
}
}
164 changes: 161 additions & 3 deletions spec/InfiniteIterableValueSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use GW\Value\Wrap;
use PhpSpec\Exception\Example\FailureException;
use PhpSpec\ObjectBehavior;
use function range;

final class InfiniteIterableValueSpec extends ObjectBehavior
{
Expand All @@ -19,13 +20,45 @@ function it_can_be_converted_to_array_value()
$this->toArrayValue()->shouldBeLike(Wrap::array($items));
}

function it_can_be_converted_to_simple_assoc_array()
{
$items = ['item 1', 'item 2', 'item 3'];
$this->beConstructedWith($items);
$this->toAssocArray()->shouldBeLike([0 => 'item 1', 1 => 'item 2', 2 => 'item 3']);
}

function it_can_be_converted_to_keyed_assoc_array()
{
$items = ['foo' => 'item 1', 'bar' => 'item 2'];
$this->beConstructedWith($items);
$this->toAssocArray()->shouldBeLike(['foo' => 'item 1', 'bar' => 'item 2']);
}

function it_can_be_converted_to_keyed_assoc_array_with_map_filter()
{
$items = ['foo' => 'item 1', 'bar' => 'item 2'];
$this->beConstructedWith($items);
$this
->map(fn(string $value, string $key): string => "{$value} mod")
->filter(fn(string $value): bool => true)
->toAssocArray()
->shouldBeLike(['foo' => 'item 1 mod', 'bar' => 'item 2 mod']);
}

function it_returns_items()
{
$items = ['item 1', 'item 2', 'item 3'];
$this->beConstructedWith($items);
$this->toArray()->shouldReturn($items);
}

function it_returns_keys()
{
$items = ['item 1', 'item 2', 'item 3'];
$this->beConstructedWith($items);
$this->keys()->toArray()->shouldReturn([0, 1, 2]);
}

function it_maps_string_items_with_closure()
{
$this->beConstructedWith(['item 1', 'item 2', 'item 3']);
Expand All @@ -41,8 +74,7 @@ function it_maps_string_items_with_closure()
function it_maps_items_with_php_callable()
{
$this->beConstructedWith(['100', '50.12', '', true, false]);

$mapped = $this->map('intval');
$mapped = $this->map(fn($value): int => (int)$value);

$mapped->shouldNotBe($this);
$mapped->toArray()->shouldBeLike([100, 50, 0, 1, 0]);
Expand Down Expand Up @@ -184,12 +216,41 @@ function it_slices_given_part()
{
$this->beConstructedWith(['item 1', 'item 2', 'item 3', 'item 4', 'item 5', 'item 6']);

$this->slice(0, 1)->shouldNotBe($this);
$this->slice(0, 1)->toArray()->shouldNotBe($this->toArray());
$this->slice(0, 1)->toArray()->shouldBeLike(['item 1']);
$this->slice(1, 4)->toArray()->shouldBeLike(['item 2', 'item 3', 'item 4', 'item 5']);
$this->slice(5, 1)->toArray()->shouldBeLike(['item 6']);
}

function it_returns_empty_set_for_slice_with_zero_length()
{
$this->beConstructedWith(['item 1', 'item 2', 'item 3', 'item 4', 'item 5', 'item 6']);

$this->slice(0, 0)->toArray()->shouldBeLike([]);
$this->slice(1, 0)->toArray()->shouldBeLike([]);
$this->slice(4, 0)->toArray()->shouldBeLike([]);
$this->slice(55, 0)->toArray()->shouldBeLike([]);
}

function it_throws_when_used_on_negative_offset_or_length_in_slice()
{
$this->beConstructedWith(['item 1', 'item 2', 'item 3', 'item 4', 'item 5', 'item 6']);

$this->shouldThrow()->during('slice', [-1, 10]);
$this->shouldThrow()->during('slice', [-1, -110]);
$this->shouldThrow()->during('slice', [1, -110]);
}

function it_skips_and_takes_given_part()
{
$this->beConstructedWith(['item 1', 'item 2', 'item 3', 'item 4', 'item 5', 'item 6']);

$this->take(1)->toArray()->shouldNotBe($this->toArray());
$this->take(1)->toArray()->shouldBeLike(['item 1']);
$this->skip(1)->take(4)->toArray()->shouldBeLike(['item 2', 'item 3', 'item 4', 'item 5']);
$this->skip(5)->take(1)->toArray()->shouldBeLike(['item 6']);
}

function it_slice_and_do_not_take_elements_above_end_index()
{
$takenElements = 0;
Expand Down Expand Up @@ -518,6 +579,103 @@ function it_finds_null_when_no_item_matches_condition()
->shouldReturn(null);
}

function it_handles_repeated_keys_properly_with_toArray()
{
$iterator = function () {
foreach (range(0, 5) as $item) {
yield 0 => $item;
}
};

$this->beConstructedWith($iterator());
$this->toArray()->shouldEqual([0, 1, 2, 3, 4, 5]);
}

function it_handles_repeated_keys_properly_with_toAssocArray()
{
$iterator = function () {
foreach (range(0, 5) as $item) {
yield 0 => $item;
}
};

$this->beConstructedWith($iterator());
$this->toAssocArray()->shouldEqual([0 => 5]);
}

function it_handles_repeated_keys_properly_with_keys()
{
$iterator = function () {
foreach (range(0, 5) as $item) {
yield 0 => $item;
}
};

$this->beConstructedWith($iterator());
$this->keys()->toArray()->shouldEqual([0, 0, 0, 0, 0, 0]);
}

function it_handles_repeated_keys_properly_with_map()
{
$iterator = function () {
foreach (range(0, 5) as $item) {
yield 0 => $item;
}
};

$this->beConstructedWith($iterator());
$this->map(fn(int $value, int $key): int => $key)->toArray()->shouldEqual([0, 0, 0, 0, 0, 0]);
}

function it_handles_repeated_keys_properly_with_slice()
{
$iterator = function () {
foreach (range(0, 5) as $item) {
yield 0 => $item;
}
};

$this->beConstructedWith($iterator());
$this->slice(1, 2)->toArray()->shouldEqual([1, 2]);
}

function it_handles_numeric_strings_key_as_int_from_array()
{
$this->beConstructedWith(['0' => 'zero', '1' => 'one']);
$this->map(fn(string $val, int $key): string => $val)
->keys()->toArray()->shouldEqual([0, 1]);
}

function it_handles_numeric_strings_key_as_string_from_iterator()
{
$pairs = [['0', 'zero'], ['1', 'one'], ['1', 'one one']];

$iterator = function () use ($pairs) {
foreach ($pairs as [$key, $item]) {
yield $key => $item;
}
};

$this->beConstructedWith($iterator());
$this->map(fn(string $val, string $key): string => $val)
->keys()->toArray()->shouldEqual(['0', '1', '1']);
}

function it_handles_object_keys()
{
$pairs = [[(object)['foo' => 'bar'], 'zero'], [(object)['foo' => 'baz'], 'one one']];

$iterator = function () use ($pairs) {
foreach ($pairs as [$key, $item]) {
yield $key => $item;
}
};

$this->beConstructedWith($iterator());
$this->map(fn(string $val, object $key): string => $val)
->keys()->toArray()->shouldBeLike([(object)['foo' => 'bar'], (object)['foo' => 'baz']]);
}

private function entityComparator(): \Closure
{
return function (DummyEntity $entityA, DummyEntity $entityB): int {
Expand Down
14 changes: 12 additions & 2 deletions spec/PlainArraySpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ function it_maps_items_with_php_callable()
{
$this->beConstructedWith(['100', '50.12', '', true, false]);

$mapped = $this->map('intval');
$mapped = $this->map(fn($value): int => (int)$value);

$mapped->shouldNotBe($this);
$mapped->toArray()->shouldBeLike([100, 50, 0, 1, 0]);
Expand Down Expand Up @@ -341,12 +341,22 @@ function it_slices_given_part()
{
$this->beConstructedWith(['item 1', 'item 2', 'item 3', 'item 4', 'item 5', 'item 6']);

$this->slice(0, 1)->shouldNotBe($this);
$this->slice(0, 1)->toArray()->shouldNotBe($this->toArray());
$this->slice(0, 1)->toArray()->shouldBeLike(['item 1']);
$this->slice(1, 4)->toArray()->shouldBeLike(['item 2', 'item 3', 'item 4', 'item 5']);
$this->slice(5, 1)->toArray()->shouldBeLike(['item 6']);
}

function it_skips_and_takes_given_part()
{
$this->beConstructedWith(['item 1', 'item 2', 'item 3', 'item 4', 'item 5', 'item 6']);

$this->take(1)->toArray()->shouldNotBe($this->toArray());
$this->take(1)->toArray()->shouldBeLike(['item 1']);
$this->skip(1)->take(4)->toArray()->shouldBeLike(['item 2', 'item 3', 'item 4', 'item 5']);
$this->skip(5)->take(1)->toArray()->shouldBeLike(['item 6']);
}

function it_allows_to_remove_slice_from_array_with_splice()
{
$this->beConstructedWith(['item 1', 'item 2', 'item 3', 'item 4', 'item 5', 'item 6']);
Expand Down
13 changes: 12 additions & 1 deletion spec/PlainStringsArraySpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,25 @@ function it_can_be_sliced()
$strings = ['string 1', 'string 2', 'string 3', 'string 4'];
$this->beConstructedWithStrings(...$strings);

$this->slice(0, 1)->shouldNotBe($this);
$this->slice(0, 1)->toNativeStrings()->shouldNotBe($this->toNativeStrings());
$this->slice(0, 1)->toNativeStrings()->shouldBeLike(['string 1']);
$this->slice(3, 1)->toNativeStrings()->shouldBeLike(['string 4']);
$this->slice(1, 2)->toNativeStrings()->shouldBeLike(['string 2', 'string 3']);
$this->slice(0, 4)->toNativeStrings()->shouldBeLike($strings);
$this->slice(0, 500)->toNativeStrings()->shouldBeLike($strings);
}

function it_skips_and_takes_given_part()
{
$strings = ['item 1', 'item 2', 'item 3', 'item 4', 'item 5', 'item 6'];
$this->beConstructedWithStrings(...$strings);

$this->take(1)->toNativeStrings()->shouldNotBe($this->toNativeStrings());
$this->take(1)->toNativeStrings()->shouldBeLike(['item 1']);
$this->skip(1)->take(4)->toNativeStrings()->shouldBeLike(['item 2', 'item 3', 'item 4', 'item 5']);
$this->skip(5)->take(1)->toNativeStrings()->shouldBeLike(['item 6']);
}

function it_can_be_spliced()
{
$this->beConstructedWithStrings('string 1', 'string 2', 'string 3', 'string 4');
Expand Down
Loading

0 comments on commit ac0120b

Please sign in to comment.