TypedEntityManager.php 5.14 KB
Newer Older
Mateu Aguiló Bosch's avatar
Mateu Aguiló Bosch committed
1
2
3
4
5
6
7
8
9
<?php

/**
 * @file
 * Contains \Drupal\typed_entity\TypedEntity\TypedEntityManager.
 */

namespace Drupal\typed_entity\TypedEntity;

10
11
use Drupal\xautoload\DrupalSystem\DrupalSystemInterface;

Mateu Aguiló Bosch's avatar
Mateu Aguiló Bosch committed
12
13
class TypedEntityManager implements TypedEntityManagerInterface {

14
15
16
17
18
19
20
  /**
   * Drupal system wrapper.
   *
   * @var DrupalSystemInterface
   */
  protected static $system;

Mateu Aguiló Bosch's avatar
Mateu Aguiló Bosch committed
21
22
23
24
  /**
   * {@inheritdoc}
   */
  public static function create($entity_type, $entity) {
25
    static::$system = xautoload()->getServiceContainer()->get('system');
26
    $class_name = static::getClass($entity_type, $entity);
27
    return new $class_name($entity_type, NULL, $entity);
Mateu Aguiló Bosch's avatar
Mateu Aguiló Bosch committed
28
  }
29

30
31
  /**
   * Helper function to get a class name given an entity type and an entity.
32
   *
33
34
35
36
   * @param string $entity_type
   *   The entity type
   * @param object $entity
   *   The entity object.
37
38
39
   *
   * @return string
   *   A valid class name if one exists. It defaults to TypedEntity.
40
   */
41
  public static function getClass($entity_type, $entity) {
Mateu Aguiló Bosch's avatar
Mateu Aguiló Bosch committed
42
    $classes = &drupal_static(__METHOD__);
Mateu Aguiló Bosch's avatar
Mateu Aguiló Bosch committed
43
    list(,, $bundle) = entity_extract_ids($entity_type, $entity);
Mateu Aguiló Bosch's avatar
Mateu Aguiló Bosch committed
44
    $cid = $entity_type . ':' . $bundle;
45

Mateu Aguiló Bosch's avatar
Mateu Aguiló Bosch committed
46
47
    if (isset($classes[$cid])) {
      return $classes[$cid];
48
    }
49

Mateu Aguiló Bosch's avatar
Mateu Aguiló Bosch committed
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
    $cached_classes = array();
    if ($cache = cache_get('typed_entity_classes', 'cache_bootstrap')) {
      $cached_classes = $cache->data;
    }

    $classes = array_merge($cached_classes, isset($classes) ? $classes : array());
    if (isset($classes[$cid])) {
      return $classes[$cid];
    }

    // The default class should always be TypedEntity. Assume that TypedEntity
    // is under the same namespace as TypedEntityManager.
    $classes[$cid] = '\\' . __NAMESPACE__ . '\\TypedEntity';
    $candidates = static::getClassNameCandidates($entity_type, $bundle);
    foreach ($candidates as $candidate) {
      if (class_exists($candidate)) {
        $classes[$cid] = $candidate;
        break;
68
69
      }
    }
Mateu Aguiló Bosch's avatar
Mateu Aguiló Bosch committed
70
    cache_set('typed_entity_classes', $classes, 'cache_bootstrap');
71

72
73
    return $classes[$cid];
  }
Mateu Aguiló Bosch's avatar
Mateu Aguiló Bosch committed
74
75

  /**
76
   * Helper function to get possible class names given entity type & bundle.
Mateu Aguiló Bosch's avatar
Mateu Aguiló Bosch committed
77
78
79
80
81
82
83
84
   *
   * If you want your entity types to be auto loaded then you need to place your
   * class in your custom module, under src/TypedEntity. The class needs to be
   * named Typed<EntityTypeCamelCase> or
   * Typed<EntityTypeCamelCase><BundleCamelCase>. For instance TypedNodeArticle.
   *
   * @param string $entity_type
   *   The type of the entity.
85
86
   * @param string $bundle
   *   The bundle of the entity.
Mateu Aguiló Bosch's avatar
Mateu Aguiló Bosch committed
87
88
89
90
   *
   * @return array
   *   An array of class name candidates.
   */
Mateu Aguiló Bosch's avatar
Mateu Aguiló Bosch committed
91
  protected static function getClassNameCandidates($entity_type, $bundle = NULL) {
92
93
94
    $candidates = module_invoke_all('typed_entity_registry_info');
    $candidate_entity_type = $candidate_bundle = '';
    foreach ($candidates as $candidate) {
95
96
97
98
      if ($candidate['entity_type'] != $entity_type) {
        continue;
      }
      if (empty($candidate['bundle'])) {
99
100
        $candidate_entity_type = $candidate['class'];
      }
Mateu Aguiló Bosch's avatar
Mateu Aguiló Bosch committed
101
      if (!empty($candidate['bundle']) && $candidate['bundle'] == $bundle) {
102
103
104
        $candidate_bundle = $candidate['class'];
      }
    }
Mateu Aguiló Bosch's avatar
Mateu Aguiló Bosch committed
105
    $names = array();
106
107
108

    // First add the specific suggestions for bundles. It is important to add
    // the most specific first.
109
110
    if (!empty($candidate_bundle)) {
      $names[] = $candidate_bundle;
111
    }
Mateu Aguiló Bosch's avatar
Mateu Aguiló Bosch committed
112
    $names = array_merge($names, static::getClassNameCandidatesBundle($entity_type, $bundle));
113
114
115
116

    // Then add the generic ones for entity types.
    if (!empty($candidate_entity_type)) {
      $names[] = $candidate_entity_type;
Mateu Aguiló Bosch's avatar
Mateu Aguiló Bosch committed
117
    }
Mateu Aguiló Bosch's avatar
Mateu Aguiló Bosch committed
118
    $names = array_merge($names, static::getClassNameCandidatesEntity($entity_type));
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134

    return $names;
  }

  /**
   * Helper function to get possible class names given entity type & bundle.
   *
   * @param string $entity_type
   *   The type of the entity.
   *
   * @return array
   *   An array of class name candidates.
   */
  protected static function getClassNameCandidatesEntity($entity_type) {
    $names = array();
    $class_name_entity_type = 'Typed' . static::camelize($entity_type);
135
    foreach (static::$system->moduleList() as $module_name) {
136
137
138
      $names[] = '\\Drupal\\' . $module_name . '\\TypedEntity\\' . $class_name_entity_type;
    }

Mateu Aguiló Bosch's avatar
Mateu Aguiló Bosch committed
139
140
141
    return $names;
  }

142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
  /**
   * Helper function to get possible class names given entity type & bundle.
   *
   * @param string $entity_type
   *   The type of the entity.
   * @param string $bundle
   *   The bundle of the entity.
   *
   * @return array
   *   An array of class name candidates.
   */
  protected static function getClassNameCandidatesBundle($entity_type, $bundle) {
    $names = array();

    if (empty($bundle)) {
      return $names;
    }
    $class_name_bundle = 'Typed' . static::camelize($entity_type) . static::camelize($bundle);
160
    foreach (static::$system->moduleList() as $module_name) {
161
162
163
164
165
166
      $names[] = '\\Drupal\\' . $module_name . '\\TypedEntity\\' . $class_name_bundle;
    }

    return $names;
  }

Mateu Aguiló Bosch's avatar
Mateu Aguiló Bosch committed
167
  /**
168
   * {@inheritdoc}
Mateu Aguiló Bosch's avatar
Mateu Aguiló Bosch committed
169
   */
170
  public static function camelize($input) {
Mateu Aguiló Bosch's avatar
Mateu Aguiló Bosch committed
171
    $input = preg_replace('/[-_]/', ' ', $input);
Mateu Aguiló Bosch's avatar
Mateu Aguiló Bosch committed
172
    $input = ucwords($input);
Mateu Aguiló Bosch's avatar
Mateu Aguiló Bosch committed
173
    $parts = explode(' ', $input);
Mateu Aguiló Bosch's avatar
Mateu Aguiló Bosch committed
174
175
176
177
    return implode('', $parts);
  }

}