Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
9.09% covered (danger)
9.09%
3 / 33
8.33% covered (danger)
8.33%
1 / 12
CRAP
0.00% covered (danger)
0.00%
0 / 1
OneToMany
9.09% covered (danger)
9.09%
3 / 33
8.33% covered (danger)
8.33%
1 / 12
161.26
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 prepare
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
6
 offsetExists
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 offsetGet
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 offsetSet
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 offsetUnset
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 current
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 next
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 key
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 valid
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 rewind
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 count
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace Miniframe\ORM\Collection;
4
5use Miniframe\Core\Registry;
6use Miniframe\ORM\Middleware\ORM;
7
8class OneToMany implements \ArrayAccess, \Iterator, \Countable
9{
10    /**
11     * The actual collection
12     *
13     * @var array|null
14     */
15    protected $collection = null;
16    /**
17     * Position within the array
18     *
19     * @var int|string|null
20     */
21    protected $position = null;
22
23    /**
24     * Name of the type of entities in this collection
25     *
26     * @var string
27     */
28    protected $entityClassName;
29    /**
30     * Name of the column that should match $columnValue
31     *
32     * @var string
33     */
34    protected $columnName;
35    /**
36     * The value that should be in $columnName
37     *
38     * @var mixed
39     */
40    protected $columnValue;
41
42    /**
43     * Collection object for a OneToMany join
44     *
45     * @param string $entityClassName Name of the type of entities in this collection.
46     * @param string $columnName      Name of the column that should match $columnValue.
47     * @param mixed  $columnValue     The value that should be in $columnName.
48     */
49    public function __construct(string $entityClassName, string $columnName, $columnValue)
50    {
51        $this->entityClassName = $entityClassName;
52        $this->columnName = $columnName;
53        $this->columnValue = $columnValue;
54    }
55
56    /**
57     * Prepares the data collection when it's accessed for the first time
58     *
59     * @return void
60     */
61    protected function prepare(): void
62    {
63        if ($this->collection !== null) {
64            return;
65        }
66        $this->collection = Registry::get(ORM::class)
67            ->getRepository($this->entityClassName)
68            ->findBy([$this->columnName => $this->columnValue]);
69
70        $this->rewind();
71    }
72
73    /**
74     * ArrayAccess::offsetExists — Whether an offset exists
75     *
76     * @param mixed $offset An offset to check for.
77     *
78     * @return boolean
79     */
80    public function offsetExists($offset): bool
81    {
82        $this->prepare();
83        return isset($this->collection[$offset]); // @TODO maybe use array_key_exists ?
84    }
85
86    /**
87     * ArrayAccess::offsetGet — Offset to retrieve
88     *
89     * @param mixed $offset The offset to retrieve.
90     *
91     * @return mixed
92     */
93    public function offsetGet($offset)
94    {
95        $this->prepare();
96        return $this->collection[$offset];
97    }
98
99    /**
100     * ArrayAccess::offsetSet — Assign a value to the specified offset
101     *
102     * @param mixed $offset The offset to assign the value to.
103     * @param mixed $value  The value to set.
104     *
105     * @return void
106     */
107    public function offsetSet($offset, $value): void
108    {
109        $this->prepare();
110        if (is_null($offset)) {
111            $this->collection[] = $value;
112        } else {
113            $this->collection[$offset] = $value;
114        }
115    }
116
117    /**
118     * ArrayAccess::offsetUnset — Unset an offset
119     *
120     * @param mixed $offset The offset to unset.
121     *
122     * @return void
123     */
124    public function offsetUnset($offset): void
125    {
126        $this->prepare();
127        unset($this->collection[$offset]);
128    }
129
130    /**
131     * Iterator::current — Return the current element
132     *
133     * @return mixed
134     */
135    public function current()
136    {
137        $this->prepare();
138        return $this->collection[$this->position] ?? null;
139    }
140
141    /**
142     * Iterator::next — Move forward to next element
143     *
144     * @return void
145     */
146    public function next(): void
147    {
148        $this->prepare();
149        $keys = array_keys($this->collection);
150        $index = array_search($this->position, $keys) + 1;
151        $this->position = $keys[$index] ?? null;
152    }
153
154    /**
155     * Iterator::key — Return the key of the current element
156     *
157     * @return mixed
158     */
159    public function key()
160    {
161        $this->prepare();
162        return $this->position;
163    }
164
165    /**
166     * Iterator::valid — Checks if current position is valid
167     *
168     * @return boolean
169     */
170    public function valid(): bool
171    {
172        $this->prepare();
173        return $this->position !== null;
174    }
175
176    /**
177     * Iterator::rewind — Rewind the Iterator to the first element
178     *
179     * @return void
180     */
181    public function rewind(): void
182    {
183        $this->prepare();
184        $this->position = array_key_first($this->collection);
185    }
186
187    /**
188     * Countable::count — Count elements of an object
189     *
190     * @return integer
191     */
192    public function count(): int
193    {
194        $this->prepare();
195        return count($this->collection);
196    }
197}