00001 <?php
00044 require_once 'Object/Freezer/HashGenerator/NonRecursiveSHA1.php';
00045 require_once 'Object/Freezer/IdGenerator/UUID.php';
00046 require_once 'Object/Freezer/Util.php';
00047
00060 class Object_Freezer
00061 {
00065 protected $autoload = TRUE;
00066
00070 protected $blacklist = array();
00071
00075 protected $idGenerator;
00076
00080 protected $hashGenerator;
00081
00091 public function __construct(Object_Freezer_IdGenerator $idGenerator = NULL, Object_Freezer_HashGenerator $hashGenerator = NULL, array $blacklist = array(), $useAutoload = TRUE)
00092 {
00093
00094 if ($idGenerator === NULL) {
00095 $idGenerator = new Object_Freezer_IdGenerator_UUID;
00096 }
00097
00098
00099 if ($hashGenerator === NULL) {
00100 $hashGenerator = new Object_Freezer_HashGenerator_NonRecursiveSHA1(
00101 $idGenerator
00102 );
00103 }
00104
00105 $this->setIdGenerator($idGenerator);
00106 $this->setHashGenerator($hashGenerator);
00107 $this->setBlacklist($blacklist);
00108 $this->setUseAutoload($useAutoload);
00109 }
00110
00197 public function freeze($object, array &$objects = array())
00198 {
00199
00200 if (!is_object($object)) {
00201 throw Object_Freezer_Util::getInvalidArgumentException(1, 'object');
00202 }
00203
00204
00205
00206 if (!isset($object->__php_object_freezer_uuid)) {
00207 $object->__php_object_freezer_uuid = $this->idGenerator->getId();
00208 }
00209
00210 $isDirty = $this->isDirty($object, TRUE);
00211
00212 if (!isset($objects[$object->__php_object_freezer_uuid])) {
00213 $objects[$object->__php_object_freezer_uuid] = array(
00214 'className' => get_class($object),
00215 'isDirty' => $isDirty,
00216 'state' => array()
00217 );
00218
00219
00220 foreach (Object_Freezer_Util::readAttributes($object) as $name => $value) {
00221 if ($name !== '__php_object_freezer_uuid') {
00222 if (is_array($value)) {
00223 $this->freezeArray($value, $objects);
00224 }
00225
00226 else if (is_object($value) &&
00227 !in_array(get_class($object), $this->blacklist)) {
00228
00229 $this->freeze($value, $objects);
00230
00231
00232 $value = '__php_object_freezer_' . $value->__php_object_freezer_uuid;
00233 }
00234
00235 else if (is_resource($value)) {
00236 $value = NULL;
00237 }
00238
00239
00240 $objects[$object->__php_object_freezer_uuid]['state'][$name] = $value;
00241 }
00242 }
00243 }
00244
00245 return array(
00246 'root' => $object->__php_object_freezer_uuid,
00247 'objects' => $objects
00248 );
00249 }
00250
00257 protected function freezeArray(array &$array, array &$objects)
00258 {
00259 foreach ($array as &$value) {
00260 if (is_array($value)) {
00261 $this->freezeArray($value, $objects);
00262 }
00263
00264 else if (is_object($value)) {
00265 $tmp = $this->freeze($value, $objects);
00266 $value = '__php_object_freezer_' . $tmp['root'];
00267 unset($tmp);
00268 }
00269 }
00270 }
00271
00334 public function thaw(array $frozenObject, $root = NULL, array &$objects = array())
00335 {
00336
00337 foreach ($frozenObject['objects'] as $_frozenObject) {
00338 if (!class_exists($_frozenObject['className'], $this->useAutoload)) {
00339 throw new RuntimeException(
00340 sprintf(
00341 'Class "%s" could not be found.', $_frozenObject['className']
00342 )
00343 );
00344 }
00345 }
00346
00347
00348
00349 if ($root === NULL) {
00350 $root = $frozenObject['root'];
00351 }
00352
00353
00354 if (!isset($objects[$root])) {
00355 $className = $frozenObject['objects'][$root]['className'];
00356 $state = $frozenObject['objects'][$root]['state'];
00357
00358
00359
00360 $objects[$root] = unserialize(
00361 sprintf('O:%d:"%s":0:{}', strlen($className), $className)
00362 );
00363
00364
00365 $this->thawArray($state, $frozenObject, $objects);
00366
00367 $reflector = new ReflectionObject($objects[$root]);
00368
00369 foreach ($state as $name => $value) {
00370 if (strpos($name, '__php_object_freezer') !== 0) {
00371 $attribute = $reflector->getProperty($name);
00372 $attribute->setAccessible(TRUE);
00373 $attribute->setValue($objects[$root], $value);
00374 }
00375 }
00376
00377
00378 $objects[$root]->__php_object_freezer_uuid = $root;
00379
00380
00381 if (isset($state['__php_object_freezer_hash'])) {
00382 $objects[$root]->__php_object_freezer_hash = $state['__php_object_freezer_hash'];
00383 }
00384 }
00385
00386 return $objects[$root];
00387 }
00388
00397 protected function thawArray(array &$array, array $frozenObject, array &$objects)
00398 {
00399 foreach ($array as &$value) {
00400 if (is_array($value)) {
00401 $this->thawArray($value, $frozenObject, $objects);
00402 }
00403
00404 else if (is_string($value) && strpos($value, '__php_object_freezer') === 0) {
00405 $aggregatedObjectId = str_replace(
00406 '__php_object_freezer_', '', $value
00407 );
00408
00409 if (isset($frozenObject['objects'][$aggregatedObjectId])) {
00410 $value = $this->thaw(
00411 $frozenObject, $aggregatedObjectId, $objects
00412 );
00413 }
00414 }
00415 }
00416 }
00417
00424 public function getIdGenerator()
00425 {
00426 return $this->idGenerator;
00427 }
00428
00435 public function setIdGenerator(Object_Freezer_IdGenerator $idGenerator)
00436 {
00437 $this->idGenerator = $idGenerator;
00438 }
00439
00446 public function getHashGenerator()
00447 {
00448 return $this->hashGenerator;
00449 }
00450
00457 public function setHashGenerator(Object_Freezer_HashGenerator $hashGenerator)
00458 {
00459 $this->hashGenerator = $hashGenerator;
00460 }
00461
00468 public function getBlacklist()
00469 {
00470 return $this->blacklist;
00471 }
00472
00480 public function setBlacklist(array $blacklist)
00481 {
00482 $this->blacklist = $blacklist;
00483 }
00484
00491 public function getUseAutoload()
00492 {
00493 return $this->useAutoload;
00494 }
00495
00503 public function setUseAutoload($flag)
00504 {
00505
00506 if (!is_bool($flag)) {
00507 throw Object_Freezer_Util::getInvalidArgumentException(1, 'boolean');
00508 }
00509
00510 $this->useAutoload = $flag;
00511 }
00512
00526 public function isDirty($object, $rehash = FALSE)
00527 {
00528
00529 if (!is_object($object)) {
00530 throw Object_Freezer_Util::getInvalidArgumentException(1, 'object');
00531 }
00532
00533
00534 if (!is_bool($rehash)) {
00535 throw Object_Freezer_Util::getInvalidArgumentException(2, 'boolean');
00536 }
00537
00538 $isDirty = TRUE;
00539 $hash = $this->hashGenerator->getHash($object);
00540
00541 if (isset($object->__php_object_freezer_hash) &&
00542 $object->__php_object_freezer_hash == $hash) {
00543 $isDirty = FALSE;
00544 }
00545
00546 if ($isDirty && $rehash) {
00547 $object->__php_object_freezer_hash = $hash;
00548 }
00549
00550 return $isDirty;
00551 }
00552 }