1313use OutOfBoundsException ;
1414use SplObjectStorage ;
1515
16- class IdentityMap
16+ final class IdentityMap
1717{
1818
19+ const ADDED = 'added ' ;
20+ const MODIFIED = 'modified ' ;
21+ const REMOVED = 'removed ' ;
22+ const UNHANDLED = 'unhandled ' ;
23+
1924 /**
2025 * @var ArrayObject
2126 */
@@ -26,11 +31,54 @@ class IdentityMap
2631 */
2732 protected $ objectToId ;
2833
34+ /**
35+ * @var ArrayObject
36+ */
37+ private $ removed ;
38+
2939 public function __construct ()
3040 {
3141 $ this ->objectToId = new SplObjectStorage ();
3242 $ this ->idToObject = new ArrayObject ();
3343 $ this ->removed = new ArrayObject ();
44+ $ this ->objectStorage = new \SplObjectStorage ();
45+ }
46+
47+ /**
48+ * @param $object
49+ */
50+ private function add ($ object )
51+ {
52+ $ this ->objectStorage [$ object ] = self ::ADDED ;
53+ }
54+
55+ /**
56+ * @param $object
57+ */
58+ private function modify ($ object )
59+ {
60+ $ this ->objectStorage [$ object ] = self ::MODIFIED ;
61+ }
62+
63+ /**
64+ * @param $object
65+ */
66+ private function delete ($ object )
67+ {
68+ $ this ->objectStorage [$ object ] = self ::REMOVED ;
69+ }
70+
71+ /**
72+ * @param $object
73+ * @return object|string
74+ */
75+ public function getState ($ object )
76+ {
77+ if (isset ($ this ->objectStorage [$ object ])) {
78+ return $ this ->objectStorage [$ object ];
79+ }
80+
81+ return self ::UNHANDLED ;
3482 }
3583
3684 /**
@@ -39,6 +87,19 @@ public function __construct()
3987 */
4088 public function set ($ id , $ object )
4189 {
90+ if ($ this ->hasObject ($ object )) {
91+ $ this ->modify ($ object );
92+ }else {
93+ $ this ->add ($ object );
94+ }
95+
96+ // remove old id's
97+ if ($ this ->hasObject ($ object )){
98+ if ($ this ->getId ($ object ) !== $ id ){
99+ $ this ->removeId ($ id );
100+ }
101+ }
102+
42103 $ this ->idToObject [$ id ] = $ object ;
43104 $ this ->objectToId [$ object ] = $ id ;
44105 }
@@ -93,38 +154,72 @@ public function getObject($id)
93154 }
94155
95156 /**
157+ * Remove link from object to id
96158 * @param $object
97159 */
98- public function removeObject ($ object )
160+ private function removeObject ($ object )
99161 {
100- if (false === $ this ->hasObject ($ object )) {
101- $ id = $ this ->getId ($ object );
162+ if ($ this ->hasObject ($ object )) {
102163 unset($ this ->objectToId [$ object ]);
103- unset($ this ->idToObject [$ id ]);
104- $ this ->removed [$ id ] = $ object ;
105164 }
106165 }
107166
108167 /**
168+ * Remove link from id to object
109169 * @param $id
110170 */
111- public function removeId ($ id )
171+ private function removeId ($ id )
112172 {
113173 if ($ this ->hasId ($ id )) {
114- $ object = $ this ->getObject ($ id );
115- unset($ this ->objectToId [$ object ]);
116174 unset($ this ->idToObject [$ id ]);
117- $ this ->removed [$ id ] = $ object ;
118175 }
119176 }
120177
178+ /**
179+ * remove object by id
180+ * @param $id
181+ * @param $object
182+ */
183+ public function remove ($ id , $ object ){
184+ $ this ->removeId ($ id );
185+ $ this ->removeObject ($ object );
186+ $ this ->removed [$ id ] = $ object ;
187+
188+ //update object state
189+ $ this ->delete ($ object );
190+ }
191+
192+ /**
193+ * @return array
194+ */
195+ public function getModified ()
196+ {
197+ return $ this ->idToObject ->getArrayCopy ();
198+ }
199+
121200 /**
122201 * @return array
123202 */
124- public function toArray ()
203+ public function getRemoved ()
125204 {
126- $ modified = $ this ->idToObject ->getArrayCopy ();
127- $ removed = $ this ->removed ->getArrayCopy ();
128- return array_replace ($ modified , $ removed );
205+ return $ this ->removed ->getArrayCopy ();
206+ }
207+
208+ /**
209+ * @return array
210+ */
211+ public function getGraph ()
212+ {
213+ $ graph = [];
214+
215+ $ modified = $ this ->getModified ();
216+ $ removed = $ this ->getRemoved ();
217+ $ identities = array_replace ($ modified , $ removed );
218+
219+ foreach ($ identities as $ id => $ object ) {
220+ $ graph [get_class ($ object )][$ id ] = $ this ->getState ($ object );
221+ }
222+
223+ return $ graph ;
129224 }
130225}
0 commit comments