1+ <?php
2+
3+ namespace Sevavietl \Arrays ;
4+
5+ class CompositeKeyArray implements \ArrayAccess
6+ {
7+ protected $ array ;
8+ protected $ undefinedOffsetAction ;
9+
10+ public function __construct (array $ array = [])
11+ {
12+ $ this ->array = $ array ;
13+
14+ $ this ->undefinedOffsetAction = function ($ offset ) {
15+ throw new UndefinedOffsetException (
16+ "Undefined offset $ offset. "
17+ );
18+ };
19+ }
20+
21+ public function setUndefinedOffsetAction (Callable $ undefinedOffsetAction )
22+ {
23+ $ this ->undefinedOffsetAction = $ undefinedOffsetAction ;
24+
25+ return $ this ;
26+ }
27+
28+ public function toArray ()
29+ {
30+ return $ this ->array ;
31+ }
32+
33+ protected $ offsets ;
34+
35+ public function offsetExists ($ offset )
36+ {
37+ $ this ->setOffsets ($ offset );
38+
39+ return $ this ->walkThroughOffsets (
40+ $ this ->array ,
41+ function ($ array , $ offset ) {
42+ return isset ($ array [$ offset ]);
43+ },
44+ function () {
45+ return false ;
46+ }
47+ );
48+ }
49+
50+ public function offsetGet ($ offset )
51+ {
52+ $ this ->setOffsets ($ offset );
53+
54+ return $ this ->walkThroughOffsets (
55+ $ this ->array ,
56+ function &($ array , $ offset ) {
57+ return $ array [$ offset ];
58+ },
59+ $ this ->undefinedOffsetAction
60+ );
61+ }
62+
63+ public function offsetSet ($ offset , $ value )
64+ {
65+ $ this ->value = $ value ;
66+
67+ $ this ->setOffsets ($ offset );
68+
69+ $ baseCaseAction = function (&$ array , $ offset ) {
70+ $ array [$ offset ] = $ this ->value ;
71+ };
72+
73+ $ offsetNotExistsAction = function (&$ array , $ offset ) use (
74+ $ baseCaseAction ,
75+ &$ offsetNotExistsAction
76+ ) {
77+ $ value = empty ($ this ->offsets ) ? $ this ->value : [];
78+
79+ if (!empty ($ offset )) {
80+ $ array [$ offset ] = $ value ;
81+ } else {
82+ $ array [] = $ value ;
83+ }
84+
85+ if (empty ($ this ->offsets )) {
86+ return ;
87+ }
88+
89+ return $ this ->walkThroughOffsets (
90+ $ array ,
91+ $ baseCaseAction ,
92+ $ offsetNotExistsAction
93+ );
94+ };
95+
96+ return $ this ->walkThroughOffsets (
97+ $ this ->array ,
98+ $ baseCaseAction ,
99+ $ offsetNotExistsAction
100+ );
101+ }
102+
103+ public function offsetUnset ($ offset )
104+ {
105+ $ this ->setOffsets ($ offset );
106+
107+ return $ this ->walkThroughOffsets (
108+ $ this ->array ,
109+ function (&$ array , $ offset ) {
110+ unset($ array [$ offset ]);
111+ },
112+ $ this ->undefinedOffsetAction
113+ );
114+ }
115+
116+ protected function setOffsets ($ offsets )
117+ {
118+ $ this ->offsets = is_array ($ offsets ) ? $ offsets : [$ offsets ];
119+ }
120+
121+ protected function walkThroughOffsets (
122+ &$ array ,
123+ Callable $ baseCaseAction ,
124+ Callable $ offsetNotExistsAction
125+ ) {
126+ $ offset = array_shift ($ this ->offsets );
127+
128+ if (isset ($ array [$ offset ])) {
129+ if (empty ($ this ->offsets )) {
130+ return $ baseCaseAction ($ array , $ offset );
131+ }
132+
133+ return $ this ->walkThroughOffsets (
134+ $ array [$ offset ],
135+ $ baseCaseAction ,
136+ $ offsetNotExistsAction
137+ );
138+ }
139+
140+ return $ offsetNotExistsAction ($ array , $ offset );
141+ }
142+ }
0 commit comments