1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
22:
23: namespace picon;
24:
25: 26: 27: 28: 29: 30: 31: 32:
33: class PiconSerializer
34: {
35: private static $prepared = array();
36: private static $restore = array();
37:
38: private function __construct()
39: {
40:
41: }
42:
43: 44: 45: 46: 47:
48: public static function serialize($object)
49: {
50: if(!is_object($object))
51: {
52: return serialize($object);
53: }
54: self::$prepared = array();
55: self::$restore = array();
56: self::prepareForSerize(new \ReflectionAnnotatedClass($object), $object);
57:
58: $serialized = serialize($object);
59: self::restore();
60:
61: self::$prepared = array();
62: self::$restore = array();
63: return $serialized;
64: }
65:
66: 67: 68: 69: 70:
71: public static function unserialize($string)
72: {
73: $unserialzed = unserialize($string);
74:
75: if($unserialzed instanceof InjectOnWakeup)
76: {
77: Injector::get()->inject($unserialzed);
78: }
79:
80: return $unserialzed;
81: }
82:
83: private static function prepareForSerize(\ReflectionAnnotatedClass $reflection, $object, $parent = false)
84: {
85: $hash = spl_object_hash($object);
86: if(in_array($hash, self::$prepared) && $parent==false)
87: {
88: return;
89: }
90: array_push(self::$prepared, $hash);
91: $globalAltered = false;
92: $defaults = null;
93:
94: foreach($reflection->getProperties() as $property)
95: {
96: $altered = false;
97: $property->setAccessible(true);
98: $value = $property->getValue($object);
99: if(self::isTransient($property))
100: {
101: $defaults = $defaults==null?$reflection->getDefaultProperties():$defaults;
102: $name = $property->getName();
103: $property->setValue($object, array_key_exists($name, $defaults)?$defaults[$name]:null);
104: $altered = true;
105: }
106: else if(is_object($value) && $value instanceof \Closure)
107: {
108: $property->setValue($object, new SerializableClosure($value));
109: $altered = true;
110: }
111: else if(is_object($value) && !($value instanceof SerializableClosure) && spl_object_hash($value)!=$hash)
112: {
113: $valueReflection = new \ReflectionAnnotatedClass($value);
114: $altered = self::prepareForSerize($valueReflection, $value);
115: }
116: else if(is_array($value))
117: {
118: $newValue = self::prepareArrayForSerialize($value);
119:
120: if(is_array($newValue))
121: {
122: $property->setValue($object, $newValue);
123: $altered = true;
124: }
125: }
126:
127: if($altered)
128: {
129: self::addRestore($property, $object, $value);
130: $globalAltered = true;
131: }
132: }
133:
134: $parent = $reflection->getParentClass();
135:
136: if($parent!=null)
137: {
138: self::prepareForSerize($parent, $object, true);
139: }
140:
141: if(!$parent)
142: {
143: if($object instanceof Detachable)
144: {
145: $object->detach();
146: }
147: }
148: return $globalAltered;
149: }
150:
151: 152: 153: 154: 155:
156: private static function prepareArrayForSerialize($entry)
157: {
158: $newEntry = array();
159: $altered = false;
160:
161: foreach($entry as $key => $value)
162: {
163: if(is_array($value))
164: {
165: $newValue = self::prepareArrayForSerialize($value);
166: $newEntry[$key] = is_array($newValue) ? $newValue : $value;
167: $altered = $altered?true:is_array($newValue);
168: }
169: else if(is_object($value) && $value instanceof \Closure)
170: {
171: $newEntry[$key] = new SerializableClosure($value);
172: $altered = true;
173: }
174: else if(is_object($value) && !($value instanceof SerializableClosure) && !in_array(spl_object_hash($value), self::$prepared))
175: {
176: $ia = self::prepareForSerize(new \ReflectionAnnotatedClass($value), $value);
177: $altered = $altered?true:$ia;
178: $newEntry[$key] = $value;
179: }
180: else
181: {
182: $newEntry[$key] = $value;
183: }
184: }
185:
186: if($altered)
187: {
188: return $newEntry;
189: }
190: return false;
191: }
192:
193: private static function addRestore(\ReflectionAnnotatedProperty $property, $object, $value)
194: {
195: $restore = new \stdClass();
196: $restore->property = $property;
197: $restore->object = $object;
198: $restore->value = $value;
199: self::$restore[] = $restore;
200: }
201:
202: private static function restore()
203: {
204: foreach(self::$restore as $restore)
205: {
206: $restore->property->setValue($restore->object, $restore->value);
207: }
208: }
209:
210: private static function isTransient(\ReflectionAnnotatedProperty $property)
211: {
212: $annotations = $property->getAllAnnotations();
213:
214: foreach($annotations as $annotation)
215: {
216: return is_subclass_of($annotation, "Transient") || get_class($annotation)=="Transient";
217: }
218: }
219: }
220:
221: ?>
222: