| 1 |
<?php
|
| 2 |
// $Id: subscriptions.module,v 1.88 2009/07/20 21:22:21 salvis Exp $
|
| 3 |
|
| 4 |
/**
|
| 5 |
* @mainpage Subscriptions module
|
| 6 |
*
|
| 7 |
* This module enables users to subscribe to be notified of changes to nodes or
|
| 8 |
* taxonomies, such as new comments in specific forums, or additions to some
|
| 9 |
* category of blog. Once enabled, all nodes will have an additional link that
|
| 10 |
* allows the user to change their subscriptions. Users get a tab on their user
|
| 11 |
* page to manage their own subscriptions. Users can also set an auto-subscribe
|
| 12 |
* function which notifies the user if anyone comments on posts they have made.
|
| 13 |
* Admins can turn this on by default.
|
| 14 |
*/
|
| 15 |
|
| 16 |
/**
|
| 17 |
* @file
|
| 18 |
* Subscriptions module.
|
| 19 |
*/
|
| 20 |
|
| 21 |
/**
|
| 22 |
* Implementation of hook_init().
|
| 23 |
*
|
| 24 |
* @ingroup hooks
|
| 25 |
* @ingroup init
|
| 26 |
*/
|
| 27 |
function subscriptions_init() {
|
| 28 |
define('SUBSCRIPTIONS_UNAVAILABLE', '<span class="error" title="'. t('(unavailable to regular users)') .'">¤</span>');
|
| 29 |
if (arg(0) == 'subscriptions' || arg(2) == 'subscriptions') {
|
| 30 |
include_once drupal_get_path('module', 'subscriptions') .'/subscriptions.admin.inc'; // TODO: do we need this?
|
| 31 |
}
|
| 32 |
if (arg(0) == 's' && arg(1) == 'del') {
|
| 33 |
$router_item = menu_get_item('subscriptions/rem/'. substr($_GET['q'], 6));
|
| 34 |
if (isset($router_item) && $router_item['access']) {
|
| 35 |
menu_set_item($_GET['q'], $router_item);
|
| 36 |
}
|
| 37 |
}
|
| 38 |
}
|
| 39 |
|
| 40 |
/**
|
| 41 |
* Implementation of hook_menu().
|
| 42 |
*
|
| 43 |
* @ingroup hooks
|
| 44 |
* @ingroup menu
|
| 45 |
*/
|
| 46 |
function subscriptions_menu() {
|
| 47 |
global $user; // we need the user to to build some urls
|
| 48 |
|
| 49 |
$items['admin/settings/subscriptions'] = array(
|
| 50 |
'title' => 'Subscriptions',
|
| 51 |
'description' => 'Enables site settings for user subscriptions.',
|
| 52 |
'page callback' => 'drupal_get_form',
|
| 53 |
'page arguments' => array('subscriptions_settings_form'),
|
| 54 |
'access arguments' => array('administer site configuration'),
|
| 55 |
);
|
| 56 |
$items['admin/settings/subscriptions/settings'] = array(
|
| 57 |
'title' => 'Site settings',
|
| 58 |
'weight' => -10,
|
| 59 |
'type' => MENU_DEFAULT_LOCAL_TASK,
|
| 60 |
);
|
| 61 |
$items['admin/settings/subscriptions/userdefaults'] = array(
|
| 62 |
'title' => 'User defaults',
|
| 63 |
'weight' => -5,
|
| 64 |
'page callback' => 'subscriptions_page_user_overview',
|
| 65 |
'page arguments' => array(NULL),
|
| 66 |
'type' => MENU_LOCAL_TASK,
|
| 67 |
'access arguments' => array('administer site configuration'),
|
| 68 |
);
|
| 69 |
$items['admin/settings/subscriptions/userdefaults/settings'] = array(
|
| 70 |
'type' => MENU_DEFAULT_LOCAL_TASK,
|
| 71 |
'title' => 'Overview',
|
| 72 |
'weight' => -10,
|
| 73 |
);
|
| 74 |
$items['admin/settings/subscriptions/intervals'] = array(
|
| 75 |
'title' => 'Interval',
|
| 76 |
'page callback' => 'drupal_get_form',
|
| 77 |
'page arguments' => array('subscriptions_intervals'),
|
| 78 |
'type' => MENU_LOCAL_TASK,
|
| 79 |
'access arguments' => array('administer site configuration'),
|
| 80 |
);
|
| 81 |
$items['user/%user/subscriptions'] = array(
|
| 82 |
'title' => 'Subscriptions',
|
| 83 |
'page callback' => 'subscriptions_page_user_overview',
|
| 84 |
'page arguments' => array(1),
|
| 85 |
'type' => MENU_LOCAL_TASK,
|
| 86 |
'access callback' => '_subscriptions_access',
|
| 87 |
'access arguments' => array(1),
|
| 88 |
);
|
| 89 |
|
| 90 |
$hide_overview_page = variable_get('subscriptions_hide_overview_page', 0);
|
| 91 |
if (!$hide_overview_page) {
|
| 92 |
$items['user/%user/subscriptions/overview'] = array(
|
| 93 |
'type' => MENU_DEFAULT_LOCAL_TASK,
|
| 94 |
'title' => 'Overview',
|
| 95 |
'weight' => -10,
|
| 96 |
);
|
| 97 |
}
|
| 98 |
else {
|
| 99 |
$minimum_weight = 0;
|
| 100 |
foreach (subscriptions_types() as $stype => $data) {
|
| 101 |
if (isset($data['weight']) && $data['weight'] < $minimum_weight) {
|
| 102 |
$minimum_weight = $data['weight'];
|
| 103 |
}
|
| 104 |
}
|
| 105 |
}
|
| 106 |
|
| 107 |
foreach (subscriptions_types() as $stype => $data) {
|
| 108 |
$weight = (isset($data['weight']) ? $data['weight'] : 0);
|
| 109 |
$items['subscriptions/add/'. $stype] = array(
|
| 110 |
'title' => 'Add subscription',
|
| 111 |
'type' => MENU_CALLBACK,
|
| 112 |
'page callback' => 'drupal_get_form',
|
| 113 |
'page arguments' => array('subscriptions_add_form', $stype),
|
| 114 |
'access arguments' => array($data['access']),
|
| 115 |
);
|
| 116 |
$items['subscriptions/del/'. $stype] = array(
|
| 117 |
'type' => MENU_CALLBACK,
|
| 118 |
'page callback' => 'drupal_get_form',
|
| 119 |
'page arguments' => array('subscriptions_del_form', $stype),
|
| 120 |
'access arguments' => array($data['access']),
|
| 121 |
);
|
| 122 |
|
| 123 |
if (empty($data['page'])) {
|
| 124 |
continue; // no page
|
| 125 |
}
|
| 126 |
$items['user/%user/subscriptions/'. $stype] = array(
|
| 127 |
'title' => $data['title'],
|
| 128 |
'type' => MENU_LOCAL_TASK,
|
| 129 |
'file' => 'subscriptions.admin.inc',
|
| 130 |
'page callback' => 'subscriptions_page',
|
| 131 |
'page arguments' => array(1, $stype),
|
| 132 |
'access callback' => '_subscriptions_access',
|
| 133 |
'access arguments' => array(1, $data['access']),
|
| 134 |
'weight' => $weight,
|
| 135 |
);
|
| 136 |
|
| 137 |
if ($hide_overview_page && $minimum_weight == $weight) {
|
| 138 |
// Install the first subscription type page as the default task.
|
| 139 |
$items['user/%user/subscriptions/'. $stype]['type'] = MENU_DEFAULT_LOCAL_TASK;
|
| 140 |
$default_item = $items['user/%user/subscriptions/'. $stype];
|
| 141 |
$items['user/%user/subscriptions'] = array_merge($items['user/%user/subscriptions'], array(
|
| 142 |
'file' => $default_item['file'],
|
| 143 |
'page callback' => $default_item['page callback'],
|
| 144 |
'page arguments' => $default_item['page arguments'],
|
| 145 |
'access callback' => $default_item['access callback'],
|
| 146 |
'access arguments' => $default_item['access arguments'],
|
| 147 |
));
|
| 148 |
$hide_overview_page = FALSE;
|
| 149 |
}
|
| 150 |
|
| 151 |
if ($stype == 'node') {
|
| 152 |
continue; // not in site settings
|
| 153 |
}
|
| 154 |
$items['admin/settings/subscriptions/userdefaults/'. $stype] = array(
|
| 155 |
'title' => $data['title'],
|
| 156 |
'type' => MENU_LOCAL_TASK,
|
| 157 |
'file' => 'subscriptions.admin.inc',
|
| 158 |
'page callback' => 'subscriptions_page',
|
| 159 |
'page arguments' => array(NULL, $stype),
|
| 160 |
'access arguments' => array('administer site configuration'),
|
| 161 |
'weight' => $weight,
|
| 162 |
);
|
| 163 |
}
|
| 164 |
|
| 165 |
// Unsubscribe links
|
| 166 |
$items['subscriptions/rem/%'] = array(
|
| 167 |
'page callback' => 'drupal_get_form',
|
| 168 |
'page arguments' => array('subscriptions_delete_form', 2, 3, 4, 5, 6),
|
| 169 |
'type' => MENU_CALLBACK,
|
| 170 |
'access callback' => '_subscriptions_rem_access',
|
| 171 |
'access arguments' => array(2, 3, 4, 5, 6, 7),
|
| 172 |
);
|
| 173 |
return $items;
|
| 174 |
|
| 175 |
// potx fails to pick up these strings:
|
| 176 |
t('Add subscription');
|
| 177 |
t('Remove subscription');
|
| 178 |
t('Enables site settings for user subscriptions.');
|
| 179 |
t('Site settings');
|
| 180 |
t('User defaults');
|
| 181 |
t('Overview');
|
| 182 |
t('Interval');
|
| 183 |
}
|
| 184 |
|
| 185 |
function _subscriptions_rem_access($a2, $a3, $a4, $a5, $a6, $md) {
|
| 186 |
return $md == md5(drupal_get_private_key() . $a2 . $a3 . $a4 . $a5 . $a6);
|
| 187 |
}
|
| 188 |
|
| 189 |
function _subscriptions_access($account, $access = NULL) {
|
| 190 |
global $user;
|
| 191 |
if ($account && $account->uid) {
|
| 192 |
if (isset($access)) {
|
| 193 |
$has_access = user_access($access, $account);
|
| 194 |
}
|
| 195 |
else {
|
| 196 |
foreach (subscriptions_types() as $stype => $data) {
|
| 197 |
if (user_access($data['access'], $account)) {
|
| 198 |
$has_access = TRUE;
|
| 199 |
}
|
| 200 |
}
|
| 201 |
}
|
| 202 |
return !empty($has_access) && ($account->uid == $user->uid || user_access('administer user subscriptions'));
|
| 203 |
}
|
| 204 |
return FALSE;
|
| 205 |
}
|
| 206 |
|
| 207 |
/**
|
| 208 |
* Implementation of hook_perms().
|
| 209 |
*
|
| 210 |
* @ingroup hooks
|
| 211 |
*/
|
| 212 |
function subscriptions_perm() {
|
| 213 |
return array_merge(array('administer user subscriptions', 'subscribe to all content types'), subscriptions_types('access'));
|
| 214 |
t('administer user subscriptions');
|
| 215 |
t('subscribe to all content types');
|
| 216 |
}
|
| 217 |
|
| 218 |
/**
|
| 219 |
* Implementation of hook_user().
|
| 220 |
*
|
| 221 |
* @ingroup hooks
|
| 222 |
*/
|
| 223 |
function subscriptions_user($type, $edit, &$account, $category = NULL) {
|
| 224 |
static $new_uid = 0;
|
| 225 |
switch ($type) {
|
| 226 |
case 'insert':
|
| 227 |
db_query("INSERT INTO {subscriptions_user} (uid) VALUES(%d)", $account->uid);
|
| 228 |
// $account->roles isn't set yet, but we'll be called again with 'load'
|
| 229 |
$new_uid = $account->uid;
|
| 230 |
break;
|
| 231 |
|
| 232 |
case 'load':
|
| 233 |
if ($new_uid && $account->uid == $new_uid) {
|
| 234 |
foreach (array_keys($account->roles) as $rid) {
|
| 235 |
$rids[] = -$rid;
|
| 236 |
}
|
| 237 |
db_query("INSERT INTO {subscriptions} (module, field, value, recipient_uid, send_interval, author_uid, send_updates, send_comments)
|
| 238 |
SELECT module, field, value, %d, send_interval, author_uid, send_updates, send_comments FROM {subscriptions}
|
| 239 |
WHERE recipient_uid IN (%s)", $account->uid, implode(',', $rids));
|
| 240 |
$new_uid = 0;
|
| 241 |
}
|
| 242 |
break;
|
| 243 |
|
| 244 |
case 'delete':
|
| 245 |
db_query("DELETE FROM {subscriptions_user} WHERE uid = %d", $account->uid);
|
| 246 |
db_query("DELETE FROM {subscriptions} WHERE recipient_uid = %d", $account->uid);
|
| 247 |
db_query("DELETE FROM {subscriptions_last_sent} WHERE uid = %d", $account->uid);
|
| 248 |
break;
|
| 249 |
}
|
| 250 |
}
|
| 251 |
|
| 252 |
/**
|
| 253 |
* Helper function to do access checking and create a subscription.
|
| 254 |
*/
|
| 255 |
function subscriptions_write($access_key, $module, $field, $value, $author_uid = -1, $recipient = NULL, $send_interval = 1, $send_updates = 0, $send_comments = 0) {
|
| 256 |
global $user;
|
| 257 |
// Access checking
|
| 258 |
$recipient_uid = isset($recipient) ? $recipient : $user->uid;
|
| 259 |
$access = subscriptions_types('access', $access_key);
|
| 260 |
if ($recipient_uid && $access && ($recipient_uid == $user->uid && user_access($access) || user_access('administer user subscriptions')) || $recipient_uid == 0 && user_access('administer site configuration')) {
|
| 261 |
subscriptions_write_subscription($module, $field, $value, $author_uid, $recipient_uid, $send_interval, $send_updates, $send_comments);
|
| 262 |
}
|
| 263 |
}
|
| 264 |
|
| 265 |
/**
|
| 266 |
* Queue events for notifications.
|
| 267 |
*
|
| 268 |
* @param $event
|
| 269 |
* Event array.
|
| 270 |
*/
|
| 271 |
function subscriptions_queue($event) {
|
| 272 |
global $user;
|
| 273 |
|
| 274 |
if (isset($event['node']->nid) && strpos(' '. variable_get('subscriptions_blocked_nodes', '') .' ', ' '. $event['node']->nid .' ')) {
|
| 275 |
return;
|
| 276 |
}
|
| 277 |
|
| 278 |
$event += array(
|
| 279 |
'uid' => $user->uid,
|
| 280 |
'load_args' => '',
|
| 281 |
);
|
| 282 |
|
| 283 |
foreach (module_implements('subscriptions_queue_alter') as $module) {
|
| 284 |
$function = $module .'_subscriptions_queue_alter';
|
| 285 |
$function($event);
|
| 286 |
if (empty($event)) {
|
| 287 |
return; // $event was cleared, forget it
|
| 288 |
}
|
| 289 |
}
|
| 290 |
|
| 291 |
if (is_array($event['load_args'])) {
|
| 292 |
$event['load_args'] = serialize($event['load_args']);
|
| 293 |
}
|
| 294 |
if (!empty($event['noqueue_uids'])) {
|
| 295 |
// Allow hook_subscriptions_queue_alter() modules to set uids that won't get any notifications queued:
|
| 296 |
$noqueue_uids_where = "s.recipient_uid NOT IN (". implode(', ', array_fill(0, count($event['noqueue_uids']), '%d')) .")";
|
| 297 |
}
|
| 298 |
|
| 299 |
foreach (module_implements('subscriptions') as $subs_module) {
|
| 300 |
$subs_module_query = module_invoke($subs_module, 'subscriptions', 'queue', $event);
|
| 301 |
if (!isset($subs_module_query)) {
|
| 302 |
continue;
|
| 303 |
}
|
| 304 |
foreach ($subs_module_query as $module => $module_query) {
|
| 305 |
foreach ($module_query as $field => $query) {
|
| 306 |
$join = empty($query['join']) ? '' : $query['join'];
|
| 307 |
$where = empty($query['where']) ? array() : array($query['where']);
|
| 308 |
$args = array($event['load_function'], $event['load_args'], $event['is_new'], $module, $field);
|
| 309 |
// author-specific subscriptions trigger on comments, when the node author is subscribed to:
|
| 310 |
$args[] = ($module == 'node' && $event['type'] == 'comment' && isset($event['node']->uid) ? $event['node']->uid : $event['uid']);
|
| 311 |
if (!empty($query['value'])) {
|
| 312 |
$where[] = "s.value = '%s'";
|
| 313 |
$args[] = $query['value'];
|
| 314 |
}
|
| 315 |
if (!empty($query['args'])) {
|
| 316 |
$args = array_merge($args, $query['args']);
|
| 317 |
}
|
| 318 |
if ($user->uid && !_subscriptions_get_setting('send_self', $user)) {
|
| 319 |
$where[] = "s.recipient_uid != %d";
|
| 320 |
$args[] = $user->uid;
|
| 321 |
}
|
| 322 |
if (!empty($event['noqueue_uids'])) {
|
| 323 |
$where[] = $noqueue_uids_where;
|
| 324 |
$args = array_merge($args, $event['noqueue_uids']);
|
| 325 |
}
|
| 326 |
$conditions = implode(' AND ', $where);
|
| 327 |
$sql = "
|
| 328 |
INSERT INTO {subscriptions_queue} (uid, name, mail, language, module, field, value, author_uid, send_interval, digest, last_sent, load_function, load_args, is_new)
|
| 329 |
SELECT u.uid, u.name, u.mail, u.language, s.module, s.field, s.value, s.author_uid, s.send_interval, su.digest, COALESCE(sls.last_sent, 0), '%s', '%s', '%d'
|
| 330 |
FROM {subscriptions} s
|
| 331 |
INNER JOIN {subscriptions_user} su ON s.recipient_uid = su.uid
|
| 332 |
INNER JOIN {users} u ON su.uid = u.uid
|
| 333 |
$join
|
| 334 |
LEFT JOIN {subscriptions_last_sent} sls ON su.uid = sls.uid AND s.send_interval = sls.send_interval
|
| 335 |
WHERE
|
| 336 |
s.module = '%s' AND
|
| 337 |
s.field = '%s' AND
|
| 338 |
s.author_uid IN (%d, -1) AND $conditions";
|
| 339 |
$result = db_query($sql, $args);
|
| 340 |
$affected_rows = db_affected_rows();
|
| 341 |
/* for debugging:
|
| 342 |
$sql = db_prefix_tables($sql);
|
| 343 |
_db_query_callback($args, TRUE);
|
| 344 |
$sql = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $sql);
|
| 345 |
drupal_set_message("$sql<br />". $affected_rows .' row(s) inserted.');
|
| 346 |
/**/
|
| 347 |
}
|
| 348 |
}
|
| 349 |
}
|
| 350 |
}
|
| 351 |
|
| 352 |
/**
|
| 353 |
* Get subscription sid for the given parameters.
|
| 354 |
*/
|
| 355 |
function subscriptions_get_subscription($uid, $module, $field, $value, $author_uid = -1) {
|
| 356 |
static $subscriptions;
|
| 357 |
|
| 358 |
if (!isset($subscriptions[$uid][$module][$field][$value][$author_uid])) {
|
| 359 |
$sql = "SELECT sid FROM {subscriptions} WHERE module = '%s' AND field = '%s' AND value = '%s' AND author_uid = %d AND recipient_uid = %d";
|
| 360 |
$subscriptions[$uid][$module][$field][$value][$author_uid] = db_result(db_query($sql, $module, $field, $value, $author_uid, $uid));
|
| 361 |
}
|
| 362 |
|
| 363 |
return $subscriptions[$uid][$module][$field][$value][$author_uid];
|
| 364 |
}
|
| 365 |
|
| 366 |
/**
|
| 367 |
* Get all subscription fields for the given parameters.
|
| 368 |
*/
|
| 369 |
function subscriptions_get_full_subscription($uid, $module, $field, $value, $author_uid = -1) {
|
| 370 |
$sql = "SELECT * FROM {subscriptions} WHERE module = '%s' AND field = '%s' AND value = '%s' AND author_uid = %d AND recipient_uid = %d";
|
| 371 |
return db_fetch_object(db_query($sql, $module, $field, $value, $author_uid, $uid));
|
| 372 |
}
|
| 373 |
|
| 374 |
/**
|
| 375 |
* Create a subscription.
|
| 376 |
*/
|
| 377 |
function subscriptions_write_subscription($module, $field, $value, $author_uid, $recipient_uid, $send_interval = 1, $send_updates = 0, $send_comments = 0) {
|
| 378 |
db_query("UPDATE {subscriptions} SET send_interval = %d, send_updates = %d, send_comments = %d WHERE module = '%s' AND field ='%s' AND value='%s' AND recipient_uid = %d AND author_uid = %d", $send_interval, $send_updates, $send_comments, $module, $field, $value, $recipient_uid, $author_uid);
|
| 379 |
if (!db_affected_rows()) {
|
| 380 |
@db_query("INSERT INTO {subscriptions} (module, field, value, author_uid, recipient_uid, send_interval, send_updates, send_comments) VALUES ('%s', '%s', '%s', %d, %d, %d, %d, %d)", $module, $field, $value, $author_uid, $recipient_uid, $send_interval, $send_updates, $send_comments);
|
| 381 |
}
|
| 382 |
}
|
| 383 |
|
| 384 |
/**
|
| 385 |
* Provide the form definition for deleting subscriptions via
|
| 386 |
* s/del/... (aka subscriptions/rem/...) link.
|
| 387 |
*
|
| 388 |
* Callback of _subscriptions_menu().
|
| 389 |
*
|
| 390 |
* @param $form_state
|
| 391 |
* FAPI form state.
|
| 392 |
* @param $module
|
| 393 |
* Module that controls the subscription.
|
| 394 |
* @param $field
|
| 395 |
* Field that controls the subscription (subscription type).
|
| 396 |
* @param $value
|
| 397 |
* Subscription parameter (depends on type).
|
| 398 |
* @param $author_uid
|
| 399 |
* User ID for author-specific subscriptions or -1/NULL for all authors.
|
| 400 |
* @param $recipient_uid
|
| 401 |
* User ID of the subscriber.
|
| 402 |
*
|
| 403 |
* @ingroup forms
|
| 404 |
* @see _subscriptions_menu()
|
| 405 |
*/
|
| 406 |
function subscriptions_delete_form(&$form_state, $module, $field, $value, $author_uid, $recipient_uid) {
|
| 407 |
$form['data'] = array('#type' => 'value', '#value' => array($module, $field, $value, $author_uid, $recipient_uid));
|
| 408 |
// We might be called from subscriptions_del_form() and don't want to submit to subscriptions_del_form_submit():
|
| 409 |
$form['#submit'][] = 'subscriptions_delete_form_submit';
|
| 410 |
return confirm_form($form, t('Are you sure you want to unsubscribe?'), '<front>', NULL, t('Unsubscribe'));
|
| 411 |
}
|
| 412 |
|
| 413 |
/**
|
| 414 |
* Delete Subscription form submit handler.
|
| 415 |
*/
|
| 416 |
function subscriptions_delete_form_submit($form, &$form_state) {
|
| 417 |
db_query("DELETE FROM {subscriptions} WHERE module = '%s' AND field = '%s' AND value = '%s' AND author_uid = %d AND recipient_uid = %d", $form_state['values']['data']);
|
| 418 |
drupal_set_message(t('Your subscription was deactivated.'));
|
| 419 |
$form_state['redirect'] = '<front>';
|
| 420 |
}
|
| 421 |
|
| 422 |
/**
|
| 423 |
* Subscribe users to content they post, if not already subscribed
|
| 424 |
* (context: on_post, on_update, on_comment).
|
| 425 |
*/
|
| 426 |
function subscriptions_autosubscribe($module, $field, $value, $context) {
|
| 427 |
global $user;
|
| 428 |
// if user has auto subscribe enabled and he's not already subscribed
|
| 429 |
if ($user->uid && _subscriptions_get_setting('autosub_'. $context, $user) && !subscriptions_get_subscription($user->uid, $module, $field, $value)) {
|
| 430 |
subscriptions_write_subscription($module, $field, $value, -1, $user->uid, _subscriptions_get_setting('send_interval', $user), 1, 1);
|
| 431 |
}
|
| 432 |
}
|
| 433 |
|
| 434 |
/**
|
| 435 |
* Get subscriptions.
|
| 436 |
*
|
| 437 |
* @param $params
|
| 438 |
* Array of parameters for the query.
|
| 439 |
* @return
|
| 440 |
* Array of subscriptions indexed by uid, module, field, value, author_uid.
|
| 441 |
*/
|
| 442 |
function subscriptions_get($params) {
|
| 443 |
// Build query
|
| 444 |
foreach ($params as $field => $value) {
|
| 445 |
if (is_numeric($value)) {
|
| 446 |
$conditions[] = $field .' = %d';
|
| 447 |
}
|
| 448 |
else {
|
| 449 |
$conditions[] = "$field = '%s'";
|
| 450 |
}
|
| 451 |
$args[] = $value;
|
| 452 |
}
|
| 453 |
$sql = "SELECT * FROM {subscriptions} WHERE ". implode(' AND ', $conditions);
|
| 454 |
$result = db_query($sql, $args);
|
| 455 |
$subscriptions = array();
|
| 456 |
while ($s = db_fetch_object($result)) {
|
| 457 |
$subscriptions[$s->recipient_uid][$s->module][$s->field][$s->value][$s->author_uid] = 1;
|
| 458 |
}
|
| 459 |
return $subscriptions;
|
| 460 |
}
|
| 461 |
|
| 462 |
/**
|
| 463 |
* Hook subscription_types(). Get info about subscription types.
|
| 464 |
*
|
| 465 |
* @return
|
| 466 |
* Information for a given field and type
|
| 467 |
* or information for a given field for all types
|
| 468 |
*
|
| 469 |
* @ingroup hooks
|
| 470 |
*/
|
| 471 |
function subscriptions_types($field = NULL, $type = NULL) {
|
| 472 |
static $types, $list;
|
| 473 |
|
| 474 |
if (!isset($types)) {
|
| 475 |
$types = module_invoke_all('subscriptions', 'types');
|
| 476 |
foreach ($types as $stype => $data) {
|
| 477 |
if (!_subscriptions_validate_hook_result($stype, $data)) {
|
| 478 |
continue;
|
| 479 |
}
|
| 480 |
foreach ($data as $name => $value) {
|
| 481 |
$list[$name][$stype] = $value;
|
| 482 |
}
|
| 483 |
}
|
| 484 |
}
|
| 485 |
if ($type) {
|
| 486 |
return isset($types[$type][$field]) ? $types[$type][$field] : NULL;
|
| 487 |
}
|
| 488 |
else if ($field) {
|
| 489 |
return isset($list[$field]) ? $list[$field] : array();
|
| 490 |
}
|
| 491 |
else {
|
| 492 |
return $types;
|
| 493 |
}
|
| 494 |
}
|
| 495 |
|
| 496 |
/**
|
| 497 |
* Check return values of hook_subscriptions().
|
| 498 |
*/
|
| 499 |
function _subscriptions_validate_hook_result($stype, $data)
|
| 500 |
{
|
| 501 |
if (isset($stype)) {
|
| 502 |
if (!is_numeric($stype) && is_array($data) && isset($data['title']) && isset($data['access']) && isset($data['page']) && isset($data['fields']) && is_array($data['fields'])) {
|
| 503 |
return TRUE;
|
| 504 |
}
|
| 505 |
}
|
| 506 |
|
| 507 |
static $already_reported = FALSE;
|
| 508 |
if (!$already_reported) {
|
| 509 |
$already_reported = TRUE;
|
| 510 |
foreach (module_implements('subscriptions') as $module) {
|
| 511 |
$hook = $module .'_subscriptions';
|
| 512 |
$types = $hook('types');
|
| 513 |
foreach($types as $stype => $data) {
|
| 514 |
if (!_subscriptions_validate_hook_result($stype, $data)) {
|
| 515 |
$modules[$module] = $module;
|
| 516 |
}
|
| 517 |
}
|
| 518 |
}
|
| 519 |
drupal_set_message(t('The following modules return invalid data from %hook: !modules Either they are buggy !Subscriptions add-ons, or they are unrelated to !Subscriptions and should not define %hook!', array('%hook' => 'hook_subscriptions()', '!modules' => '<ul><li>'. implode($modules, '</li><li>') .'</li></ul>', '!Subscriptions' => 'Subscriptions')), 'error', FALSE);
|
| 520 |
}
|
| 521 |
return FALSE;
|
| 522 |
}
|
| 523 |
|
| 524 |
/**
|
| 525 |
* Implementation of hook_theme().
|
| 526 |
*/
|
| 527 |
function subscriptions_theme() {
|
| 528 |
return array(
|
| 529 |
'subscriptions_form_table' => array(
|
| 530 |
'file' => 'subscriptions.admin.inc',
|
| 531 |
'arguments' => array('element' => NULL),
|
| 532 |
)
|
| 533 |
);
|
| 534 |
}
|
| 535 |
|
| 536 |
/**
|
| 537 |
* Returns TRUE if the given $nid is blocked.
|
| 538 |
*/
|
| 539 |
function subscriptions_node_is_blocked($nid) {
|
| 540 |
return strpos(' '. variable_get('subscriptions_blocked_nodes', '') .' ', ' '. $nid .' ');
|
| 541 |
}
|
| 542 |
|
| 543 |
/**
|
| 544 |
* Helper function for uasort()ing arrays with elements that have a 'weight'
|
| 545 |
*/
|
| 546 |
function _subscriptions_cmp_by_weight($a, $b) {
|
| 547 |
$a = (isset($a['weight']) ? $a['weight'] : 0);
|
| 548 |
$b = (isset($b['weight']) ? $b['weight'] : 0);
|
| 549 |
return ($a < $b ? -1 : ($a == $b ? 0 : +1));
|
| 550 |
}
|
| 551 |
|
| 552 |
/**
|
| 553 |
* Helper function to retrieve
|
| 554 |
* send_self/autosub_on_post/autosub_on_update/autosub_on_comment/ | 1, 0,
|
| 555 |
* digest/send_interval/send_updates/send_comments/ | -1 = use default
|
| 556 |
* send_interval_visible/send_updates_visible/send_comments_visible/ | 1, 0, -1 = only preference, -2 = always use site default
|
| 557 |
* uses_defaults values;
|
| 558 |
* $account can be NULL/0 (for site default), a user object, or a uid.
|
| 559 |
*/
|
| 560 |
function _subscriptions_get_setting($name, $account) {
|
| 561 |
global $user;
|
| 562 |
if (!isset($account) || is_object($account) && empty($account->uid) || is_numeric($account) && $account <= 0 ) {
|
| 563 |
$uid = -DRUPAL_AUTHENTICATED_RID;
|
| 564 |
unset($account);
|
| 565 |
}
|
| 566 |
elseif (is_numeric($account)) {
|
| 567 |
if ($account == $user->uid) {
|
| 568 |
$account = $user;
|
| 569 |
$uid = $user->uid;
|
| 570 |
}
|
| 571 |
else {
|
| 572 |
$uid = $account;
|
| 573 |
unset($account);
|
| 574 |
}
|
| 575 |
}
|
| 576 |
if (isset($account)) {
|
| 577 |
$uid = $account->uid;
|
| 578 |
}
|
| 579 |
|
| 580 |
static $defaults = array();
|
| 581 |
if (!isset($defaults[$uid][$name])) {
|
| 582 |
$result = db_query("SELECT uid, digest, send_interval, send_updates, send_comments, send_interval_visible, send_updates_visible, send_comments_visible, autosub_on_post, autosub_on_update, autosub_on_comment, send_self FROM {subscriptions_user} WHERE uid in (%d, %d) ORDER BY uid", -DRUPAL_AUTHENTICATED_RID, $uid);
|
| 583 |
while ($s = db_fetch_array($result)) {
|
| 584 |
$defaults[$s['uid']] = $s;
|
| 585 |
}
|
| 586 |
if (empty($defaults[$uid])) {
|
| 587 |
// Note: This should not happen -- subscriptions_user() takes care of inserting/removing records as users are created/deleted.
|
| 588 |
// If it does happen, then users were created without calling the proper hooks, or they may have been created on another multi-site (#351753).
|
| 589 |
// Let's add the missing records, as if the user were being created just now, with the expected hook_user() invocations:
|
| 590 |
$account = user_load($uid);
|
| 591 |
subscriptions_user('insert', NULL, $account);
|
| 592 |
subscriptions_user('load', NULL, $account);
|
| 593 |
return _subscriptions_get_setting($name, $account);
|
| 594 |
}
|
| 595 |
$defaults[$uid]['uses_defaults'] = FALSE;
|
| 596 |
foreach ($defaults[$uid] as $key => $value) {
|
| 597 |
if ($value < 0) { // not set, use site dft
|
| 598 |
$defaults[$uid][$key] = $defaults[-DRUPAL_AUTHENTICATED_RID][$key];
|
| 599 |
$defaults[$uid]['uses_defaults'] = TRUE;
|
| 600 |
}
|
| 601 |
}
|
| 602 |
foreach (array('interval', 'updates', 'comments') as $parm ) {
|
| 603 |
// Site overrides user values.
|
| 604 |
if ($defaults[-DRUPAL_AUTHENTICATED_RID]['send_'. $parm .'_visible'] == -2) {
|
| 605 |
$defaults[$uid]['send_'. $parm] = $defaults[-DRUPAL_AUTHENTICATED_RID]['send_'. $parm];
|
| 606 |
}
|
| 607 |
}
|
| 608 |
}
|
| 609 |
return $defaults[$uid][$name];
|
| 610 |
}
|