1: | <?php declare(strict_types=1); |
2: | |
3: | namespace Salient\Collection; |
4: | |
5: | use Salient\Contract\Collection\ListInterface; |
6: | use Salient\Contract\Core\Arrayable; |
7: | use Salient\Utility\Exception\InvalidArgumentTypeException; |
8: | use InvalidArgumentException; |
9: | |
10: | |
11: | |
12: | |
13: | |
14: | |
15: | |
16: | |
17: | |
18: | |
19: | |
20: | |
21: | |
22: | |
23: | |
24: | |
25: | |
26: | |
27: | |
28: | trait ListTrait |
29: | { |
30: | |
31: | use CollectionTrait { |
32: | getItems as private _getItems; |
33: | replaceItems as private _replaceItems; |
34: | } |
35: | |
36: | |
37: | |
38: | |
39: | public function add($value) |
40: | { |
41: | $items = $this->Items; |
42: | $items[] = $value; |
43: | return $this->maybeReplaceItems($items); |
44: | } |
45: | |
46: | |
47: | |
48: | |
49: | public function set($key, $value) |
50: | { |
51: | $this->checkKey($key); |
52: | $items = $this->Items; |
53: | $items[$key] = $value; |
54: | return $this->maybeReplaceItems($items); |
55: | } |
56: | |
57: | |
58: | |
59: | |
60: | public function merge($items) |
61: | { |
62: | $_items = $this->getItems($items); |
63: | if (!$_items) { |
64: | return $this; |
65: | } |
66: | $items = array_merge($this->Items, $_items); |
67: | return $this->maybeReplaceItems($items); |
68: | } |
69: | |
70: | |
71: | |
72: | |
73: | public function push(...$item) |
74: | { |
75: | if (!$item) { |
76: | return $this; |
77: | } |
78: | $clone = $this->maybeClone(); |
79: | array_push($clone->Items, ...$item); |
80: | return $clone; |
81: | } |
82: | |
83: | |
84: | |
85: | |
86: | public function unshift(...$item) |
87: | { |
88: | if (!$item) { |
89: | return $this; |
90: | } |
91: | $clone = $this->maybeClone(); |
92: | array_unshift($clone->Items, ...$item); |
93: | return $clone; |
94: | } |
95: | |
96: | |
97: | |
98: | |
99: | |
100: | public function offsetSet($offset, $value): void |
101: | { |
102: | if ($offset === null) { |
103: | $this->Items[] = $value; |
104: | return; |
105: | } |
106: | $this->checkKey($offset, 'offset'); |
107: | $this->Items[$offset] = $value; |
108: | } |
109: | |
110: | |
111: | |
112: | |
113: | public function offsetUnset($offset): void |
114: | { |
115: | if ( |
116: | !array_key_exists($offset, $this->Items) |
117: | || $offset === array_key_last($this->Items) |
118: | ) { |
119: | unset($this->Items[$offset]); |
120: | return; |
121: | } |
122: | $items = $this->Items; |
123: | unset($items[$offset]); |
124: | $this->Items = array_values($items); |
125: | } |
126: | |
127: | |
128: | |
129: | |
130: | |
131: | protected function getItems($items): array |
132: | { |
133: | return array_values($this->_getItems($items)); |
134: | } |
135: | |
136: | |
137: | |
138: | |
139: | |
140: | protected function replaceItems(array $items, ?bool $getClone = null) |
141: | { |
142: | $key = array_key_last($items); |
143: | if ($key === null || $key === count($items) - 1) { |
144: | return $this->_replaceItems($items, $getClone); |
145: | } |
146: | return $this->_replaceItems(array_values($items), $getClone); |
147: | } |
148: | |
149: | |
150: | |
151: | |
152: | |
153: | |
154: | private function checkKey($key, string $argument = 'key'): void |
155: | { |
156: | if (!is_int($key)) { |
157: | throw new InvalidArgumentTypeException(1, $argument, 'int', $key); |
158: | } |
159: | |
160: | if ( |
161: | !array_key_exists($key, $this->Items) |
162: | && $key !== count($this->Items) |
163: | ) { |
164: | throw new InvalidArgumentException(sprintf( |
165: | 'Item cannot be added with key: %d', |
166: | $key, |
167: | )); |
168: | } |
169: | } |
170: | } |
171: | |