Skip to content

Commit 7cf69f1

Browse files
committed
feat: apply specific namespace
1 parent 77ad64b commit 7cf69f1

9 files changed

+181
-381
lines changed

src/IterableObject.php

Lines changed: 23 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22

33
namespace BenTools\IterableFunctions;
44

5-
use Closure;
65
use EmptyIterator;
7-
use InvalidArgumentException;
86
use IteratorAggregate;
97
use Traversable;
108

9+
/**
10+
* @internal
11+
*/
1112
final class IterableObject implements IteratorAggregate
1213
{
1314
/**
@@ -18,93 +19,50 @@ final class IterableObject implements IteratorAggregate
1819
/**
1920
* @var callable
2021
*/
21-
private $filter;
22+
private $filterFn;
2223

2324
/**
2425
* @var callable
2526
*/
26-
private $map;
27+
private $mapFn;
2728

28-
/**
29-
* IterableObject constructor.
30-
* @param iterable|array|Traversable $iterable
31-
* @param callable|null $filter
32-
* @param callable|null $map
33-
* @throws InvalidArgumentException
34-
*/
35-
public function __construct($iterable, $filter = null, $map = null)
29+
public function __construct(?iterable $iterable = null, ?callable $filter = null, ?callable $map = null)
3630
{
37-
if (null === $iterable) {
38-
$iterable = new EmptyIterator();
39-
}
40-
if (!is_iterable($iterable)) {
41-
throw new InvalidArgumentException(
42-
sprintf('Expected array or Traversable, got %s', is_object($iterable) ? get_class($iterable) : gettype($iterable))
43-
);
44-
}
45-
46-
// Cannot rely on callable type-hint on PHP 5.3
47-
if (null !== $filter && !is_callable($filter) && !$filter instanceof Closure) {
48-
throw new InvalidArgumentException(
49-
sprintf('Expected callable, got %s', is_object($filter) ? get_class($filter) : gettype($filter))
50-
);
51-
}
52-
53-
if (null !== $map && !is_callable($map) && !$map instanceof Closure) {
54-
throw new InvalidArgumentException(
55-
sprintf('Expected callable, got %s', is_object($map) ? get_class($map) : gettype($map))
56-
);
57-
}
58-
59-
$this->iterable = $iterable;
60-
$this->filter = $filter;
61-
$this->map = $map;
31+
$this->iterable = $iterable ?? new EmptyIterator();
32+
$this->filterFn = $filter;
33+
$this->mapFn = $map;
6234
}
6335

64-
/**
65-
* @param callable $filter
66-
* @return self
67-
*/
68-
public function filter($filter)
36+
public function filter(callable $filter): self
6937
{
70-
return new self($this->iterable, $filter, $this->map);
38+
return new self($this->iterable, $filter, $this->mapFn);
7139
}
7240

73-
/**
74-
* @param callable $map
75-
* @return self
76-
*/
77-
public function map($map)
41+
public function map(callable $map): self
7842
{
79-
return new self($this->iterable, $this->filter, $map);
43+
return new self($this->iterable, $this->filterFn, $map);
8044
}
8145

82-
/**
83-
* @inheritdoc
84-
*/
85-
public function getIterator()
46+
public function getIterator(): Traversable
8647
{
8748
$iterable = $this->iterable;
88-
if (null !== $this->filter) {
89-
$iterable = iterable_filter($iterable, $this->filter);
49+
if (null !== $this->filterFn) {
50+
$iterable = iterable_filter($iterable, $this->filterFn);
9051
}
91-
if (null !== $this->map) {
92-
$iterable = iterable_map($iterable, $this->map);
52+
if (null !== $this->mapFn) {
53+
$iterable = iterable_map($iterable, $this->mapFn);
9354
}
9455
return iterable_to_traversable($iterable);
9556
}
9657

97-
/**
98-
* @return array
99-
*/
100-
public function asArray()
58+
public function asArray(): array
10159
{
10260
$iterable = $this->iterable;
103-
if (null !== $this->filter) {
104-
$iterable = iterable_filter($iterable, $this->filter);
61+
if (null !== $this->filterFn) {
62+
$iterable = iterable_filter($iterable, $this->filterFn);
10563
}
106-
if (null !== $this->map) {
107-
$iterable = iterable_map($iterable, $this->map);
64+
if (null !== $this->mapFn) {
65+
$iterable = iterable_map($iterable, $this->mapFn);
10866
}
10967
return iterable_to_array($iterable);
11068
}

src/iterable-functions.php

Lines changed: 83 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -1,174 +1,108 @@
11
<?php
22

3-
use BenTools\IterableFunctions\IterableObject;
4-
5-
if (!function_exists('iterable_map')) {
6-
7-
/**
8-
* Maps a callable to an iterable.
9-
*
10-
* @param iterable|array|\Traversable $iterable
11-
* @param callable $map
12-
* @return array|ArrayIterator
13-
* @throws InvalidArgumentException
14-
*/
15-
function iterable_map($iterable, $map)
16-
{
17-
if (!is_iterable($iterable)) {
18-
throw new \InvalidArgumentException(
19-
sprintf('Expected array or Traversable, got %s', is_object($iterable) ? get_class($iterable) : gettype($iterable))
20-
);
21-
}
22-
23-
// Cannot rely on callable type-hint on PHP 5.3
24-
if (null !== $map && !is_callable($map) && !$map instanceof Closure) {
25-
throw new InvalidArgumentException(
26-
sprintf('Expected callable, got %s', is_object($map) ? get_class($map) : gettype($map))
27-
);
28-
}
29-
30-
if ($iterable instanceof Traversable) {
31-
return new ArrayIterator(array_map($map, iterator_to_array($iterable)));
32-
}
33-
34-
return array_map($map, $iterable);
3+
namespace BenTools\IterableFunctions;
4+
5+
6+
use ArrayIterator;
7+
use CallbackFilterIterator;
8+
use IteratorIterator;
9+
use Traversable;
10+
11+
/**
12+
* Maps a callable to an iterable.
13+
*
14+
* @param array|Traversable $iterable
15+
* @return array|ArrayIterator
16+
*/
17+
function iterable_map(iterable $iterable, callable $map): iterable
18+
{
19+
if ($iterable instanceof Traversable) {
20+
return new ArrayIterator(array_map($map, iterator_to_array($iterable)));
3521
}
3622

23+
return array_map($map, $iterable);
3724
}
3825

3926

40-
if (!function_exists('is_iterable')) {
41-
42-
/**
43-
* Check wether or not a variable is iterable (i.e array or \Traversable)
44-
*
45-
* @param mixed $iterable
46-
* @return bool
47-
*/
48-
function is_iterable($iterable)
49-
{
50-
return is_array($iterable) || $iterable instanceof \Traversable;
27+
/**
28+
* Copy the iterable into an array. If the iterable is already an array, return it.
29+
*
30+
* @param array|Traversable $iterable
31+
* @param bool $use_keys [optional] Whether to use the iterator element keys as index.
32+
* @return array
33+
*/
34+
function iterable_to_array(iterable $iterable, bool $use_keys = true): array
35+
{
36+
if ($iterable instanceof Traversable) {
37+
return iterator_to_array($iterable, $use_keys);
5138
}
39+
40+
return $use_keys ? $iterable : array_values($iterable);
5241
}
5342

54-
if (!function_exists('iterable_to_array')) {
55-
56-
/**
57-
* Copy the iterable into an array. If the iterable is already an array, return it.
58-
*
59-
* @param iterable|array|\Traversable $iterable
60-
* @param bool $use_keys [optional] Whether to use the iterator element keys as index.
61-
* @return array
62-
*/
63-
function iterable_to_array($iterable, $use_keys = true)
64-
{
65-
return is_array($iterable) ? ($use_keys ? $iterable : array_values($iterable)) : iterator_to_array($iterable, $use_keys);
43+
/**
44+
* If the iterable is not intance of Traversable, it is an array => convert it to an ArrayIterator.
45+
*
46+
* @param array|Traversable $iterable
47+
*/
48+
function iterable_to_traversable(iterable $iterable): Traversable
49+
{
50+
if ($iterable instanceof Traversable) {
51+
return $iterable;
6652
}
53+
54+
return new ArrayIterator($iterable);
6755
}
6856

69-
if (!function_exists('iterable_to_traversable')) {
70-
71-
/**
72-
* If the iterable is not intance of \Traversable, it is an array => convert it to an ArrayIterator.
73-
*
74-
* @param iterable|array|\Traversable $iterable
75-
* @return \Traversable
76-
*/
77-
function iterable_to_traversable($iterable)
78-
{
79-
if ($iterable instanceof Traversable) {
80-
return $iterable;
81-
} elseif (is_array($iterable)) {
82-
return new ArrayIterator($iterable);
83-
} else {
84-
throw new \InvalidArgumentException(
85-
sprintf(
86-
'Expected array or \\Traversable, got %s',
87-
is_object($iterable) ? get_class($iterable) : gettype($iterable)
88-
)
89-
);
90-
}
57+
58+
/**
59+
* Filters an iterable.
60+
*
61+
* @param array|Traversable $iterable
62+
* @return array|CallbackFilterIterator
63+
*/
64+
function iterable_filter(iterable $iterable, ?callable $filter = null)
65+
{
66+
if (null === $filter) {
67+
$filter = static function ($value) {
68+
return (bool) $value;
69+
};
9170
}
92-
}
9371

94-
if (!function_exists('iterable_filter')) {
95-
96-
/**
97-
* Filters an iterable.
98-
*
99-
* @param iterable|array|\Traversable $iterable
100-
* @param callable $filter
101-
* @return array|CallbackFilterIterator
102-
* @throws InvalidArgumentException
103-
*/
104-
function iterable_filter($iterable, $filter = null)
105-
{
106-
if (!is_iterable($iterable)) {
107-
throw new \InvalidArgumentException(
108-
sprintf('Expected array or Traversable, got %s', is_object($iterable) ? get_class($iterable) : gettype($iterable))
109-
);
110-
}
111-
112-
// Cannot rely on callable type-hint on PHP 5.3
113-
if (null !== $filter && !is_callable($filter) && !$filter instanceof Closure) {
114-
throw new InvalidArgumentException(
115-
sprintf('Expected callable, got %s', is_object($filter) ? get_class($filter) : gettype($filter))
116-
);
117-
}
118-
119-
if (null === $filter) {
120-
$filter = function ($value) {
121-
return (bool) $value;
122-
};
123-
}
124-
125-
if ($iterable instanceof Traversable) {
126-
if (!class_exists('CallbackFilterIterator')) {
127-
throw new \RuntimeException('Class CallbackFilterIterator not found. Try using a polyfill, like symfony/polyfill-php54');
128-
}
129-
return new CallbackFilterIterator(new IteratorIterator($iterable), $filter);
130-
}
131-
132-
return array_filter($iterable, $filter);
72+
if ($iterable instanceof Traversable) {
73+
return new CallbackFilterIterator(new IteratorIterator($iterable), $filter);
13374
}
13475

76+
return array_filter($iterable, $filter);
13577
}
13678

137-
if (!function_exists('iterable_reduce')) {
138-
/**
139-
* Reduces an iterable.
140-
*
141-
* @param iterable<mixed> $iterable
142-
* @param callable(mixed, mixed) $reduce
143-
* @return mixed
144-
*
145-
* @psalm-template TValue
146-
* @psalm-template TResult
147-
*
148-
* @psalm-param iterable<TValue> $iterable
149-
* @psalm-param callable(TResult|null, TValue) $reduce
150-
* @psalm-param TResult|null $initial
151-
*
152-
* @psalm-return TResult|null
153-
*/
154-
function iterable_reduce($iterable, $reduce, $initial = null)
155-
{
156-
foreach ($iterable as $item) {
157-
$initial = $reduce($initial, $item);
158-
}
159-
160-
return $initial;
161-
}
162-
}
16379

16480
/**
165-
* @param iterable|array|\Traversable $iterable
166-
* @param callable|null $filter
167-
* @param callable|null $map
168-
* @return Traversable|IterableObject
169-
* @throws InvalidArgumentException
81+
* Reduces an iterable.
82+
*
83+
* @param iterable<mixed> $iterable
84+
* @param callable(mixed, mixed) $reduce
85+
* @return mixed
86+
*
87+
* @psalm-template TValue
88+
* @psalm-template TResult
89+
*
90+
* @psalm-param iterable<TValue> $iterable
91+
* @psalm-param callable(TResult|null, TValue) $reduce
92+
* @psalm-param TResult|null $initial
93+
*
94+
* @psalm-return TResult|null
17095
*/
171-
function iterable($iterable, $filter = null, $map = null)
96+
function iterable_reduce(iterable $iterable, callable $reduce, $initial = null)
97+
{
98+
foreach ($iterable as $item) {
99+
$initial = $reduce($initial, $item);
100+
}
101+
102+
return $initial;
103+
}
104+
105+
function iterable(iterable $iterable, ?callable $filter = null, ?callable $map = null): IterableObject
172106
{
173107
return new IterableObject($iterable, $filter, $map);
174108
}

0 commit comments

Comments
 (0)