Project

General

Profile

Paste
Download (10.4 KB) Statistics
| Branch: | Revision:

root / drupal7 / sites / all / modules / entity / includes / entity.inc @ 7d7b5830

1
<?php
2

    
3
/**
4
 * @file
5
 * Provides a base class for entities.
6
 */
7

    
8
/**
9
 * A common class for entities.
10
 *
11
 * It's suggested, but not required, to extend this class and to override
12
 * __construct() in order to specify a fixed entity type.
13
 *
14
 * For providing an entity label and URI it is suggested to override the
15
 * defaultLabel() and defaultUri() methods, and to specify the
16
 * entity_class_label() and entity_class_uri() as respective callbacks in
17
 * hook_entity_info(). That way modules are able to override your defaults
18
 * by altering the hook_entity_info() callbacks, while $entity->label() and
19
 * $entity->uri() reflect this changes as well.
20
 *
21
 * Defaults for entity properties can be easily defined by adding class
22
 * properties, e.g.:
23
 * @code
24
 *   public $name = '';
25
 *   public $count = 0;
26
 * @endcode
27
 */
28
class Entity {
29

    
30
  protected $entityType;
31
  protected $entityInfo;
32
  protected $idKey, $nameKey, $statusKey;
33
  protected $defaultLabel = FALSE;
34
  protected $wrapper;
35

    
36
  /**
37
   * Creates a new entity.
38
   *
39
   * @see entity_create()
40
   */
41
  public function __construct(array $values = array(), $entityType = NULL) {
42
    if (empty($entityType)) {
43
      throw new Exception('Cannot create an instance of Entity without a specified entity type.');
44
    }
45
    $this->entityType = $entityType;
46
    $this->setUp();
47
    // Set initial values.
48
    foreach ($values as $key => $value) {
49
      $this->$key = $value;
50
    }
51
  }
52

    
53
  /**
54
   * Set up the object instance on construction or unserializiation.
55
   */
56
  protected function setUp() {
57
    $this->entityInfo = entity_get_info($this->entityType);
58
    $this->idKey = $this->entityInfo['entity keys']['id'];
59
    $this->nameKey = isset($this->entityInfo['entity keys']['name']) ? $this->entityInfo['entity keys']['name'] : $this->idKey;
60
    $this->statusKey = empty($this->entityInfo['entity keys']['status']) ? 'status' : $this->entityInfo['entity keys']['status'];
61
  }
62

    
63
  /**
64
   * Returns the internal, numeric identifier.
65
   *
66
   * Returns the numeric identifier, even if the entity type has specified a
67
   * name key. In the latter case, the numeric identifier is supposed to be used
68
   * when dealing generically with entities or internally to refer to an entity,
69
   * i.e. in a relational database. If unsure, use Entity:identifier().
70
   */
71
  public function internalIdentifier() {
72
    return isset($this->{$this->idKey}) ? $this->{$this->idKey} : NULL;
73
  }
74

    
75
  /**
76
   * Returns the entity identifier, i.e. the entities name or numeric id.
77
   *
78
   * @return
79
   *   The identifier of the entity. If the entity type makes use of a name key,
80
   *   the name is returned, else the numeric id.
81
   *
82
   * @see entity_id()
83
   */
84
  public function identifier() {
85
    return isset($this->{$this->nameKey}) ? $this->{$this->nameKey} : NULL;
86
  }
87

    
88
  /**
89
   * Returns the info of the type of the entity.
90
   *
91
   * @see entity_get_info()
92
   */
93
  public function entityInfo() {
94
    return $this->entityInfo;
95
  }
96

    
97
  /**
98
   * Returns the type of the entity.
99
   */
100
  public function entityType() {
101
    return $this->entityType;
102
  }
103

    
104
  /**
105
   * Returns the bundle of the entity.
106
   *
107
   * @return
108
   *   The bundle of the entity. Defaults to the entity type if the entity type
109
   *   does not make use of different bundles.
110
   */
111
  public function bundle() {
112
    return !empty($this->entityInfo['entity keys']['bundle']) ? $this->{$this->entityInfo['entity keys']['bundle']} : $this->entityType;
113
  }
114

    
115
  /**
116
   * Returns the EntityMetadataWrapper of the entity.
117
   *
118
   * @return EntityDrupalWrapper
119
   *   An EntityMetadataWrapper containing the entity.
120
   */
121
  public function wrapper() {
122
    if (empty($this->wrapper)) {
123
      $this->wrapper = entity_metadata_wrapper($this->entityType, $this);
124
    }
125
    elseif ($this->wrapper->value() !== $this) {
126
      // Wrapper has been modified outside, so let's better create a new one.
127
      $this->wrapper = entity_metadata_wrapper($this->entityType, $this);
128
    }
129
    return $this->wrapper;
130
  }
131

    
132
  /**
133
   * Returns the label of the entity.
134
   *
135
   * Modules may alter the label by specifying another 'label callback' using
136
   * hook_entity_info_alter().
137
   *
138
   * @see entity_label()
139
   */
140
  public function label() {
141
    // If the default label flag is enabled, this is being invoked recursively.
142
    // In this case we need to use our default label callback directly. This may
143
    // happen if a module provides a label callback implementation different
144
    // from ours, but then invokes Entity::label() or entity_class_label() from
145
    // there.
146
    if ($this->defaultLabel || (isset($this->entityInfo['label callback']) && $this->entityInfo['label callback'] == 'entity_class_label')) {
147
      return $this->defaultLabel();
148
    }
149
    $this->defaultLabel = TRUE;
150
    $label = entity_label($this->entityType, $this);
151
    $this->defaultLabel = FALSE;
152
    return $label;
153
  }
154

    
155
  /**
156
   * Defines the entity label if the 'entity_class_label' callback is used.
157
   *
158
   * Specify 'entity_class_label' as 'label callback' in hook_entity_info() to
159
   * let the entity label point to this method. Override this in order to
160
   * implement a custom default label.
161
   */
162
  protected function defaultLabel() {
163
    // Add in the translated specified label property.
164
    return $this->getTranslation($this->entityInfo['entity keys']['label']);
165
  }
166

    
167
  /**
168
   * Returns the uri of the entity just as entity_uri().
169
   *
170
   * Modules may alter the uri by specifying another 'uri callback' using
171
   * hook_entity_info_alter().
172
   *
173
   * @see entity_uri()
174
   */
175
  public function uri() {
176
    if (isset($this->entityInfo['uri callback']) && $this->entityInfo['uri callback'] == 'entity_class_uri') {
177
      return $this->defaultUri();
178
    }
179
    return entity_uri($this->entityType, $this);
180
  }
181

    
182
  /**
183
   * Override this in order to implement a custom default URI and specify
184
   * 'entity_class_uri' as 'uri callback' hook_entity_info().
185
   */
186
  protected function defaultUri() {
187
    return array('path' => 'default/' . $this->identifier());
188
  }
189

    
190
  /**
191
   * Checks if the entity has a certain exportable status.
192
   *
193
   * @param $status
194
   *   A status constant, i.e. one of ENTITY_CUSTOM, ENTITY_IN_CODE,
195
   *   ENTITY_OVERRIDDEN or ENTITY_FIXED.
196
   *
197
   * @return
198
   *   For exportable entities TRUE if the entity has the status, else FALSE.
199
   *   In case the entity is not exportable, NULL is returned.
200
   *
201
   * @see entity_has_status()
202
   */
203
  public function hasStatus($status) {
204
    if (!empty($this->entityInfo['exportable'])) {
205
      return isset($this->{$this->statusKey}) && ($this->{$this->statusKey} & $status) == $status;
206
    }
207
  }
208

    
209
  /**
210
   * Permanently saves the entity.
211
   *
212
   * @see entity_save()
213
   */
214
  public function save() {
215
    return entity_get_controller($this->entityType)->save($this);
216
  }
217

    
218
  /**
219
   * Permanently deletes the entity.
220
   *
221
   * @see entity_delete()
222
   */
223
  public function delete() {
224
    $id = $this->identifier();
225
    if (isset($id)) {
226
      entity_get_controller($this->entityType)->delete(array($id));
227
    }
228
  }
229

    
230
  /**
231
   * Exports the entity.
232
   *
233
   * @see entity_export()
234
   */
235
  public function export($prefix = '') {
236
    return entity_get_controller($this->entityType)->export($this, $prefix);
237
  }
238

    
239
  /**
240
   * Generate an array for rendering the entity.
241
   *
242
   * @see entity_view()
243
   */
244
  public function view($view_mode = 'full', $langcode = NULL, $page = NULL) {
245
    return entity_get_controller($this->entityType)->view(array($this), $view_mode, $langcode, $page);
246
  }
247

    
248
  /**
249
   * Builds a structured array representing the entity's content.
250
   *
251
   * @see entity_build_content()
252
   */
253
  public function buildContent($view_mode = 'full', $langcode = NULL) {
254
    return entity_get_controller($this->entityType)->buildContent($this, $view_mode, $langcode);
255
  }
256

    
257
  /**
258
   * Gets the raw, translated value of a property or field.
259
   *
260
   * Supports retrieving field translations as well as i18n string translations.
261
   *
262
   * Note that this returns raw data values, which might not reflect what
263
   * has been declared for hook_entity_property_info() as no 'getter callbacks'
264
   * are invoked or no referenced entities are loaded. For retrieving values
265
   * reflecting the property info make use of entity metadata wrappers, see
266
   * entity_metadata_wrapper().
267
   *
268
   * @param $property_name
269
   *   The name of the property to return; e.g., 'title'.
270
   * @param $langcode
271
   *   (optional) The language code of the language to which the value should
272
   *   be translated. If set to NULL, the default display language is being
273
   *   used.
274
   *
275
   * @return
276
   *   The raw, translated property value; or the raw, un-translated value if no
277
   *   translation is available.
278
   *
279
   * @todo Implement an analogous setTranslation() method for updating.
280
   */
281
  public function getTranslation($property, $langcode = NULL) {
282
    $all_info = entity_get_all_property_info($this->entityType);
283
    // Assign by reference to avoid triggering notices if metadata is missing.
284
    $property_info = &$all_info[$property];
285

    
286
    if (!empty($property_info['translatable'])) {
287
      if (!empty($property_info['field'])) {
288
        return field_get_items($this->entityType, $this, $property, $langcode);
289
      }
290
      elseif (!empty($property_info['i18n string'])) {
291
        $name = $this->entityInfo['module'] . ':' . $this->entityType . ':' . $this->identifier() . ':' . $property;
292
        return entity_i18n_string($name, $this->$property, $langcode);
293
      }
294
    }
295
    return $this->$property;
296
  }
297

    
298
  /**
299
   * Checks whether the entity is the default revision.
300
   *
301
   * @return Boolean
302
   *
303
   * @see entity_revision_is_default()
304
   */
305
  public function isDefaultRevision() {
306
    if (!empty($this->entityInfo['entity keys']['revision'])) {
307
      $key = !empty($this->entityInfo['entity keys']['default revision']) ? $this->entityInfo['entity keys']['default revision'] : 'default_revision';
308
      return !empty($this->$key);
309
    }
310
    return TRUE;
311
  }
312

    
313
  /**
314
   * Magic method to only serialize what's necessary.
315
   */
316
  public function __sleep() {
317
    $vars = get_object_vars($this);
318
    unset($vars['entityInfo'], $vars['idKey'], $vars['nameKey'], $vars['statusKey']);
319
    // Also key the returned array with the variable names so the method may
320
    // be easily overridden and customized.
321
    return drupal_map_assoc(array_keys($vars));
322
  }
323

    
324
  /**
325
   * Magic method to invoke setUp() on unserialization.
326
   */
327
  public function __wakeup() {
328
    $this->setUp();
329
  }
330
}
331

    
332
/**
333
 * These classes are deprecated by "Entity" and are only here for backward
334
 * compatibility reasons.
335
 */
336
class EntityDB extends Entity {}
337
class EntityExtendable extends Entity {}
338
class EntityDBExtendable extends Entity {}