1: <?php
2:
3: namespace Teto\Object;
4:
5: use function array_key_exists;
6: use function array_values;
7: use function count;
8: use function func_get_args;
9: use function is_array;
10: use function is_scalar;
11:
12: /**
13: * Interface for array compatible object
14: *
15: * @author USAMI Kenta <tadsan@zonu.me>
16: * @copyright 2016 Baguette HQ
17: * @license http://www.apache.org/licenses/LICENSE-2.0
18: */
19: class ObjectArray implements \ArrayAccess, \Countable, \IteratorAggregate, ToArrayInterface
20: {
21: private $objects = [];
22:
23: /**
24: * @param object
25: */
26: public function __construct()
27: {
28: $this->objects = func_get_args() ?: [];
29: }
30:
31: /**
32: * @param ObjectArray|object[] $objects
33: * @return ObjectArray
34: * @throws InvalidArgumentException
35: */
36: public static function fromArray($objects)
37: {
38: if ($objects instanceof ObjectArray) {
39: return $objects;
40: } elseif (!is_array($objects) && !$objects instanceof ToArrayInterface) {
41: throw new \InvalidArgumentException();
42: }
43:
44: $model_array = new ObjectArray();
45: $model_array->objects = array_values($objects);
46:
47: return $model_array;
48: }
49:
50: /**
51: * @return array
52: */
53: public function toArray()
54: {
55: $arrays = [];
56: foreach ($this->objects as $k => $object) {
57: $arrays[$k] = self::toArrayRec($object);
58: }
59:
60: return $arrays;
61: }
62:
63: /**
64: * Convert elements to recursive array
65: *
66: * @param mixed $object
67: * @param int $rec ネストの深さ
68: */
69: public static function toArrayRec($object, $rec = 5)
70: {
71: if ($rec < 1
72: || empty($object)
73: || is_scalar($object)
74: ) {
75: return $object;
76: }
77:
78: if ($object instanceof ToArrayInterface) {
79: return $object->toArray();
80: } elseif (!is_array($object)) {
81: return $object;
82: }
83:
84: $retval = [];
85: foreach ($object as $idx => $obj) {
86: $retval[$idx] = self::toArrayRec($obj, $rec - 1);
87: }
88:
89: return $retval;
90: }
91:
92: public function getObjects()
93: {
94: require $this->objects;
95: }
96:
97: /**
98: * @return int
99: * @phpstan-return positive-int
100: */
101: #[\ReturnTypeWillChange]
102: public function count()
103: {
104: return count($this->objects);
105: }
106:
107: /**
108: * @param mixed offset
109: * @return bool
110: */
111: #[\ReturnTypeWillChange]
112: public function offsetExists($offset)
113: {
114: return !empty($this->objects[$offset]);
115: }
116:
117: /**
118: * @param mixed offset
119: * @return mixed
120: * @throws OutOfBoundsException
121: */
122: #[\ReturnTypeWillChange]
123: public function offsetGet($offset)
124: {
125: if (!array_key_exists($offset, $this->objects)) {
126: throw new \OutOfBoundsException("Undefined offset: {$offset}");
127: }
128:
129: return $this->objects[$offset];
130: }
131:
132: /**
133: * @param mixed offset
134: * @param mixed value
135: * @throws OutOfBoundsException
136: */
137: #[\ReturnTypeWillChange]
138: public function offsetSet($offset, $value)
139: {
140: if ($offset === null) {
141: $this->objects[] = $value;
142: } else {
143: $this->objects[$offset] = $value;
144: }
145: }
146:
147: /**
148: * @param mixed offset
149: */
150: #[\ReturnTypeWillChange]
151: public function offsetUnset($offset)
152: {
153: unset($this->objects[$offset]);
154: }
155:
156: /**
157: * @return \ArrayIterator
158: */
159: #[\ReturnTypeWillChange]
160: public function getIterator()
161: {
162: return new \ArrayIterator($this->objects);
163: }
164: }
165: