/[drupal]/contributions/modules/votingapi/votingapi_actions.module
ViewVC logotype

Contents of /contributions/modules/votingapi/votingapi_actions.module

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


Revision 1.8 - (show annotations) (download) (as text)
Sat Oct 14 02:01:43 2006 UTC (3 years, 1 month ago) by eaton
Branch: MAIN
CVS Tags: DRUPAL-5--1-2, HEAD
Branch point for: DRUPAL-5
Changes since 1.7: +322 -272 lines
File MIME type: text/x-php
Hooray for Drupal 5. Views integration is no longer inherent to the module; votingapi_views.module will be coming shortly.
1 <?php
2 // $Id: votingapi_actions.module,v 1.7 2006/09/27 03:20:18 eaton Exp $
3
4 /**
5 * Lets users directly control the votingapi's integration with the actions module.
6 */
7
8 /**
9 * Implementation of hook_perm().
10 */
11 function votingapi_actions_perm() {
12 return array('administer voting actions');
13 }
14
15 /*
16 * Implementation of hook_menu()
17 */
18 function votingapi_actions_menu($may_cache) {
19 $items = array();
20 require_once('votingapi_actions.inc');
21 require_once('votingapi_actions_ui.inc');
22
23 if ($may_cache) {
24 $items[] = array('path' => 'admin/voting/actions',
25 'title' => t('voting actions'),
26 'description' => t('Vote-driven triggers and actions for your site'),
27 'callback' => 'votingapi_actions_admin_page',
28 'access' => user_access('administer voting actions'),
29 'type' => MENU_NORMAL_ITEM);
30 $items[] = array('path' => 'admin/voting/actions/list',
31 'title' => t('list'),
32 'callback' => 'votingapi_actions_admin_page',
33 'access' => user_access('administer voting actions'),
34 'type' => MENU_DEFAULT_LOCAL_TASK,
35 'weight' => '-1');
36 $items[] = array('path' => 'admin/voting/actions/add',
37 'title' => t('add'),
38 'callback' => 'drupal_get_form',
39 'callback arguments' => array('votingapi_actions_admin_edit_page', 'add'),
40 'access' => user_access('administer voting actions'),
41 'type' => MENU_LOCAL_TASK);
42 $items[] = array('path' => 'admin/voting/actions/edit',
43 'title' => t('edit action set'),
44 'callback' => 'drupal_get_form',
45 'callback arguments' => array('votingapi_actions_admin_edit_page', 'edit'),
46 'type' => MENU_CALLBACK);
47 $items[] = array('path' => 'admin/voting/actions/import',
48 'title' => t('import'),
49 'callback' => 'drupal_get_form',
50 'callback arguments' => array('votingapi_actions_admin_import_page'),
51 'access' => user_access('administer voting actions'),
52 'type' => MENU_LOCAL_TASK);
53 $items[] = array('path' => 'admin/voting/actions/export',
54 'title' => t('export action set'),
55 'callback' => 'drupal_get_form',
56 'callback arguments' => array('votingapi_actions_admin_export_page'),
57 'access' => user_access('administer voting actions'),
58 'type' => MENU_CALLBACK);
59 $items[] = array('path' => 'admin/voting/actions/delete',
60 'title' => t('edit action set'),
61 'callback' => 'drupal_get_form',
62 'callback arguments' => array('votingapi_actions_admin_delete_page'),
63 'access' => user_access('administer voting actions'),
64 'type' => MENU_CALLBACK);
65 $items[] = array('path' => 'admin/voting/actions/enable',
66 'callback' => 'votingapi_actions_admin_enable_page',
67 'access' => user_access('administer voting actions'),
68 'type' => MENU_CALLBACK);
69 $items[] = array('path' => 'admin/voting/actions/disable',
70 'callback' => 'votingapi_actions_admin_disable_page',
71 'access' => user_access('administer voting actions'),
72 'type' => MENU_CALLBACK);
73 }
74 return $items;
75 }
76
77 function votingapi_actions_votingapi_recalculate($cached, $votes, $content_type, $content_id) {
78 _votingapi_process_actions($content_id, $content_type, $votes, $cached);
79 }
80
81 /**
82 * Functions that integrate VotingAPI with the Actions module.
83 * Allows VotingAPI-based modules to insert nested sets of conditionals
84 * and actions to be executed whenever a voting result is fired off.
85 */
86
87 // Called by the Voting API whenever a result is calculated.
88 // Other helper functions build the actions cache from the database.
89
90 function _votingapi_process_actions($content_id, $content_type, $votes, $results) {
91 $data = cache_get('votingapi_action_sets');
92 $action_sets = unserialize($data->data);
93
94 if (!is_array($action_sets)) {
95 return;
96 }
97
98 $content = _votingapi_load_content($content_id, $content_type);
99 if ($content == NULL) {
100 return;
101 }
102
103 foreach ($action_sets as $action_set) {
104 if ($action_set['content_type'] == $content_type) {
105 $actions = array();
106 _votingapi_process_action_set($content, $votes, $results, $action_set, $actions);
107 foreach ($actions as $action) {
108 actions_do($action, $content);
109 }
110 }
111 }
112 }
113
114 // An internal utility function that calls itself recursively to evaluate a
115 // tree of voting action sets. $actions is passed in by references, and accumulates
116 // actions-to-initiate. The calling function is responsible for firing them off.
117
118 function _votingapi_process_action_set($content = NULL, $votes = array(), $results = array(), $action_set = NULL, &$actions) {
119 // a little safety code to catch malformed sets.
120 if (!isset($action_set['conditions'])) {
121 $action_set['conditions'] = array();
122 }
123 if (!isset($action_set['actions'])) {
124 $action_set['actions'] = array();
125 }
126 if (!isset($action_set['subsets'])) {
127 $action_set['subsets'] = array();
128 }
129
130 // Here, we iterate through every rule. The value starts as true,
131 // and a single false will trip it to failure state.
132 foreach($action_set['conditions'] as $condition) {
133 $function = $condition['handler'];
134 if (function_exists($function)) {
135 // this calls a handler with several ops. 'process' and 'input' are the two i've thought of.
136 $conditions_result = $function('process', $content, $votes, $results, $condition);
137 }
138 else {
139 $conditions_result = FALSE;
140 }
141 if ($action_set['condition_mask'] == 'AND') {
142 if ($conditions_result === FALSE) {
143 // bail out to avoid unecessary processing.
144 return FALSE;
145 }
146 else {
147 // AND the set result and rule result together.
148 if (isset($set_result)) {
149 $set_result = $set_result && $conditions_result;
150 }
151 else {
152 $set_result = $conditions_result;
153 }
154 }
155 }
156 else if ($action_set['condition_mask'] == 'OR') {
157 // OR the set result and rule result together.
158 $set_result = $set_result || $conditions_result;
159 }
160 }
161
162 if ($set_result == TRUE) {
163 // Now check sub-actions.
164
165 foreach($action_set['subsets'] as $subset) {
166 // check the required flag of the subset. if it is, evaluate it.
167 if ($subset['required'] == TRUE) {
168 $set_result = $set_result && _votingapi_process_action_set($content, $votes, $results, $subset, $actions);
169 if ($set_result == FALSE) {
170 return FALSE;
171 }
172 }
173 }
174
175 if ($set_result == TRUE) {
176 // It's still true after executing required subsets. Add the actions, then process optional subsets.
177 foreach ($action_set['actions'] as $action) {
178 $actions[] = $action;
179 }
180
181 foreach($action_set['subsets'] as $subset) {
182 // now handle the non-required subsets
183 if ($subset['required'] == FALSE) {
184 _votingapi_process_action_set($content, $votes, $results, $subset, $actions);
185 }
186 }
187 }
188 }
189
190 return $set_result;
191 }
192
193 /**
194 * Utility functions that manage the raw voting actions data..
195 */
196
197 function votingapi_rebuild_action_cache() {
198 // This builds a live cache of all the currently enabled sets,
199 // first from the database, then from module 'defaults'. Any
200 // set saved in the DB is assumed to be enabled, and any DB
201 // set overrides a module set with the same name.
202
203 $sets = _votingapi_load_action_sets_from_db();
204 $module_sets = _votingapi_load_action_sets_from_modules();
205
206 foreach($sets as $name => $set) {
207 $active_sets[$name] = $set;
208 }
209
210 $status_list = variable_get('votingapi_action_status', array());
211 foreach($module_sets as $name => $set) {
212 if (!in_array($name, array_keys($sets))) {
213 if ($status_list[$name]) {
214 $sets[$name] = $set;
215 }
216 }
217 }
218 cache_set("votingapi_action_sets", 'cache', serialize($sets));
219 }
220
221 function _votingapi_get_action_status($set_name) {
222 $status_list = variable_get('votingapi_action_status', array());
223 return $status_list[$set_name];
224 }
225
226 function _votingapi_set_action_status($set_name, $status) {
227 $status_list = variable_get('votingapi_action_status', array());
228 $status_list[$set_name] = $status;
229 variable_set('votingapi_action_status', $status_list);
230 votingapi_rebuild_action_cache();
231 }
232
233 function _votingapi_load_action_sets_from_modules() {
234 $sets = array();
235 $status_list = variable_get('votingapi_action_status', array());
236
237 $set_data = module_invoke_all('votingapi_action_sets');
238 foreach ($set_data as $name => $set) {
239 $sets[$name] = $set;
240 if (!isset($status_list[$name])) {
241 $status_list[$name] = $set['enabled'];
242 }
243 }
244
245 variable_set('votingapi_action_status', $status_list);
246 return $sets;
247 }
248
249 function _votingapi_load_action_sets_from_db($parent = '') {
250 $sets = array();
251 $result = db_query("SELECT * FROM {votingapi_action_set} WHERE parent_name = '%s' ORDER BY weight, name ASC", $parent);
252
253 while ($set = db_fetch_array($result)) {
254 $set_name = $set['name'];
255 unset($set['name']);
256
257 $condition_result = db_query("SELECT * FROM {votingapi_action_condition} WHERE parent_name = '%s' ORDER BY weight ASC", $set_name);
258 while ($condition = db_fetch_array($condition_result)) {
259 $condition['data'] = unserialize($condition['data']);
260 $name = $condition['name'];
261 unset($condition['name']);
262 $set['conditions'][$name] = $condition;
263 }
264
265 $action_result = db_query("SELECT * FROM {votingapi_action} WHERE parent_name = '%s' ORDER BY aid ASC", $set_name);
266 while ($action = db_fetch_array($action_result)) {
267 $set['actions'][] = $action['aid'];
268 }
269
270 $set->subsets = _votingapi_load_action_sets_from_db($set_name);
271 $sets[$set_name] = $set;
272 }
273
274 return $sets;
275 }
276
277 function _votingapi_insert_set($name, $set) {
278 $sql = "INSERT INTO {votingapi_action_set} ";
279 $sql .= "(name, parent_name, content_type, source, description, condition_mask, required, weight)";
280 $sql .= "VALUES ('%s', '%s', '%s', '%s', '%s', '%s', %d, %d)";
281
282 db_query($sql, $name, $set['parent_name'], $set['content_type'],
283 $set['source'], $set['description'], $set['condition_mask'],
284 $set['required'], $set['weight']);
285
286 if (is_array($set['conditions'])) {
287 foreach ($set['conditions'] as $cname => $condition) {
288 $condition['parent_name'] = $name;
289 _votingapi_insert_condition($cname, $condition);
290 }
291 }
292
293 if (is_array($set['actions'])) {
294 foreach ($set['actions'] as $action) {
295 db_query("INSERT INTO {votingapi_action} (parent_name, aid) VALUES ('%s', '%s')", $name, $action);
296 }
297 }
298
299 if (is_array($set['sets'])) {
300 foreach ($set['sets'] as $sname => $subset) {
301 $subset['parent_name'] = $name;
302 _votingapi_insert_set($sname, $subset);
303 }
304 }
305 }
306
307 function _votingapi_insert_condition($name, $condition) {
308 $sql = "INSERT INTO {votingapi_action_condition} ";
309 $sql .= "(name, parent_name, description, data, handler, weight)";
310 $sql .= "VALUES ('%s', '%s', '%s', '%s', '%s', %d)";
311
312 db_query($sql, $name, $condition['parent_name'], $condition['description'],
313 serialize($condition['data']), $condition['handler'], $condition['weight']);
314 }
315
316 function _votingapi_update_set($name, $old_name, $set) {
317 $sql = "UPDATE {votingapi_action_set} SET ";
318 $sql .= "name = '%s', parent_name = '%s', content_type = '%s', source = '%s', description = '%s', condition_mask = '%s', ";
319 $sql .= "required = %d, weight = %d ";
320 $sql .= "WHERE name = '%s'";
321
322 db_query($sql, $name, $set['parent_name'], $set['content_type'],
323 $set['source'], $set['description'], $set['condition_mask'],
324 $set['required'], $set['weight'], $old_name);
325
326 db_query("DELETE FROM {votingapi_action_condition} WHERE parent_name = '%s'", $old_name);
327 if (is_array($set['conditions'])) {
328 foreach ($set['conditions'] as $cname => $condition) {
329 $condition['parent_name'] = $name;
330 _votingapi_insert_condition($cname, $condition);
331 }
332 }
333
334 db_query("DELETE FROM {votingapi_action} WHERE parent_name = '%s'", $old_name);
335 if (is_array($set['actions'])) {
336 foreach ($set['actions'] as $action) {
337 db_query("INSERT INTO {votingapi_action} (parent_name, aid) VALUES ('%s', '%s')", $name, $action);
338 }
339 }
340
341 if (is_array($set['sets'])) {
342 foreach ($set['sets'] as $sname => $subset) {
343 $subset['parent_name'] = $name;
344 if ($subset['new']) {
345 _votingapi_insert_set($sname , $subset);
346 }
347 else {
348 _votingapi_update_set($sname , $subset);
349 }
350 }
351 }
352
353 if (is_array($set['deleted_sets'])) {
354 foreach ($set['deleted_sets'] as $sname => $subset) {
355 $subset['parent_name'] = $name;
356 _votingapi_delete_set($sname , $subset);
357 }
358 }
359 }
360
361 function _votingapi_update_condition($name, $condition) {
362 $sql = "UPDATE {votingapi_action_condition} SET ";
363 $sql .= "name = '%s', parent_name = '%s', description = '%s', data = '%s', handler = '%s', weight = %d ";
364 $sql .= "WHERE name = '%s' AND parent_name = '%s'";
365
366 db_query($sql, $name, $condition['parent_name'], $condition['description'],
367 serialize($condition['data']), $condition['handler'], $condition['weight'],
368 $name, $condition['parent_name']);
369 }
370
371 function _votingapi_delete_set($name, $set) {
372 if (is_array($set['sets'])) {
373 foreach ($set['sets'] as $sname => $subset) {
374 $subset['parent_name'] = $name;
375 _votingapi_delete_set($sname, $subset);
376 }
377 }
378
379 db_query("DELETE FROM {votingapi_action_condition} WHERE parent_name = '%s'", $name);
380 db_query("DELETE FROM {votingapi_action} WHERE parent_name = '%s'", $name);
381 db_query("DELETE FROM {votingapi_action_set} WHERE name = '%s'", $name);
382 }
383
384 function _votingapi_validate_action_set($name, $set) {
385 $errors = array();
386
387 if (!is_array($set)) {
388 $errors[] = "The set '$name' is not an array!";
389 return $errors;
390 }
391
392 if (!isset($set['content_type']) && !isset($set['parent_name'])) {
393 $errors[] = "The set '$name' must have a content_type.";
394 }
395
396 if ($set['condition_mask'] != 'AND' && $set['condition_mask'] != 'OR') {
397 $errors[] = "The set '$name' must define a condition_mask of 'AND' or 'OR'.";
398 }
399
400 if (!isset($set['conditions'])) {
401 $errors[] = "The set '$name' has no conditions defined.";
402 }
403 else {
404 if (count($set['conditions']) == 0) {
405 $errors[] = "The set '$name' has no conditions defined.";
406 }
407 }
408
409 if (is_array($set['conditions'])) {
410 foreach ($set['conditions'] as $cname => $condition) {
411 $errors = array_merge($errors, _votingapi_validate_action_condition($cname, $condition));
412 }
413 }
414
415 if (is_array($set['sets'])) {
416 foreach ($set['sets'] as $subname => $subset) {
417 $errors = array_merge($errors, _votingapi_validate_action_set($subname, $subset));
418 }
419 }
420 return $errors;
421 }
422
423 function _votingapi_validate_action_condition($name, $condition) {
424 $errors = array();
425 if (!is_array($condition)) {
426 $errors[] = "The condition '$name' is not an array!";
427 return $errors;
428 }
429
430 if (!isset($condition['handler'])) {
431 $errors[] = "The condition '$name' has no handler.";
432 }
433
434 if (!function_exists($condition['handler'])) {
435 $handler = $condition['handler'];
436 $errors[] = "The condition '$name' has an invalid handler ($handler).";
437 }
438
439 return $errors;
440 }

  ViewVC Help
Powered by ViewVC 1.1.2