[+FEATURE] Extbase (Persistence): Implemented a second Lazy Loading strategy called...
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Reflection / ClassSchema.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2009 Jochen Rau <jochen.rau@typoplanet.de>
6 * All rights reserved
7 *
8 * This class is a backport of the corresponding class of FLOW3.
9 * All credits go to the v5 team.
10 *
11 * This script is part of the TYPO3 project. The TYPO3 project is
12 * free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * The GNU General Public License can be found at
18 * http://www.gnu.org/copyleft/gpl.html.
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27
28 /**
29 * A class schema
30 *
31 * @version $Id: ClassSchema.php 2984 2009-08-04 13:04:35Z k-fish $
32 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
33 */
34 class Tx_Extbase_Reflection_ClassSchema {
35
36 /**
37 * Available model types
38 */
39 const MODELTYPE_ENTITY = 1;
40 const MODELTYPE_VALUEOBJECT = 2;
41
42 /**
43 * Specifies the allowed property types.
44 */
45 const ALLOWED_TYPES_PATTERN = '/^(?P<type>integer|int|float|boolean|string|DateTime|Tx_[a-zA-Z0-9_]+|array|ArrayObject|Tx_Extbase_Persistence_ObjectStorage)(?:<(?P<elementType>[a-zA-Z0-9_]+)>)?/';
46
47 /**
48 * Name of the class this schema is referring to
49 *
50 * @var string
51 */
52 protected $className;
53
54 /**
55 * Model type of the class this schema is referring to
56 *
57 * @var integer
58 */
59 protected $modelType = self::MODELTYPE_ENTITY;
60
61 /**
62 * Whether a repository exists for the class this schema is referring to
63 * @var boolean
64 */
65 protected $aggregateRoot = FALSE;
66
67 /**
68 * The name of the property holding the uuid of an entity, if any.
69 *
70 * @var string
71 */
72 protected $uuidPropertyName;
73
74 /**
75 * Properties of the class which need to be persisted
76 *
77 * @var array
78 */
79 protected $properties = array();
80
81 /**
82 * The properties forming the identity of an object
83 *
84 * @var array
85 */
86 protected $identityProperties = array();
87
88 /**
89 * Constructs this class schema
90 *
91 * @param string $className Name of the class this schema is referring to
92 * @author Robert Lemke <robert@typo3.org>
93 */
94 public function __construct($className) {
95 $this->className = $className;
96 }
97
98 /**
99 * Returns the class name this schema is referring to
100 *
101 * @return string The class name
102 * @author Robert Lemke <robert@typo3.org>
103 */
104 public function getClassName() {
105 return $this->className;
106 }
107
108 /**
109 * Adds (defines) a specific property and its type.
110 *
111 * @param string $name Name of the property
112 * @param string $type Type of the property (see ALLOWED_TYPES_PATTERN)
113 * @param boolean $lazy Whether the property should be lazy-loaded when reconstituting
114 * @return void
115 * @author Robert Lemke <robert@typo3.org>
116 * @author Karsten Dambekalns <karsten@typo3.org>
117 */
118 public function addProperty($name, $type, $lazy = FALSE) {
119 $matches = array();
120 if (preg_match(self::ALLOWED_TYPES_PATTERN, $type, $matches)) {
121 $type = ($matches['type'] === 'int') ? 'integer' : $matches['type'];
122 $elementType = isset($matches['elementType']) ? $matches['elementType'] : NULL;
123
124 if ($elementType !== NULL && !in_array($type, array('array', 'ArrayObject', 'Tx_Extbase_Persistence_ObjectStorage', 'Tx_Extbase_Persistence_LazyObjectStorage'))) {
125 throw new Tx_Extbase_Reflection_Exception_InvalidPropertyType('Property of type "' . $type . '" must not have an element type hint (' . $elementType . ').', 1248103053);
126 }
127
128 $this->properties[$name] = array(
129 'type' => $type,
130 'elementType' => $elementType,
131 'lazy' => $lazy
132 );
133 } else {
134 throw new Tx_Extbase_Reflection_Exception_InvalidPropertyType('Invalid property type encountered: ' . $type, 1220387528);
135 }
136 }
137
138 /**
139 * Returns the given property defined in this schema. Check with
140 * hasProperty($propertyName) before!
141 *
142 * @return array
143 * @author Karsten Dambekalns <karsten@typo3.org>
144 */
145 public function getProperty($propertyName) {
146 return $this->properties[$propertyName];
147 }
148
149 /**
150 * Returns all properties defined in this schema
151 *
152 * @return array
153 * @author Robert Lemke <robert@typo3.org>
154 */
155 public function getProperties() {
156 return $this->properties;
157 }
158
159 /**
160 * Sets the model type of the class this schema is referring to.
161 *
162 * @param integer The model type, one of the MODELTYPE_* constants.
163 * @return void
164 * @author Robert Lemke <robert@typo3.org>
165 */
166 public function setModelType($modelType) {
167 if ($modelType < self::MODELTYPE_ENTITY || $modelType > self::MODELTYPE_VALUEOBJECT) throw new InvalidArgumentException('"' . $modelType . '" is an invalid model type.', 1212519195);
168 $this->modelType = $modelType;
169 }
170
171 /**
172 * Returns the model type of the class this schema is referring to.
173 *
174 * @return integer The model type, one of the MODELTYPE_* constants.
175 * @author Robert Lemke <robert@typo3.org>
176 */
177 public function getModelType() {
178 return $this->modelType;
179 }
180
181 /**
182 * Marks the class if it is root of an aggregate and therefore accessible
183 * through a repository - or not.
184 *
185 * @param boolean $isRoot TRUE if it is the root of an aggregate
186 * @return void
187 * @author Karsten Dambekalns <karsten@typo3.org>
188 */
189 public function setAggregateRoot($isRoot) {
190 $this->aggregateRoot = $isRoot;
191 }
192
193 /**
194 * Whether the class is an aggregate root and therefore accessible through
195 * a repository.
196 *
197 * @return boolean TRUE if it is managed
198 * @author Karsten Dambekalns <karsten@typo3.org>
199 */
200 public function isAggregateRoot() {
201 return $this->aggregateRoot;
202 }
203
204 /**
205 * If the class schema has a certain property.
206 *
207 * @param string $propertyName Name of the property
208 * @return boolean
209 * @author Robert Lemke <robert@typo3.org>
210 */
211 public function hasProperty($propertyName) {
212 return array_key_exists($propertyName, $this->properties);
213 }
214
215 /**
216 * Sets the property marked as uuid of an object with @uuid
217 *
218 * @param string $propertyName
219 * @return void
220 * @author Karsten Dambekalns <karsten@typo3.org>
221 */
222 public function setUUIDPropertyName($propertyName) {
223 if (!array_key_exists($propertyName, $this->properties)) {
224 throw new InvalidArgumentException('Property "' . $propertyName . '" must be added to the class schema before it can be marked as UUID property.', 1233863842);
225 }
226
227 $this->uuidPropertyName = $propertyName;
228 }
229
230 /**
231 * Gets the name of the property marked as uuid of an object
232 *
233 * @return string
234 * @author Karsten Dambekalns <karsten@typo3.org>
235 */
236 public function getUUIDPropertyName() {
237 return $this->uuidPropertyName;
238 }
239
240 /**
241 * Marks the given property as one of properties forming the identity
242 * of an object. The property must already be registered in the class
243 * schema.
244 *
245 * @param string $propertyName
246 * @return void
247 * @author Karsten Dambekalns <karsten@typo3.org>
248 */
249 public function markAsIdentityProperty($propertyName) {
250 if (!array_key_exists($propertyName, $this->properties)) {
251 throw new InvalidArgumentException('Property "' . $propertyName . '" must be added to the class schema before it can be marked as identity property.', 1233775407);
252 }
253 if ($this->properties[$propertyName]['lazy'] === TRUE) {
254 throw new InvalidArgumentException('Property "' . $propertyName . '" must not be makred for lazy loading to be marked as identity property.', 1239896904);
255 }
256
257 $this->identityProperties[$propertyName] = $this->properties[$propertyName]['type'];
258 }
259
260 /**
261 * Gets the properties (names and types) forming the identity of an object.
262 *
263 * @return array
264 * @author Karsten Dambekalns <karsten@typo3.org>
265 * @see markAsIdentityProperty()
266 */
267 public function getIdentityProperties() {
268 return $this->identityProperties;
269 }
270
271 }
272 ?>