/[drupal]/contributions/modules/uc_node_access/uc_node_access.module
ViewVC logotype

Contents of /contributions/modules/uc_node_access/uc_node_access.module

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


Revision 1.1 - (show annotations) (download) (as text)
Fri Jun 27 18:21:27 2008 UTC (17 months ago) by rszrama
Branch: MAIN
CVS Tags: DRUPAL-5--1-0, HEAD
Branch point for: DRUPAL-5, DRUPAL-6--1
File MIME type: text/x-php
Initial commit of UC Node Access; creates a product feature that lets you grant customers access to view nodes through a product purchase.  Includes a handler to integrate UC Node Access with ACL + Content Access.
1 <?php
2 // $Id$
3
4 /**
5 * @file
6 * Defines a node access product feature that grants customers access to nodes
7 * on your site upon order completion.
8 *
9 * Sponsored by Flat World Knowledge - http://www.flatworldknowledge.com
10 */
11
12 /**
13 * Implementation of hook_menu().
14 */
15 function uc_node_access_menu($may_cache) {
16 $items = array();
17
18 if ($may_cache) {
19 $items[] = array(
20 'path' => 'uc_node_access/autocomplete',
21 'title' => t('UC Node Access autocomplete'),
22 'callback' => 'uc_node_access_autocomplete',
23 'access' => user_access('administer product features'),
24 'type' => MENU_CALLBACK,
25 );
26 }
27
28 return $items;
29 }
30
31 /**
32 * Implementation of hook_cron().
33 */
34 function uc_node_access_cron() {
35 $items = array();
36
37 // Load and process any expired node access rules.
38 $result = db_query("SELECT uid, access_nid FROM {uc_node_access_expirations} WHERE expiration <= %d", time());
39 while ($access = db_fetch_array($result)) {
40 // Revoke access for the user through the current node access handler.
41 uc_node_access_op('revoke', $access['access_nid'], $access['uid']);
42
43 // Delete the expiration from the database.
44 db_query("DELETE FROM {uc_node_access_expirations} WHERE uid = %d AND access_nid = %d", $access['uid'], $access['access_nid']);
45
46 $items[] = t('User @uid lost access to <a href="!url">node @nid</a>.', array('@uid' => $access['uid'], '@nid' => $access['access_nid'], '!url' => url('node/'. $access['access_nid'])));
47 }
48
49 if (!empty($items)) {
50 watchdog('uc_node_access', t('The following expirations occurred:') . theme('item_list', $items));
51 }
52 }
53
54 /**
55 * Implementation of hook_product_feature().
56 */
57 function uc_node_access_product_feature() {
58 $features[] = array(
59 'id' => 'node_access',
60 'title' => t('Node access'),
61 'callback' => 'uc_node_access_feature_form',
62 'delete' => 'uc_node_access_feature_delete',
63 'settings' => 'uc_node_access_feature_settings_form',
64 );
65
66 return $features;
67 }
68
69 // Display the settings form for the node access product feature.
70 function uc_node_access_feature_form($node, $feature) {
71 $handler = variable_get('ucna_handler', '');
72
73 // Throw up a warning if the handler hasn't been selected yet.
74 if (empty($handler) || !function_exists($handler)) {
75 drupal_set_message(t('The node access handler is either not specified or missing. Node access features can be added to products but cannot be processed until this is resolved.'), 'error');
76 }
77
78 drupal_add_css(drupal_get_path('module', 'uc_node_access') .'/uc_node_access.css');
79
80 if (!empty($feature)) {
81 $access = uc_node_access_feature_load($feature['pfid']);
82 }
83
84 $options = array('' => t('<Any>'), $node->model => $node->model);
85 if (module_exists('uc_attribute')) {
86 $result = db_query("SELECT model FROM {uc_product_adjustments} WHERE nid = %d", $node->nid);
87 while ($row = db_fetch_object($result)) {
88 if (!in_array($row->model, $options)) {
89 $options[$row->model] = $row->model;
90 }
91 }
92 }
93 $form['model'] = array(
94 '#type' => 'select',
95 '#title' => t('Applicable Model/SKU'),
96 '#description' => t('Select the applicable product model/SKU.'),
97 '#options' => $options,
98 '#default_value' => $access['model'],
99 );
100
101 $form['access_nid'] = array(
102 '#type' => 'textfield',
103 '#title' => t('Node ID'),
104 '#description' => t('Specify the node the customer will get access to after purchasing this product.<br />Start typing in a node title to view an autocomplete list that will change to an nid upon selection.'),
105 '#default_value' => $access['access_nid'],
106 '#autocomplete_path' => 'uc_node_access/autocomplete',
107 '#required' => TRUE,
108 );
109
110 $form['access_limit'] = array(
111 '#type' => 'radios',
112 '#title' => t('Access limit type'),
113 '#description' => t('Select an access limit type to govern how long the customer will have access to the node.'),
114 '#options' => array(
115 'indefinite' => t('The customer can have indefinite access to the node.'),
116 'time_period' => t('The customer can access the node for the time specified below.'),
117 'end_date' => t('The customer can access the node until the date specified below.'),
118 ),
119 '#default_value' => $access['access_limit'],
120 '#required' => TRUE,
121 );
122
123 $form['time_period'] = array(
124 '#type' => 'fieldset',
125 '#title' => t('Access time period'),
126 '#collapsible' => FALSE,
127 '#description' => t('Specify the length of time the customer should have access to the node.'),
128 '#attributes' => array('class' => 'time-period-fieldset'),
129 );
130 $form['time_period']['time_period_value'] = array(
131 '#type' => 'select',
132 '#options' => drupal_map_assoc(uc_range(1, 52)),
133 '#default_value' => $access['time_period_value'],
134 );
135 $form['time_period']['time_period_unit'] = array(
136 '#type' => 'select',
137 '#options' => array(
138 'days' => t('day(s)'),
139 'weeks' => t('week(s)'),
140 'months' => t('month(s)'),
141 'years' => t('year(s)'),
142 ),
143 '#default_value' => $access['time_period_unit'],
144 );
145
146 $form['end_date_fieldset'] = array(
147 '#type' => 'fieldset',
148 '#title' => t('Access end date'),
149 '#collapsible' => FALSE,
150 '#description' => t('Specify the end date on which a customer will lose access to the node.'),
151 );
152 $form['end_date_fieldset']['end_date'] = array(
153 '#type' => 'date',
154 '#default_value' => $access['end_date']
155 );
156
157 return uc_product_feature_form($form);
158 }
159
160 function uc_node_access_feature_form_submit($form_id, $form_values) {
161 if (empty($form_values['pfid'])) {
162 $access['pfid'] = db_next_id('{uc_product_features}_pfid');
163 }
164 else {
165 $access['pfid'] = $form_values['pfid'];
166 }
167
168 $access = array(
169 'pfid' => $access['pfid'],
170 'model' => $form_values['model'],
171 'access_nid' => $form_values['access_nid'],
172 'access_limit' => $form_values['access_limit'],
173 'time_period' => $form_values['time_period_value'] .' '. $form_values['time_period_unit'],
174 'end_date' => $form_values['end_date'],
175 );
176 uc_node_access_feature_save($access);
177
178 switch ($form_values['access_limit']) {
179 case 'time_period':
180 $description = t('Grant access to <a href="!url">node @nid</a> for @period.', array('@nid' => $access['access_nid'], '@period' => $access['time_period'], '!url' => url('node/'. $access['access_nid'])));
181 break;
182 case 'end_date':
183 $description = t('Grant access to <a href="!url">node @nid</a> until @date.', array('@nid' => $access['access_nid'], '@date' => $access['end_date']['month'] .'/'. $access['end_date']['day'] .'/'. $access['end_date']['year'], '!url' => url('node/'. $access['access_nid'])));
184 break;
185 case 'indefinite':
186 default:
187 $description = t('Grant indefinite access to <a href="!url">node @nid</a>.', array('@nid' => $access['access_nid'], '!url' => url('node/'. $access['access_nid'])));
188 break;
189 }
190
191 if (!empty($access['model'])) {
192 $description .= '<br />'. t('Applies to SKU: @sku', array('@sku' => $access['model']));
193 }
194 else {
195 $description .= '<br />'. t('Applies to any SKU.');
196 }
197
198 $data = array(
199 'pfid' => $access['pfid'],
200 'nid' => $form_values['nid'],
201 'fid' => 'node_access',
202 'description' => $description,
203 );
204
205 return uc_product_feature_save($data);
206 }
207
208 // Adds the fields for this feature in the product features settings form.
209 function uc_node_access_feature_settings_form() {
210 $options = array();
211
212 $handlers = module_invoke_all('ucna_handler');
213 foreach ($handlers as $handler) {
214 $options[$handler['callback']] = $handler['title'];
215 }
216
217 if (empty($options)) {
218 $options[''] = t('No handlers available. You must install one to use this feature.');
219 }
220
221 $form['ucna_handler'] = array(
222 '#type' => 'radios',
223 '#title' => t('Node access handler'),
224 '#description' => t('Node access features are processed using handlers that integrate UC Node Access with other access control modules.<br />You must select one in order to start using this feature.'),
225 '#options' => $options,
226 '#default_value' => variable_get('ucna_handler', ''),
227 );
228
229 return $form;
230 }
231
232 function uc_node_access_feature_save($data) {
233 // First attempt to update an existing row.
234 db_query("UPDATE {uc_node_access_products} SET model = '%s', access_nid = %d, access_limit = '%s', time_period = '%s', end_date = '%s' WHERE pfid = %d",
235 $data['model'], $data['access_nid'], $data['access_limit'], $data['time_period'], serialize($data['end_date']), $data['pfid']);
236
237 // Otherwise insert this feature as a new row.
238 if (db_affected_rows() == 0) {
239 db_query("INSERT INTO {uc_node_access_products} (pfid, model, access_nid, access_limit, time_period, end_date) VALUES (%d, '%s', %d, '%s', '%s', '%s')",
240 $data['pfid'], $data['model'], $data['access_nid'], $data['access_limit'], $data['time_period'], serialize($data['end_date']));
241 }
242 }
243
244 function uc_node_access_feature_load($pfid) {
245 $access = db_fetch_array(db_query("SELECT nap.*, pf.nid FROM {uc_node_access_products} AS nap LEFT JOIN {uc_product_features} AS pf ON nap.pfid = pf.pfid WHERE nap.pfid = %d", $pfid));
246 if (!empty($access)) {
247 list($access['time_period_value'], $access['time_period_unit']) = explode(' ', $access['time_period']);
248 $access['end_date'] = unserialize($access['end_date']);
249 }
250
251 return $access;
252 }
253
254 function uc_node_access_feature_delete($feature) {
255 db_query("DELETE FROM {uc_node_access_products} WHERE pfid = %d", $feature['pfid']);
256 }
257
258 function uc_node_access_op($op, $nid, $uid) {
259 $handler = variable_get('ucna_handler', '');
260
261 // Fail if the handler hasn't been specified or has been uninstalled.
262 if (empty($handler) || !function_exists($handler)) {
263 watchdog('uc_node_access', t('The node access handler is either not specified or missing. Node access features cannot be processed until this is resolved.'), WATCHDOG_WARNING);
264 return;
265 }
266
267 // Fail if we receive an invalid nid or uid.
268 if (intval($nid) <= 0 || intval($uid) <= 0) {
269 watchdog('uc_node_access', t('Invalid arguments passed to UC Node Access for processing.'), WATCHDOG_WARNING);
270 return;
271 }
272
273 // Pass the arguments onto the handler for processing.
274 $result = $handler($op, $nid, $uid);
275
276 // Log failed node access operations.
277 if ($result === FALSE) {
278 watchdog('uc_node_access', t('A node access operation failed! $op = @op, $nid = @nid, $uid = @uid', array('@op' => $op, '@nid' => $nid, '@uid' => $uid)), WATCHDOG_WARNING);
279 }
280 }
281
282 function uc_node_access_grant_user_access($pfid, $uid) {
283 // Load up the node access feature and target node data.
284 $access = uc_node_access_feature_load($pfid);
285 $node = node_load($access['access_nid']);
286
287 if (empty($access) || empty($node) || $uid == 0) {
288 return;
289 }
290
291 // Grant access for the user through the current node access handler.
292 uc_node_access_op('grant', $access['access_nid'], $uid);
293
294 // Let Drupal know to adjust the access for the target node.
295 node_access_acquire_grants($node);
296
297 // Calculate an expiration timestamp based on the site's timezone.
298 $expiration = FALSE;
299
300 switch ($access['access_limit']) {
301 case 'time_period':
302 $expiration = strtotime('+'. $access['time_period']);
303 break;
304 case 'end_date':
305 $expiration = gmmktime(0, 0, 0, $access['end_date']['month'], $access['end_date']['day'], $access['end_date']['year']);
306 break;
307 }
308
309 // Set the expiration in the DB if necessary.
310 if ($expiration) {
311 // Get a prior expiration if one exists.
312 $result = db_result(db_query("SELECT expiration FROM {uc_node_access_expirations} WHERE uid = %d AND access_nid = %d", $uid, $access['access_nid']));
313
314 // If there was no prior expiration, insert a new one.
315 if (empty($result)) {
316 db_query("INSERT INTO {uc_node_access_expirations} (uid, access_nid, expiration) VALUES (%d, %d, %d)",
317 $uid, $access['access_nid'], $expiration);
318 watchdog('uc_node_access', t('User @uid granted access to node @nid until @date.', array('@uid' => $uid, '@nid' => $access['access_nid'], '@date' => format_date($expiration, 'custom', 'm/d/Y'))));
319 }
320 else if ($result < $expiration) {
321 // Otherwise we need to update the expiration to be later.
322 db_query("UPDATE {uc_node_access_expirations} SET expiration = %d WHERE uid = %d AND access_nid = %d", $expiration, $uid, $access['access_nid']);
323 watchdog('uc_node_access', t('User @uid extended access for node @nid until @date.', array('@uid' => $uid, '@nid' => $access['access_nid'], '@date' => format_date($expiration, 'custom', 'm/d/Y'))));
324 }
325 else {
326 watchdog('uc_node_access', t('User @uid purchased duplicate access for node @nid that expires earlier than their current access.', array('@uid' => $uid, '@nid' => $access['access_nid'], '@date' => format_date($expiration, 'custom', 'm/d/Y'))));
327 }
328 }
329 else {
330 // Delete any prior expiration reference.
331 db_query("DELETE FROM {uc_node_access_expirations} WHERE uid = %d AND access_nid = %d", $uid, $access['access_nid']);
332
333 watchdog('uc_node_access', t('User @uid granted indefinite access to node @nid.', array('@uid' => $uid, '@nid' => $access['access_nid'])));
334 }
335 }
336
337 // Returns an autocomplete list for nodes on the node access feature form.
338 function uc_node_access_autocomplete($string = '') {
339 $matches = array();
340
341 if ($string) {
342 $result = db_query_range("SELECT nid, title FROM {node} WHERE LOWER(title) LIKE LOWER('%s%%')", $string, 0, 10);
343 while ($node = db_fetch_object($result)) {
344 $matches[$node->nid] = check_plain($node->title);
345 }
346 }
347
348 print drupal_to_js($matches);
349 exit();
350 }
351
352
353 /*******************************************************************************
354 * Workflow-ng Integration
355 ******************************************************************************/
356
357 function uc_node_access_configuration() {
358 $configurations['uc_node_access_grant_on_payment'] = array(
359 '#type' => 'configuration',
360 '#label' => t('Grant appropriate node access on full payment'),
361 '#event' => 'payment_entered',
362 '#module' => 'uc_node_access',
363 '#active' => TRUE,
364 );
365 $configurations['uc_node_access_grant_on_payment'][] = array(
366 '#type' => 'condition',
367 '#name' => 'uc_payment_condition_balance',
368 '#argument map' => array(
369 'order' => 'order',
370 ),
371 '#settings' => array(
372 'balance_comparison' => 'less_equal',
373 ),
374 );
375 $configurations['uc_node_access_grant_on_payment'][] = array(
376 '#type' => 'action',
377 '#name' => 'uc_node_access_grant_access',
378 '#argument map' => array(
379 'order' => 'order',
380 ),
381 );
382
383 return $configurations;
384 }
385
386 function uc_node_access_action_info() {
387 $actions['uc_node_access_grant_access'] = array(
388 '#label' => t('Grant node access to customer'),
389 '#arguments' => array(
390 'order' => array('#entity' => 'order', '#label' => t('Order')),
391 ),
392 '#module' => t('UC Node Access'),
393 );
394
395 return $actions;
396 }
397
398 function uc_node_access_grant_access($order, $settings) {
399 if (is_array($order->products)) {
400 $nids = array();
401 $models = array();
402
403 foreach ($order->products as $product) {
404 $nids[] = $product->nid;
405 $models[] = $product->model;
406 }
407
408 $result = db_query("SELECT pf.pfid, nap.model FROM {uc_product_features} AS pf LEFT JOIN {uc_node_access_products} AS nap ON pf.pfid = nap.pfid WHERE pf.nid IN (". implode(", ", $nids) .") AND pf.fid = 'node_access'");
409 while ($row = db_fetch_array($result)) {
410 if (empty($row['model']) || in_array($row['model'], $models)) {
411 uc_node_access_grant_user_access($row['pfid'], $order->uid);
412 }
413 }
414 }
415 }

  ViewVC Help
Powered by ViewVC 1.1.2