/
class.NodeClassRegistry.php
176 lines (152 loc) · 3.52 KB
/
class.NodeClassRegistry.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
<?php
/**
* Factory for child classes of Node.
* Although the type of node is not needed
* to be provided to the factory, this is
* not an abstract factory - the object
* returned will be an instance of the child
* class, not an interface over the abstract
* node class.
*
* To be visible, a class extending node
* must implement the 'MachineName' annotation. 'MachineName'
* requires providing the Drupal "machine name" as
* a parameter.
*/
class NodeClassRegistry {
/**
* Id that any registry data will be cached under
*/
const DOODAL_CACHE_ID = 'doodal:node_registry';
/**
* Attempts to construct a node-extended object from a node id.
* Will look through all known classes with the annotation tag 'MachineName'.
*
* If not able to construct an object, returns NULL.
*
* @access public
* @static
* @param mixed $nid Node ID of the node to construct.
* @return mixed
*/
public static function init_class($nid) {
$node = $nid && strlen($nid) ? node_load($nid) : NULL;
if($node) {
##
## Initialize/get node registry
$registry = self::init_registry();
##
## Return instantiated class if properly annotated, else NULL
if (array_key_exists($node->type, $registry)){
return new $registry[$node->type]($node);
} else {
return NULL;
}
} else {
return NULL;
}
}
/**
* Returns an associative array of classes known to extend Node.
* Pulls this array from cache if available - if not, generates
* and caches it.
*
* Class names are keyed on their machine name.
*
* @access private
* @static
* @return array
*/
private static function init_registry() {
$cache = cache_get(self::DOODAL_CACHE_ID);
##
## Attempt to get registry from cache
if ($cache && !empty($cache->data)) {
return $cache->data;
}
##
## Generate node registry, cache, and return
else {
##
## Load all classes registered for autoloading not in an ignored (i.e. system) module
$results = db_query(
"SELECT name FROM {registry} WHERE type = 'class' AND module != '' AND module NOT IN (:modules) ORDER BY name",
array(':modules' => self::get_ignored_modules())
)->fetchAll();
##
## Get subset of classes marked as "node"
$registry = array();
foreach ($results as $result) {
$reflectedClass = new ReflectionAnnotatedClass($result->name);
if ($reflectedClass->hasAnnotation('MachineName')) {
$registry[$reflectedClass->getAnnotation('MachineName')->value] = $result->name;
}
}
##
## Cache results and return
cache_set(self::DOODAL_CACHE_ID, $registry, 'cache', CACHE_PERMANENT);
return $registry;
}
}
/**
* Returns an array of modules which should not be checked for classes extending Node.
* This is mostly system modules.
*
* @access private
* @static
* @return array
*/
private static function get_ignored_modules() {
return array(
'aggregator',
'block',
'blog',
'book',
'color',
'comment',
'contact',
'contextual',
'dashboard',
'dblog',
'field',
'field_sql_storage',
'field_ui',
'file',
'filter',
'forum',
'help',
'image',
'list',
'locale',
'menu',
'node',
'number',
'openid',
'options',
'overlay',
'path',
'php',
'poll',
'profile',
'rdf',
'search',
'shortcut',
'simpletest',
'statistics',
'standard',
'syslog',
'system',
'taxonomy',
'testing',
'text',
'toolbar',
'tracker',
'translation',
'trigger',
'update',
'user',
'doodal'
);
}
}
?>