SerializableMixin::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
/**
4
 * This file is part of the Kdyby (http://www.kdyby.org)
5
 *
6
 * Copyright (c) 2008, 2012 Filip Procházka ([email protected])
7
 *
8
 * For the full copyright and license information, please view the file license.md that was distributed with this source code.
9
 */
10
11
namespace Kdyby\Doctrine\Entities;
12
13
use Kdyby;
14
use Kdyby\Doctrine\StaticClassException;
15
use Nette;
16
use Nette\Reflection\ClassType;
17
use Serializable;
18
19
20
21
/**
22
 * @author Filip Procházka <[email protected]>
23
 */
24
final class SerializableMixin
25
{
26
27
	/**
28
	 * @var array|\Nette\Reflection\ClassType[]
29
	 */
30
	private static $classes = [];
31
32
	/**
33
	 * @var array|\Nette\Reflection\Property
34
	 */
35
	private static $properties = [];
36
37
38
39
	/**
40
	 * Static class - cannot be instantiated.
41
	 */
42
	final public function __construct()
43
	{
44
		throw new StaticClassException;
45
	}
46
47
48
49
	/**
50
	 * @param Serializable $object
51
	 *
52
	 * @return string
53
	 */
54
	public static function serialize(Serializable $object)
55
	{
56
		$data = [];
57
58
		$allowed = FALSE;
59
		if (method_exists($object, '__sleep')) {
60
			$allowed = (array)$object->__sleep();
61
		}
62
63
		$class = ClassType::from($object);
64
65
		do {
66
			/** @var \Nette\Reflection\Property $propertyRefl */
67
			foreach ($class->getProperties() as $propertyRefl) {
68
				if ($allowed !== FALSE && !in_array($propertyRefl->getName(), $allowed)) {
69
					continue;
70
71
				} elseif ($propertyRefl->isStatic()) {
72
					continue;
73
				}
74
75
				// prefix private properties
76
				$prefix = $propertyRefl->isPrivate()
77
					? $propertyRefl->getDeclaringClass()->getName() . '::'
78
					: NULL;
79
80
				// save value
81
				$propertyRefl->setAccessible(TRUE);
82
				$data[$prefix . $propertyRefl->getName()] = $propertyRefl->getValue($object);
83
			}
84
85
		} while ($class = $class->getParentClass());
86
87
		return serialize($data);
88
	}
89
90
91
92
	/**
93
	 * @param Serializable $object
94
	 * @param string $serialized
95
	 */
96
	public static function unserialize(Serializable $object, $serialized)
97
	{
98
		$data = unserialize($serialized);
99
100
		foreach ($data as $target => $value) {
101
			if (strpos($target, '::') !== FALSE) {
102
				list($class, $name) = explode('::', $target, 2);
103
				$propertyRefl = self::getProperty($name, $class);
104
105
			} else {
106
				$propertyRefl = self::getProperty($target, $object);
107
			}
108
109
			$propertyRefl->setValue($object, $value);
110
		}
111
112
		if (method_exists($object, '__wakeup')) {
113
			$object->__wakeup();
114
		}
115
	}
116
117
118
119
	/**
120
	 * Class reflection cache.
121
	 *
122
	 * @param string $name
123
	 * @param string|object $class
124
	 *
125
	 * @return \Nette\Reflection\Property
126
	 */
127
	private static function getProperty($name, $class)
128
	{
129
		$class = is_object($class) ? get_class($class) : $class;
130
		if (isset(self::$properties[$class][$name])) {
131
			return self::$properties[$class][$name];
132
		}
133
134
		if (!isset(self::$classes[$class])) {
135
			self::$classes[$class] = ClassType::from($class);
136
		}
137
138
		/** @var \Nette\Reflection\Property $propRefl */
139
		$propRefl = self::$classes[$class]->getProperty($name);
140
		$propRefl->setAccessible(TRUE);
141
142
		if (!isset(self::$properties[$class])) {
143
			self::$properties[$class] = [];
144
		}
145
		return self::$properties[$class][$name] = $propRefl;
146
	}
147
148
}
149