Skip to content

Commit e2486c4

Browse files
committed
[WIP] Added Nette\Utils\Collection
1 parent c181214 commit e2486c4

File tree

2 files changed

+214
-0
lines changed

2 files changed

+214
-0
lines changed

src/Utils/Collection.php

+204
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
<?php
2+
3+
/**
4+
* This file is part of the Nette Framework (https://nette.org)
5+
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
namespace Nette\Utils;
11+
12+
use Nette;
13+
14+
15+
/**
16+
* Collection of items (probably of same type).
17+
*/
18+
abstract class Collection
19+
{
20+
21+
/** @var array */
22+
private $items = [];
23+
24+
/** @var bool */
25+
private $keysMatter = FALSE;
26+
27+
28+
/**
29+
* @return static
30+
* @throws Nette\NotSupportedException
31+
*/
32+
public static function fromIterator(\Traversable $iterator, array $constructorArgs = [])
33+
{
34+
$me = new static(...array_values($constructorArgs));
35+
if (!method_exists($me, 'add')) {
36+
throw new Nette\NotSupportedException(__METHOD__ . '() requires ' . get_class($me) . '::add() to be implemented.');
37+
}
38+
39+
foreach ($iterator as $item) {
40+
$me->add($item);
41+
}
42+
43+
return $me;
44+
}
45+
46+
47+
/**
48+
* @return static
49+
* @throws Nette\NotSupportedException
50+
*/
51+
public static function fromArray(array $items, array $constructorArgs = [])
52+
{
53+
return static::fromIterator(new \ArrayIterator($items), $constructorArgs);
54+
}
55+
56+
57+
/**
58+
* @return int
59+
*/
60+
public function count()
61+
{
62+
return count($this->items);
63+
}
64+
65+
66+
/**
67+
* @param mixed
68+
* @return bool
69+
*/
70+
public function has($key)
71+
{
72+
return array_key_exists($this->normalizeKey($key), $this->items);
73+
}
74+
75+
76+
/**
77+
* @return array
78+
*/
79+
public function getKeys()
80+
{
81+
return array_keys($this->items);
82+
}
83+
84+
85+
/**
86+
* @return \ArrayIterator
87+
*/
88+
public function getIterator()
89+
{
90+
return new \ArrayIterator($this->items);
91+
}
92+
93+
94+
/**
95+
* @param callable
96+
* @return static
97+
*/
98+
public function filter(callable $cb)
99+
{
100+
$me = clone $this;
101+
$me->items = array_filter($this->items, $cb, ARRAY_FILTER_USE_BOTH);
102+
return $me;
103+
}
104+
105+
106+
/**
107+
* @param callable
108+
* @return static
109+
*/
110+
public function walk(callable $cb)
111+
{
112+
array_walk($this->items, $cb);
113+
return $this;
114+
}
115+
116+
117+
/**
118+
* @param callable
119+
* @return array
120+
*/
121+
public function convert(callable $cb)
122+
{
123+
$result = [];
124+
foreach ($this->items as $key => $item) {
125+
$unset = FALSE;
126+
$item = $cb($item, $key, $unset);
127+
if (!$unset) {
128+
if ($key === NULL) {
129+
$result[] = $item;
130+
} else {
131+
$result[$key] = $item;
132+
}
133+
}
134+
}
135+
136+
return $result;
137+
}
138+
139+
140+
/**
141+
* @param callable $cb
142+
* @return static
143+
*/
144+
public function sortBy(callable $cb)
145+
{
146+
if ($this->keysMatter) {
147+
uasort($this->items, $cb);
148+
} else {
149+
usort($this->items, $cb);
150+
}
151+
152+
return $this;
153+
}
154+
155+
156+
/**
157+
* @param mixed $key
158+
* @return int|string
159+
*/
160+
protected function normalizeKey($key)
161+
{
162+
return $key;
163+
}
164+
165+
166+
/**
167+
* @param mixed
168+
* @param mixed
169+
* @throws Nette\ArgumentOutOfRangeException
170+
* @return void
171+
*/
172+
protected function addItem($item, $key)
173+
{
174+
$key = $this->normalizeKey($key);
175+
176+
if ($key === NULL) {
177+
$this->items[] = $item;
178+
} else {
179+
if (array_key_exists($key, $this->items)) {
180+
throw new Nette\ArgumentOutOfRangeException("Item with key '$key' already exists in " . get_class($this) . " collection.");
181+
}
182+
$this->items[$key] = $item;
183+
$this->keysMatter = TRUE;
184+
}
185+
}
186+
187+
188+
/**
189+
* @param mixed
190+
* @return mixed
191+
* @throws ItemNotFoundException
192+
*/
193+
protected function getItem($key)
194+
{
195+
$key = $this->normalizeKey($key);
196+
197+
if (!array_key_exists($key, $this->items)) {
198+
throw new ItemNotFoundException("Item with key '$key' was not found in collection.");
199+
}
200+
201+
return $this->items[$key];
202+
}
203+
204+
}

src/Utils/exceptions.php

+10
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ class StaticClassException extends \LogicException
119119

120120
namespace Nette\Utils;
121121

122+
use Nette;
123+
122124

123125
/**
124126
* The exception that is thrown when an image error occurs.
@@ -158,3 +160,11 @@ class RegexpException extends \Exception
158160
class AssertionException extends \Exception
159161
{
160162
}
163+
164+
165+
/**
166+
* The exception indicates that item is not present in collection.
167+
*/
168+
class ItemNotFoundException extends Nette\ArgumentOutOfRangeException
169+
{
170+
}

0 commit comments

Comments
 (0)