/** * Freezes an object. * * If the object has not been frozen before, the attribute * __php_object_freezer_uuid will be added to it. * * In the example below, we freeze an object of class A. As this object * aggregates an object of class B, the object freezer has to freeze two * objects in total. * * <code> * <?php * require_once 'Object/Freezer.php'; * * class A * { * protected $b; * * public function __construct() * { * $this->b = new B; * } * } * * class B * { * protected $foo = 'bar'; * } * * $freezer = new Object_Freezer; * var_dump($freezer->freeze(new A)); * ?> * </code> * * Below is the output of the code example above. * * <code> * array(2) { * ["root"]=> * string(36) "32246c35-f47b-4fbc-a2ad-ed14e520865e" * ["objects"]=> * array(2) { * ["32246c35-f47b-4fbc-a2ad-ed14e520865e"]=> * array(3) { * ["className"]=> * string(1) "A" * ["isDirty"]=> * bool(true) * ["state"]=> * array(2) { * ["b"]=> * string(57) * "__php_object_freezer_3cd682bf-8eba-4fec-90e2-ebe98aa07ab7" * ["__php_object_freezer_hash"]=> * string(40) "8b80da9c38c0c41c829cbbefbca9b18aa67ff607" * } * } * ["3cd682bf-8eba-4fec-90e2-ebe98aa07ab7"]=> * array(3) { * ["className"]=> * string(1) "B" * ["isDirty"]=> * bool(true) * ["state"]=> * array(2) { * ["foo"]=> * string(3) "bar" * ["__php_object_freezer_hash"]=> * string(40) "e04e935f09f2d526258d8a16613c5bce31e84e87" * } * } * } * } * </code> * * The reference to the object of class B that the object of class A had * before it was frozen has been replaced with the UUID of the frozen * object of class B * (__php_object_freezer_3cd682bf-8eba-4fec-90e2-ebe98aa07ab7). * * The result array's "root" element contains the UUID for the now frozen * object of class A (32246c35-f47b-4fbc-a2ad-ed14e520865e). * * @param object $object The object that is to be frozen. * @param array $objects Only used internally. * * @return array The frozen object(s). * * @throws InvalidArgumentException */ public function freeze($object, array &$objects = []) { // Bail out if a non-object was passed. if (!is_object($object)) { throw Object_Freezer_Util::getInvalidArgumentException(1, 'object'); } // The object has not been frozen before, generate a new UUID and // store it in the "special" __php_object_freezer_uuid attribute. if (!isset($object->__php_object_freezer_uuid)) { $object->__php_object_freezer_uuid = $this->idGenerator->getId(); } $isDirty = $this->isDirty($object, true); $uuid = $object->__php_object_freezer_uuid; if (!isset($objects[$uuid])) { $objects[$uuid] = ['className' => get_class($object), 'isDirty' => $isDirty, 'state' => []]; // Iterate over the attributes of the object. foreach (Object_Freezer_Util::readAttributes($object) as $k => $v) { if ($k !== '__php_object_freezer_uuid') { if (is_array($v)) { $this->freezeArray($v, $objects); } elseif (is_object($v) && !in_array(get_class($v), $this->blacklist)) { // Freeze the aggregated object. $this->freeze($v, $objects); // Replace $v with the aggregated object's UUID. $v = '__php_object_freezer_' . $v->__php_object_freezer_uuid; } elseif (is_resource($v)) { $v = null; } // Store the attribute in the object's state array. $objects[$uuid]['state'][$k] = $v; } } } return ['root' => $uuid, 'objects' => $objects]; }
/** * Implementation of Object_Freezer_HashGenerator that uses the SHA1 * hashing function on the attribute values of an object without recursing * into aggregated arrays or objects. * * @param object $object The object that is to be hashed. * * @return string * * @throws InvalidArgumentException */ public function getHash($object) { // Bail out if a non-object was passed. if (!is_object($object)) { throw Object_Freezer_Util::getInvalidArgumentException(1, 'object'); } $attributes = Object_Freezer_Util::readAttributes($object); ksort($attributes); if (isset($attributes['__php_object_freezer_hash'])) { unset($attributes['__php_object_freezer_hash']); } foreach ($attributes as $key => $value) { if (is_array($value)) { $attributes[$key] = '<array>'; } elseif (is_object($value)) { if (!isset($value->__php_object_freezer_uuid)) { $value->__php_object_freezer_uuid = $this->idGenerator->getId(); } $attributes[$key] = $value->__php_object_freezer_uuid; } elseif (is_resource($value)) { $attributes[$key] = null; } } return sha1(get_class($object) . implode(':', $attributes)); }