danielebarchiesi@4
|
1 <?php
|
danielebarchiesi@4
|
2
|
danielebarchiesi@4
|
3 /**
|
danielebarchiesi@4
|
4 * @file
|
danielebarchiesi@4
|
5 * Provides a base class for entities.
|
danielebarchiesi@4
|
6 */
|
danielebarchiesi@4
|
7
|
danielebarchiesi@4
|
8 /**
|
danielebarchiesi@4
|
9 * A common class for entities.
|
danielebarchiesi@4
|
10 *
|
danielebarchiesi@4
|
11 * It's suggested, but not required, to extend this class and to override
|
danielebarchiesi@4
|
12 * __construct() in order to specify a fixed entity type.
|
danielebarchiesi@4
|
13 *
|
danielebarchiesi@4
|
14 * For providing an entity label and URI it is suggested to override the
|
danielebarchiesi@4
|
15 * defaultLabel() and defaultUri() methods, and to specify the
|
danielebarchiesi@4
|
16 * entity_class_label() and entity_class_uri() as respective callbacks in
|
danielebarchiesi@4
|
17 * hook_entity_info(). That way modules are able to override your defaults
|
danielebarchiesi@4
|
18 * by altering the hook_entity_info() callbacks, while $entity->label() and
|
danielebarchiesi@4
|
19 * $entity->uri() reflect this changes as well.
|
danielebarchiesi@4
|
20 *
|
danielebarchiesi@4
|
21 * Defaults for entity properties can be easily defined by adding class
|
danielebarchiesi@4
|
22 * properties, e.g.:
|
danielebarchiesi@4
|
23 * @code
|
danielebarchiesi@4
|
24 * public $name = '';
|
danielebarchiesi@4
|
25 * public $count = 0;
|
danielebarchiesi@4
|
26 * @endcode
|
danielebarchiesi@4
|
27 */
|
danielebarchiesi@4
|
28 class Entity {
|
danielebarchiesi@4
|
29
|
danielebarchiesi@4
|
30 protected $entityType;
|
danielebarchiesi@4
|
31 protected $entityInfo;
|
danielebarchiesi@4
|
32 protected $idKey, $nameKey, $statusKey;
|
danielebarchiesi@4
|
33 protected $defaultLabel = FALSE;
|
danielebarchiesi@4
|
34
|
danielebarchiesi@4
|
35 /**
|
danielebarchiesi@4
|
36 * Creates a new entity.
|
danielebarchiesi@4
|
37 *
|
danielebarchiesi@4
|
38 * @see entity_create()
|
danielebarchiesi@4
|
39 */
|
danielebarchiesi@4
|
40 public function __construct(array $values = array(), $entityType = NULL) {
|
danielebarchiesi@4
|
41 if (empty($entityType)) {
|
danielebarchiesi@4
|
42 throw new Exception('Cannot create an instance of Entity without a specified entity type.');
|
danielebarchiesi@4
|
43 }
|
danielebarchiesi@4
|
44 $this->entityType = $entityType;
|
danielebarchiesi@4
|
45 $this->setUp();
|
danielebarchiesi@4
|
46 // Set initial values.
|
danielebarchiesi@4
|
47 foreach ($values as $key => $value) {
|
danielebarchiesi@4
|
48 $this->$key = $value;
|
danielebarchiesi@4
|
49 }
|
danielebarchiesi@4
|
50 }
|
danielebarchiesi@4
|
51
|
danielebarchiesi@4
|
52 /**
|
danielebarchiesi@4
|
53 * Set up the object instance on construction or unserializiation.
|
danielebarchiesi@4
|
54 */
|
danielebarchiesi@4
|
55 protected function setUp() {
|
danielebarchiesi@4
|
56 $this->entityInfo = entity_get_info($this->entityType);
|
danielebarchiesi@4
|
57 $this->idKey = $this->entityInfo['entity keys']['id'];
|
danielebarchiesi@4
|
58 $this->nameKey = isset($this->entityInfo['entity keys']['name']) ? $this->entityInfo['entity keys']['name'] : $this->idKey;
|
danielebarchiesi@4
|
59 $this->statusKey = empty($info['entity keys']['status']) ? 'status' : $info['entity keys']['status'];
|
danielebarchiesi@4
|
60 }
|
danielebarchiesi@4
|
61
|
danielebarchiesi@4
|
62 /**
|
danielebarchiesi@4
|
63 * Returns the internal, numeric identifier.
|
danielebarchiesi@4
|
64 *
|
danielebarchiesi@4
|
65 * Returns the numeric identifier, even if the entity type has specified a
|
danielebarchiesi@4
|
66 * name key. In the latter case, the numeric identifier is supposed to be used
|
danielebarchiesi@4
|
67 * when dealing generically with entities or internally to refer to an entity,
|
danielebarchiesi@4
|
68 * i.e. in a relational database. If unsure, use Entity:identifier().
|
danielebarchiesi@4
|
69 */
|
danielebarchiesi@4
|
70 public function internalIdentifier() {
|
danielebarchiesi@4
|
71 return isset($this->{$this->idKey}) ? $this->{$this->idKey} : NULL;
|
danielebarchiesi@4
|
72 }
|
danielebarchiesi@4
|
73
|
danielebarchiesi@4
|
74 /**
|
danielebarchiesi@4
|
75 * Returns the entity identifier, i.e. the entities name or numeric id.
|
danielebarchiesi@4
|
76 *
|
danielebarchiesi@4
|
77 * @return
|
danielebarchiesi@4
|
78 * The identifier of the entity. If the entity type makes use of a name key,
|
danielebarchiesi@4
|
79 * the name is returned, else the numeric id.
|
danielebarchiesi@4
|
80 *
|
danielebarchiesi@4
|
81 * @see entity_id()
|
danielebarchiesi@4
|
82 */
|
danielebarchiesi@4
|
83 public function identifier() {
|
danielebarchiesi@4
|
84 return isset($this->{$this->nameKey}) ? $this->{$this->nameKey} : NULL;
|
danielebarchiesi@4
|
85 }
|
danielebarchiesi@4
|
86
|
danielebarchiesi@4
|
87 /**
|
danielebarchiesi@4
|
88 * Returns the info of the type of the entity.
|
danielebarchiesi@4
|
89 *
|
danielebarchiesi@4
|
90 * @see entity_get_info()
|
danielebarchiesi@4
|
91 */
|
danielebarchiesi@4
|
92 public function entityInfo() {
|
danielebarchiesi@4
|
93 return $this->entityInfo;
|
danielebarchiesi@4
|
94 }
|
danielebarchiesi@4
|
95
|
danielebarchiesi@4
|
96 /**
|
danielebarchiesi@4
|
97 * Returns the type of the entity.
|
danielebarchiesi@4
|
98 */
|
danielebarchiesi@4
|
99 public function entityType() {
|
danielebarchiesi@4
|
100 return $this->entityType;
|
danielebarchiesi@4
|
101 }
|
danielebarchiesi@4
|
102
|
danielebarchiesi@4
|
103 /**
|
danielebarchiesi@4
|
104 * Returns the bundle of the entity.
|
danielebarchiesi@4
|
105 *
|
danielebarchiesi@4
|
106 * @return
|
danielebarchiesi@4
|
107 * The bundle of the entity. Defaults to the entity type if the entity type
|
danielebarchiesi@4
|
108 * does not make use of different bundles.
|
danielebarchiesi@4
|
109 */
|
danielebarchiesi@4
|
110 public function bundle() {
|
danielebarchiesi@4
|
111 return !empty($this->entityInfo['entity keys']['bundle']) ? $this->{$this->entityInfo['entity keys']['bundle']} : $this->entityType;
|
danielebarchiesi@4
|
112 }
|
danielebarchiesi@4
|
113
|
danielebarchiesi@4
|
114 /**
|
danielebarchiesi@4
|
115 * Returns the label of the entity.
|
danielebarchiesi@4
|
116 *
|
danielebarchiesi@4
|
117 * Modules may alter the label by specifying another 'label callback' using
|
danielebarchiesi@4
|
118 * hook_entity_info_alter().
|
danielebarchiesi@4
|
119 *
|
danielebarchiesi@4
|
120 * @see entity_label()
|
danielebarchiesi@4
|
121 */
|
danielebarchiesi@4
|
122 public function label() {
|
danielebarchiesi@4
|
123 // If the default label flag is enabled, this is being invoked recursively.
|
danielebarchiesi@4
|
124 // In this case we need to use our default label callback directly. This may
|
danielebarchiesi@4
|
125 // happen if a module provides a label callback implementation different
|
danielebarchiesi@4
|
126 // from ours, but then invokes Entity::label() or entity_class_label() from
|
danielebarchiesi@4
|
127 // there.
|
danielebarchiesi@4
|
128 if ($this->defaultLabel || (isset($this->entityInfo['label callback']) && $this->entityInfo['label callback'] == 'entity_class_label')) {
|
danielebarchiesi@4
|
129 return $this->defaultLabel();
|
danielebarchiesi@4
|
130 }
|
danielebarchiesi@4
|
131 $this->defaultLabel = TRUE;
|
danielebarchiesi@4
|
132 $label = entity_label($this->entityType, $this);
|
danielebarchiesi@4
|
133 $this->defaultLabel = FALSE;
|
danielebarchiesi@4
|
134 return $label;
|
danielebarchiesi@4
|
135 }
|
danielebarchiesi@4
|
136
|
danielebarchiesi@4
|
137 /**
|
danielebarchiesi@4
|
138 * Defines the entity label if the 'entity_class_label' callback is used.
|
danielebarchiesi@4
|
139 *
|
danielebarchiesi@4
|
140 * Specify 'entity_class_label' as 'label callback' in hook_entity_info() to
|
danielebarchiesi@4
|
141 * let the entity label point to this method. Override this in order to
|
danielebarchiesi@4
|
142 * implement a custom default label.
|
danielebarchiesi@4
|
143 */
|
danielebarchiesi@4
|
144 protected function defaultLabel() {
|
danielebarchiesi@4
|
145 // Add in the translated specified label property.
|
danielebarchiesi@4
|
146 return $this->getTranslation($this->entityInfo['entity keys']['label']);
|
danielebarchiesi@4
|
147 }
|
danielebarchiesi@4
|
148
|
danielebarchiesi@4
|
149 /**
|
danielebarchiesi@4
|
150 * Returns the uri of the entity just as entity_uri().
|
danielebarchiesi@4
|
151 *
|
danielebarchiesi@4
|
152 * Modules may alter the uri by specifying another 'uri callback' using
|
danielebarchiesi@4
|
153 * hook_entity_info_alter().
|
danielebarchiesi@4
|
154 *
|
danielebarchiesi@4
|
155 * @see entity_uri()
|
danielebarchiesi@4
|
156 */
|
danielebarchiesi@4
|
157 public function uri() {
|
danielebarchiesi@4
|
158 if (isset($this->entityInfo['uri callback']) && $this->entityInfo['uri callback'] == 'entity_class_uri') {
|
danielebarchiesi@4
|
159 return $this->defaultUri();
|
danielebarchiesi@4
|
160 }
|
danielebarchiesi@4
|
161 return entity_uri($this->entityType, $this);
|
danielebarchiesi@4
|
162 }
|
danielebarchiesi@4
|
163
|
danielebarchiesi@4
|
164 /**
|
danielebarchiesi@4
|
165 * Override this in order to implement a custom default URI and specify
|
danielebarchiesi@4
|
166 * 'entity_class_uri' as 'uri callback' hook_entity_info().
|
danielebarchiesi@4
|
167 */
|
danielebarchiesi@4
|
168 protected function defaultUri() {
|
danielebarchiesi@4
|
169 return array('path' => 'default/' . $this->identifier());
|
danielebarchiesi@4
|
170 }
|
danielebarchiesi@4
|
171
|
danielebarchiesi@4
|
172 /**
|
danielebarchiesi@4
|
173 * Checks if the entity has a certain exportable status.
|
danielebarchiesi@4
|
174 *
|
danielebarchiesi@4
|
175 * @param $status
|
danielebarchiesi@4
|
176 * A status constant, i.e. one of ENTITY_CUSTOM, ENTITY_IN_CODE,
|
danielebarchiesi@4
|
177 * ENTITY_OVERRIDDEN or ENTITY_FIXED.
|
danielebarchiesi@4
|
178 *
|
danielebarchiesi@4
|
179 * @return
|
danielebarchiesi@4
|
180 * For exportable entities TRUE if the entity has the status, else FALSE.
|
danielebarchiesi@4
|
181 * In case the entity is not exportable, NULL is returned.
|
danielebarchiesi@4
|
182 *
|
danielebarchiesi@4
|
183 * @see entity_has_status()
|
danielebarchiesi@4
|
184 */
|
danielebarchiesi@4
|
185 public function hasStatus($status) {
|
danielebarchiesi@4
|
186 if (!empty($this->entityInfo['exportable'])) {
|
danielebarchiesi@4
|
187 return isset($this->{$this->statusKey}) && ($this->{$this->statusKey} & $status) == $status;
|
danielebarchiesi@4
|
188 }
|
danielebarchiesi@4
|
189 }
|
danielebarchiesi@4
|
190
|
danielebarchiesi@4
|
191 /**
|
danielebarchiesi@4
|
192 * Permanently saves the entity.
|
danielebarchiesi@4
|
193 *
|
danielebarchiesi@4
|
194 * @see entity_save()
|
danielebarchiesi@4
|
195 */
|
danielebarchiesi@4
|
196 public function save() {
|
danielebarchiesi@4
|
197 return entity_get_controller($this->entityType)->save($this);
|
danielebarchiesi@4
|
198 }
|
danielebarchiesi@4
|
199
|
danielebarchiesi@4
|
200 /**
|
danielebarchiesi@4
|
201 * Permanently deletes the entity.
|
danielebarchiesi@4
|
202 *
|
danielebarchiesi@4
|
203 * @see entity_delete()
|
danielebarchiesi@4
|
204 */
|
danielebarchiesi@4
|
205 public function delete() {
|
danielebarchiesi@4
|
206 $id = $this->identifier();
|
danielebarchiesi@4
|
207 if (isset($id)) {
|
danielebarchiesi@4
|
208 entity_get_controller($this->entityType)->delete(array($id));
|
danielebarchiesi@4
|
209 }
|
danielebarchiesi@4
|
210 }
|
danielebarchiesi@4
|
211
|
danielebarchiesi@4
|
212 /**
|
danielebarchiesi@4
|
213 * Exports the entity.
|
danielebarchiesi@4
|
214 *
|
danielebarchiesi@4
|
215 * @see entity_export()
|
danielebarchiesi@4
|
216 */
|
danielebarchiesi@4
|
217 public function export($prefix = '') {
|
danielebarchiesi@4
|
218 return entity_get_controller($this->entityType)->export($this, $prefix);
|
danielebarchiesi@4
|
219 }
|
danielebarchiesi@4
|
220
|
danielebarchiesi@4
|
221 /**
|
danielebarchiesi@4
|
222 * Generate an array for rendering the entity.
|
danielebarchiesi@4
|
223 *
|
danielebarchiesi@4
|
224 * @see entity_view()
|
danielebarchiesi@4
|
225 */
|
danielebarchiesi@4
|
226 public function view($view_mode = 'full', $langcode = NULL, $page = NULL) {
|
danielebarchiesi@4
|
227 return entity_get_controller($this->entityType)->view(array($this), $view_mode, $langcode, $page);
|
danielebarchiesi@4
|
228 }
|
danielebarchiesi@4
|
229
|
danielebarchiesi@4
|
230 /**
|
danielebarchiesi@4
|
231 * Builds a structured array representing the entity's content.
|
danielebarchiesi@4
|
232 *
|
danielebarchiesi@4
|
233 * @see entity_build_content()
|
danielebarchiesi@4
|
234 */
|
danielebarchiesi@4
|
235 public function buildContent($view_mode = 'full', $langcode = NULL) {
|
danielebarchiesi@4
|
236 return entity_get_controller($this->entityType)->buildContent($this, $view_mode, $langcode);
|
danielebarchiesi@4
|
237 }
|
danielebarchiesi@4
|
238
|
danielebarchiesi@4
|
239 /**
|
danielebarchiesi@4
|
240 * Gets the raw, translated value of a property or field.
|
danielebarchiesi@4
|
241 *
|
danielebarchiesi@4
|
242 * Supports retrieving field translations as well as i18n string translations.
|
danielebarchiesi@4
|
243 *
|
danielebarchiesi@4
|
244 * Note that this returns raw data values, which might not reflect what
|
danielebarchiesi@4
|
245 * has been declared for hook_entity_property_info() as no 'getter callbacks'
|
danielebarchiesi@4
|
246 * are invoked or no referenced entities are loaded. For retrieving values
|
danielebarchiesi@4
|
247 * reflecting the property info make use of entity metadata wrappers, see
|
danielebarchiesi@4
|
248 * entity_metadata_wrapper().
|
danielebarchiesi@4
|
249 *
|
danielebarchiesi@4
|
250 * @param $property_name
|
danielebarchiesi@4
|
251 * The name of the property to return; e.g., 'title'.
|
danielebarchiesi@4
|
252 * @param $langcode
|
danielebarchiesi@4
|
253 * (optional) The language code of the language to which the value should
|
danielebarchiesi@4
|
254 * be translated. If set to NULL, the default display language is being
|
danielebarchiesi@4
|
255 * used.
|
danielebarchiesi@4
|
256 *
|
danielebarchiesi@4
|
257 * @return
|
danielebarchiesi@4
|
258 * The raw, translated property value; or the raw, un-translated value if no
|
danielebarchiesi@4
|
259 * translation is available.
|
danielebarchiesi@4
|
260 *
|
danielebarchiesi@4
|
261 * @todo Implement an analogous setTranslation() method for updating.
|
danielebarchiesi@4
|
262 */
|
danielebarchiesi@4
|
263 public function getTranslation($property, $langcode = NULL) {
|
danielebarchiesi@4
|
264 $all_info = entity_get_all_property_info($this->entityType);
|
danielebarchiesi@4
|
265 // Assign by reference to avoid triggering notices if metadata is missing.
|
danielebarchiesi@4
|
266 $property_info = &$all_info[$property];
|
danielebarchiesi@4
|
267
|
danielebarchiesi@4
|
268 if (!empty($property_info['translatable'])) {
|
danielebarchiesi@4
|
269 if (!empty($property_info['field'])) {
|
danielebarchiesi@4
|
270 return field_get_items($this->entityType, $this, $property, $langcode);
|
danielebarchiesi@4
|
271 }
|
danielebarchiesi@4
|
272 elseif (!empty($property_info['i18n string'])) {
|
danielebarchiesi@4
|
273 $name = $this->entityInfo['module'] . ':' . $this->entityType . ':' . $this->identifier() . ':' . $property;
|
danielebarchiesi@4
|
274 return entity_i18n_string($name, $this->$property, $langcode);
|
danielebarchiesi@4
|
275 }
|
danielebarchiesi@4
|
276 }
|
danielebarchiesi@4
|
277 return $this->$property;
|
danielebarchiesi@4
|
278 }
|
danielebarchiesi@4
|
279
|
danielebarchiesi@4
|
280 /**
|
danielebarchiesi@4
|
281 * Checks whether the entity is the default revision.
|
danielebarchiesi@4
|
282 *
|
danielebarchiesi@4
|
283 * @return Boolean
|
danielebarchiesi@4
|
284 *
|
danielebarchiesi@4
|
285 * @see entity_revision_is_default()
|
danielebarchiesi@4
|
286 */
|
danielebarchiesi@4
|
287 public function isDefaultRevision() {
|
danielebarchiesi@4
|
288 if (!empty($this->entityInfo['entity keys']['revision'])) {
|
danielebarchiesi@4
|
289 $key = !empty($this->entityInfo['entity keys']['default revision']) ? $this->entityInfo['entity keys']['default revision'] : 'default_revision';
|
danielebarchiesi@4
|
290 return !empty($this->$key);
|
danielebarchiesi@4
|
291 }
|
danielebarchiesi@4
|
292 return TRUE;
|
danielebarchiesi@4
|
293 }
|
danielebarchiesi@4
|
294
|
danielebarchiesi@4
|
295 /**
|
danielebarchiesi@4
|
296 * Magic method to only serialize what's necessary.
|
danielebarchiesi@4
|
297 */
|
danielebarchiesi@4
|
298 public function __sleep() {
|
danielebarchiesi@4
|
299 $vars = get_object_vars($this);
|
danielebarchiesi@4
|
300 unset($vars['entityInfo'], $vars['idKey'], $vars['nameKey'], $vars['statusKey']);
|
danielebarchiesi@4
|
301 // Also key the returned array with the variable names so the method may
|
danielebarchiesi@4
|
302 // be easily overridden and customized.
|
danielebarchiesi@4
|
303 return drupal_map_assoc(array_keys($vars));
|
danielebarchiesi@4
|
304 }
|
danielebarchiesi@4
|
305
|
danielebarchiesi@4
|
306 /**
|
danielebarchiesi@4
|
307 * Magic method to invoke setUp() on unserialization.
|
danielebarchiesi@4
|
308 */
|
danielebarchiesi@4
|
309 public function __wakeup() {
|
danielebarchiesi@4
|
310 $this->setUp();
|
danielebarchiesi@4
|
311 }
|
danielebarchiesi@4
|
312 }
|
danielebarchiesi@4
|
313
|
danielebarchiesi@4
|
314 /**
|
danielebarchiesi@4
|
315 * These classes are deprecated by "Entity" and are only here for backward
|
danielebarchiesi@4
|
316 * compatibility reasons.
|
danielebarchiesi@4
|
317 */
|
danielebarchiesi@4
|
318 class EntityDB extends Entity {}
|
danielebarchiesi@4
|
319 class EntityExtendable extends Entity {}
|
danielebarchiesi@4
|
320 class EntityDBExtendable extends Entity {}
|