/[drupal]/contributions/modules/rpg/inc/rpg.invoke.inc
ViewVC logotype

Contents of /contributions/modules/rpg/inc/rpg.invoke.inc

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.6 - (show annotations) (download) (as text)
Sat Mar 8 00:31:04 2008 UTC (20 months, 3 weeks ago) by aaron
Branch: MAIN
CVS Tags: HEAD
Changes since 1.5: +5 -7 lines
File MIME type: text/x-php
fix character creation process, so it correctly selects the character
change object insertion so it uses rpg_set instead of _rpg_set_raw
1 <?php
2 // $Id: rpg.invoke.inc,v 1.4 2007/11/30 20:02:02 aaron Exp $
3
4 /**
5 * Return an array of installed .inc files and/or loads them upon request.
6 * This routine is modeled after drupal_system_listing() (and also depends on it).
7 * It's major difference, however, is that it loads .inc files by default.
8 *
9 * @param $type
10 * Optional; name of the passed object type to find (e.g. "room", "human", etc.).
11 * @param $load
12 * Defaults to true; whether to include matching files into memory.
13 * @return
14 * An array of file objects optionally matching $type.
15 */
16 function rpg_system_list($type = NULL, $load = true) {
17 $files = drupal_system_listing("$type\.inc", drupal_get_path('module', 'rpg')."/types", 'name', 0);
18
19 ksort($files);
20
21 if ($load) {
22 foreach ($files as $file) {
23 rpg_include_list($file);
24 }
25 }
26
27 return $files;
28 }
29
30 /**
31 * Maintains a list of all loaded include files.
32 *
33 * @param $file
34 * Optional; a file object (from rpg_system_list()) to be included.
35 * @return
36 * An array of all loaded includes (without the .inc extension).
37 */
38 function rpg_include_list($file = NULL) {
39 static $list = array();
40
41 // if (!$list) { $list = array(); }
42
43 if ($file && !isset($list[$file->name])) {
44 include_once('./'.$file->filename);
45 $list[$file->name] = $file->name;
46 }
47
48 return $list;
49 }
50
51 /**
52 * Determine whether an include implements a hook, cf. module_hook.
53 *
54 * @param $type
55 * The name of the object type file (without the .inc extension), such as 'tangible' or 'room'.
56 * @param $hook
57 * The name of the hook (e.g. "settings", "info", etc.).
58 * @return
59 * TRUE if the provider is loaded and the hook is implemented.
60 */
61 function rpg_include_hook($type, $hook) {
62 return function_exists('rpg_' . $type .'_'. $hook);
63 }
64
65 /**
66 * Invoke a hook for an object. This will call the hook for all the types & parent types of the object.
67 * Returns the result. Object may be modified in the process.
68 * Note that this should rarely (if ever) called, except during object creation, when we don't have an rid yet
69 * and the object is not yet in the global $rpg system
70 * @param &$object
71 * The object to invoke the hook
72 * @param $hook
73 * The hook to call
74 * @param $args
75 * Any optional or required args to pass to the hook
76 * @return
77 * The return value from the hook, which may be modified at various places (as $pass)
78 */
79 function rpg_invoke_object(&$object) {
80 $args = func_get_args();
81 // remove $object, since it's passed as a reference
82 array_shift($args);
83 // $hook is used explicitly in our call later, but we don't care about the rest of the args
84 $hook = array_shift($args);
85 $pass = NULL;
86 foreach (_rpg_invoke_object_types_order($object) as $type) {
87 $function = 'rpg_' . $type . '_' . $hook;
88 rpg_system_list($type);
89 $pass = rpg_include_hook($type, $hook) ? call_user_func_array($function, array(&$object, $pass, $args)) : $pass;
90 }
91 return $pass;
92 }
93
94 /**
95 * helper function for rpg_invoke:
96 * this returns the order that types for an object should be invoked, which will be in ascending order of depth
97 * for instance, if an object is a door, with a hypothetical type structure of door (exit -- tangible,
98 * lockable -- openable -- tangible)
99 * its order of invocation would be tangible, exit, openable, lockable, door
100 * @param $object
101 * the rpg object being tested
102 * @param $cached
103 * optional; if set to the default of true, results will be fetched from the cache and stored in a static array
104 * we would need to call it with false if we changed the types of an object. in that rare case, you'll need to
105 * call this function manually before rpg_invoke
106 * @return
107 * an array of strings, being a flattened array of types to invoke in order of invocation
108 */
109 function _rpg_invoke_object_types_order($object, $cached = true) {
110 static $types = array();
111 if (!isset($object->rid) || !isset($types[$object->rid]) || !$cached) {
112 if ($object->rid && $cached && $cache = cache_get('_rpg_invoke_object_types_order:' . $object->rid, 'cache_rpg')) {
113 $types[$object->rid] = unserialize($cache->data);
114 }
115 else {
116 $depth = 0;
117 $object_types = array();
118 foreach ((array)$object->types as $type) {
119 $object_types[$depth][] = $type;
120 _rpg_invoke_type_populate_ancestors(rpg_types($type), $object_types, $depth);
121 }
122 krsort($object_types);
123 $object_types = array_unique(_rpg_invoke_array_flatten($object_types));
124 if ($object->rid) {
125 $types[$object->rid] = $object_types;
126 cache_set('_rpg_invoke_object_types_order:' . $object->rid, 'cache_rpg', serialize($types[$object->rid]));
127 } else {
128 return $object_types;
129 }
130 }
131 }
132 return $types[$object->rid];
133 }
134
135 function _rpg_invoke_type_types_order($type, $reset = false, $provided_types = NULL) {
136 static $types = array();
137 if (!isset($types[$type['type']]) || $reset) {
138 if ($type['type'] && !$reset && $cache = cache_get('_rpg_invoke_type_types_order:' . $type['type'], 'cache_rpg')) {
139 $types[$type['type']] = unserialize($cache->data);
140 }
141 else {
142 $depth = 0;
143 $type_types = array();
144 if (is_array($type['parents'])) {
145 foreach ($type['parents'] as $ancestor) {
146 $type_types[$depth][] = $ancestor;
147 if (!$reset || is_null($provided_types)) {
148 $ancestor_type = rpg_types($ancestor);
149 }
150 else {
151 $ancestor_type = is_array($provided_types[$ancestor]) ? $provided_types[$ancestor] : array();
152 }
153 _rpg_invoke_type_populate_ancestors($ancestor_type, $type_types, $depth, $provided_types);
154 }
155 }
156 krsort($type_types);
157 $type_types = array_unique(_rpg_invoke_array_flatten($type_types));
158 $types[$type['type']] = $type_types;
159 cache_set('_rpg_invoke_object_types_order:' . $type['type'], 'cache_rpg', serialize($types[$type['type']]));
160 }
161 }
162 return $types[$type['type']];
163 }
164
165 /**
166 * this is a helper function for rpg_invoke. it recursively creates a type ancestor tree for a specific object, modifying
167 * the &$types array appropriately
168 * @param $type
169 * the type to return an ancestor tree for
170 * @param &$types
171 * the tree array to recursively modify
172 * @param $depth
173 * the depth of the tree array to fill in
174 */
175 function _rpg_invoke_type_populate_ancestors($type, &$types, $depth = -1, $provided_types = NULL) {
176 $depth++;
177 if (is_array($type['parents'])) {
178 foreach ($type['parents'] as $parent) {
179 $types[$depth][$parent] = $parent;
180 if (is_null($provided_types)) {
181 $ancestor_type = rpg_types($parent);
182 }
183 else {
184 $ancestor_type = is_array($provided_types[$parent]) ? $provided_types[$parent] : array();
185 }
186 _rpg_invoke_type_populate_ancestors($ancestor_type, $types, $depth, $provided_types);
187 }
188 }
189 }
190
191 /**
192 * a helper function for rpg_invoke. this returns a flattened multidimensional array
193 */
194 function _rpg_invoke_array_flatten($array) {
195 $tmp = array();
196 while (($v = array_shift($array)) !== null) {
197 if (is_array($v)) {
198 $array = array_merge($v, $array);
199 } else {
200 $tmp[] = $v;
201 }
202 }
203 return $tmp;
204 }
205
206 /**
207 * TODO: is this depcrated?
208 * return an array of all ancestor types for an object, ordered by inheritance
209 * for instance, if an object has types=array('human', 'wizard'), the types returned might be
210 * array('human', 'race', 'actor', 'tangible', 'wizard', 'classed')
211 * while just 'wizard' might return array('wizard', 'classed', 'actor', 'tangible')
212 * @param $object
213 * The object to return all types for
214 * @param $force
215 * Optional. If true, then force a refresh of the otherwise static result
216 * @return
217 * An array of keyed types, ordered by precendence
218 */
219 function rpg_object_all_types($object, $force = false) {
220 static $types;
221 if (!isset($types)) {
222 $types = array();
223 }
224 if (!isset($types[$object->rid]) || $force) {
225 foreach ($object->types as $type) {
226 $types[$object->rid][$type] = $type;
227 foreach (rpg_type_ancestors($type) as $parent) {
228 $types[$object->rid][$parent] = $parent;
229 }
230 }
231 }
232 return $types[$object->rid];
233 }
234
235 /**
236 * @file
237 * these are helper functions that control invoking hooks in rpg object types
238 */
239
240 /**
241 * Invoke hook in a particular include.
242 *
243 * @param $type
244 * The name of the provider (without the .inc extension).
245 * @param $hook
246 * The name of the hook (e.g. "info", "extends", etc.).
247 * @param ...
248 * Arguments to pass to the hook implementation.
249 * @return
250 * The return value of the hook implementation.
251 */
252 function rpg_include_invoke() {
253 $args = func_get_args();
254 $type = array_shift($args);
255 $hook = array_shift($args);
256 $function = 'rpg_' . $type . '_' . $hook;
257 rpg_system_list($type);
258 return rpg_include_hook($type, $hook) ? call_user_func_array($function, $args) : NULL;
259 }
260
261

  ViewVC Help
Powered by ViewVC 1.1.2