notifications_team.module

Tracking 6.x-4.x branch
  1. drupal
    1. 6 contributions/notifications_team/notifications_team.module

Functions & methods

NameDescription
notifications_team_autocompleteHelper function for autocompletion. Ony for user names
notifications_team_can_subscribeWe implement a more efficient static cache than user_access() to check whether a user can subscribe to content.
notifications_team_commentImplementation of hook_comment(). Acts as a pseudo-submit handler for the notifications team UI on the comment form to avoid submit handler clashes with other modules (in particular, comment_upload).
notifications_team_count_usersCount number of users that meet some conditions
notifications_team_formDefine a "delicious" like form subscribing users to nodes. TODO - prepopulate with current user|case owner|case assignee
notifications_team_form_alterImplementation of hook_form_alter().
notifications_team_get_subscriptionsGet existing subscriptions for a node, indexed by uid
notifications_team_get_usersReturns an array of minimal user account objects that have been checked for the 'subscribe to content' permission.
notifications_team_get_users_defaultGet list of users that can be subscribed, default query, using og context when available
notifications_team_get_users_viewGet list of users from predefined view
notifications_team_menuImplementation of hook_menu()
notifications_team_nodeapiImplementation of hook_nodeapi
notifications_team_node_optionsGet settings value for content types
notifications_team_permImplementation of hook_perms()
notifications_team_themeImplementation of hook_theme()
notifications_team_ui_settings_form
notifications_team_updateUpdate subscriptions for a node.
notifications_team_views_apiImplementation of hook_views_api().
notifications_team_views_query_alterImplementation of hook views_query_alter()
theme_notifications_team_formTheme function for rendering the js-enabled team notifications widget.
theme_notifications_team_user_displayRender user's data to display as HTML
theme_notifications_team_user_plaintextRender user's data to display as plain text, for autocomplete
_notifications_team_addformHelper function adds new ui elements, and - if needed - submit hook.
_notifications_team_get_rolesGet roles that have the permission
_notifications_team_users_view_formatFormat user names from view
_notifications_team_view_string_fieldsGet string fields from view to perform searches

File

View source
  1. <?php
  2. /**
  3. * notifications_team provides a GUI for subscribing to content
  4. *
  5. * KNOWN ISSUE: Any users not available to the UI will be unsubscribed from
  6. * content they may subscribe to using some other method.
  7. */
  8. /**
  9. * Implementation of hook_menu()
  10. */
  11. function notifications_team_menu() {
  12. $items = array();
  13. $items['notifications_team/autocomplete/%'] = array(
  14. 'title' => 'Notifications_team autocomplete',
  15. 'page callback' => 'notifications_team_autocomplete',
  16. 'page arguments' => array(2),
  17. 'access arguments' => array('subscribe other users'),
  18. 'type' => MENU_CALLBACK
  19. );
  20. $items['admin/messaging/notifications/team_ui'] = array(
  21. 'title' => 'Team UI',
  22. 'description' => 'Team UI settings.',
  23. 'page callback' => 'drupal_get_form',
  24. 'page arguments' => array('notifications_team_ui_settings_form'),
  25. 'access arguments' => array('administer site configuration'),
  26. 'type' => MENU_LOCAL_TASK,
  27. );
  28. return $items;
  29. }
  30. /**
  31. * Implementation of hook_perms()
  32. */
  33. function notifications_team_perm() {
  34. return array('subscribe other users');
  35. }
  36. /**
  37. * Implementation of hook_theme()
  38. */
  39. function notifications_team_theme() {
  40. return array(
  41. 'notifications_team_form' => array(),
  42. 'notifications_team_user_display' => array(
  43. 'arguments' => array('data' => NULL, 'separator' => NULL, 'user' => NULL),
  44. ),
  45. 'notifications_team_user_plaintext' => array(
  46. 'arguments' => array('data' => NULL, 'separator' => NULL, 'user' => NULL),
  47. ),
  48. );
  49. }
  50. /**
  51. * We implement a more efficient static cache than user_access()
  52. * to check whether a user can subscribe to content.
  53. */
  54. function notifications_team_can_subscribe($account = NULL, $reset = FALSE) {
  55. // Cache the role ids that have access to 'subscribe to content'
  56. static $roles;
  57. if ($account->uid == 1) {
  58. return TRUE;
  59. }
  60. if (!isset($roles) || $reset) {
  61. $result = db_query("SELECT rid, perm FROM {permission}");
  62. while ($row = db_fetch_object($result)) {
  63. $perms = explode(', ', $row->perm);
  64. if (array_search('subscribe to content', $perms) !== FALSE) {
  65. $roles[$row->rid] = TRUE;
  66. }
  67. else {
  68. $roles[$row->rid] = FALSE;
  69. }
  70. }
  71. }
  72. // Check each role to see if this user has access to 'subscribe to content'
  73. if (!empty($account->roles)) {
  74. foreach ($account->roles as $rid) {
  75. if (!empty($roles[$rid])) {
  76. return TRUE;
  77. }
  78. }
  79. }
  80. return FALSE;
  81. }
  82. /**
  83. * Get roles that have the permission
  84. */
  85. function _notifications_team_get_roles($permission = 'subscribe to content') {
  86. static $rids;
  87. if (!isset($rids[$permission])) {
  88. $rids[$permission] = array();
  89. // Search for permission name not followed by a space (which can be other permission)
  90. $result = db_query("SELECT DISTINCT rid FROM {permission} WHERE perm LIKE '%%%s,%%' OR perm LIKE '%%%s'", $permission, $permission);
  91. while ($role = db_fetch_object($result)) {
  92. $rids[$permission][$role->rid] = $role->rid;
  93. }
  94. }
  95. return $rids[$permission];
  96. }
  97. /**
  98. * Returns an array of minimal user account objects that have been
  99. * checked for the 'subscribe to content' permission.
  100. *
  101. * @param $like
  102. * String to match for autocomplete fields
  103. * @param $limit
  104. * Maximum number of rows to return
  105. * @param $gid
  106. * Group id if using organic groups
  107. * @param $op
  108. * Operation to perform
  109. * - 'query' for regular query
  110. * - 'count' for count query
  111. * - 'reset' to reset the static cache, mostly for unit testing;
  112. */
  113. function notifications_team_get_users($like = NULL, $limit = 0, $gid = 0, $uids = NULL, $op = 'query') {
  114. static $users;
  115. if ($op == 'reset') {
  116. $users = array();
  117. return;
  118. }
  119. // This is our static cache id
  120. $params = array($like ? $like : '', $gid, $uids ? implode(',', $uids) : '', $op);
  121. $cid = implode(':', $params);
  122. if (!isset($users[$cid])) {
  123. if (($view = variable_get('notifications_team_user_view', '')) && module_exists('views')) {
  124. $users[$cid] = notifications_team_get_users_view($view, $like, $limit, $gid, $uids, $op);
  125. }
  126. else {
  127. $users[$cid] = notifications_team_get_users_default($like, $limit, $gid, $uids, $op);
  128. }
  129. }
  130. return $users[$cid];
  131. }
  132. /**
  133. * Count number of users that meet some conditions
  134. *
  135. * @param $gid
  136. * Group id
  137. */
  138. function notifications_team_count_users($gid) {
  139. if (($view = variable_get('notifications_team_user_view', '')) && module_exists('views')) {
  140. $users = notifications_team_get_users_view($view, $like, $limit, $gid);
  141. }
  142. else {
  143. $users = notifications_team_get_users_default($like, $limit, $gid);
  144. }
  145. }
  146. /**
  147. * Get list of users from predefined view
  148. */
  149. function notifications_team_get_users_view($view_name, $string = NULL, $limit = 0, $gid = 0, $uids = NULL, $op = 'query') {
  150. $result = $op == 'count' ? 0 : array();
  151. if ($view = views_get_view($view_name)) {
  152. // Use the default display
  153. $view->set_display();
  154. $view->preview = TRUE;
  155. // If we have a $string filter, we find string fields in our view, and add conditions to narrow the results
  156. // What we do is adding the information into the display handler so it can be retrieved later on hook_views_query_alter()
  157. // The $search array contains an array of searchable fields in the view for each table (varchar, text)
  158. if (isset($string) && ($search = _notifications_team_view_string_fields($view))) {
  159. $options = array(
  160. 'search_fields' => $search,
  161. 'string' => $string,
  162. 'match' => 'contains',
  163. );
  164. }
  165. elseif ($uids) {
  166. // If we just want some users, pass more parameters to the query alter
  167. // This and the string search are exclusive options
  168. $options = array(
  169. 'table' => 'users',
  170. 'field_id' => 'uid',
  171. 'ids' => $uids,
  172. );
  173. }
  174. if (!empty($options)) {
  175. $view->display_handler->set_option('notifications_team_options', $options);
  176. }
  177. // If we have a group id we set it as an argument
  178. if ($gid) {
  179. $view->pre_execute(array($gid));
  180. } else {
  181. $view->pre_execute();
  182. }
  183. if ($op == 'count') {
  184. $view->set_items_per_page(1);
  185. // Count operation: trick the view with some parameters.
  186. // @todo: There should be a better way to do this (?)
  187. $view->get_total_rows = TRUE;
  188. $view->display_handler->preview();
  189. $view->post_execute();
  190. return $view->total_rows;
  191. }
  192. else {
  193. $view->set_items_per_page($limit);
  194. // Get the results. Render the fields separately to get the name
  195. $view->display_handler->preview();
  196. $view->post_execute();
  197. $fields = $view->field;
  198. $options = $view->style_plugin->row_plugin->options;
  199. foreach ($view->result as $index => $row) {
  200. $rendered = (array)$view->style_plugin->rendered_fields[$index];
  201. $result[$row->uid] = _notifications_team_users_view_format($row, $rendered, $fields, $options);
  202. }
  203. }
  204. }
  205. return $result;
  206. }
  207. /**
  208. * Format user names from view
  209. *
  210. * @param $user
  211. * User object resulting from the query
  212. * @param $rendered
  213. * Rendered fields, usually as HTML
  214. * @param $fields
  215. * Field definition objects from the view
  216. * @param $options
  217. * Options form $view->style_plugin->row_plugin->options
  218. */
  219. function _notifications_team_users_view_format($user, $rendered, $fields, $options) {
  220. $inline = !empty($options['inline']) ? $options['inline'] : array('name');
  221. $separator = !empty($options['separator']) ? $options['separator'] : ', ';
  222. // Build user name, just reassign field
  223. $user->name = $user->users_name;
  224. // Build html display part, get out excluded fields from rendered
  225. foreach ($fields as $key => $field) {
  226. if (!empty($field->options['exclude'])) {
  227. unset($rendered[$key]);
  228. }
  229. }
  230. $user->display = theme('notifications_team_user_display', $rendered, $separator, $user);
  231. // Build plaintext display part
  232. $text= array();
  233. foreach ($inline as $key) {
  234. // @TODO: There should be a better way of rendering the field as plaintext (?)
  235. $text[$key] = check_plain($user->{$fields[$key]->field_alias}); //$fields[$key]->render($user);
  236. }
  237. $user->plaintext = theme('notifications_team_user_plaintext', $text, $separator, $user);
  238. return $user;
  239. }
  240. /**
  241. * Get string fields from view to perform searches
  242. *
  243. * @return array of table => array('field1', 'field2'...)
  244. */
  245. function _notifications_team_view_string_fields($view) {
  246. $search = array();
  247. foreach ($view->display_handler->options['fields'] as $name => $field) {
  248. $table = $field['table'];
  249. if ($schema = drupal_get_schema($table)) {
  250. $type = $schema['fields'][$name]['type'];
  251. if ($type == 'varchar' || $type == 'text') {
  252. $search[$table][] = $name;
  253. }
  254. }
  255. }
  256. return $search;
  257. }
  258. /**
  259. * Get list of users that can be subscribed, default query, using og context when available
  260. */
  261. function notifications_team_get_users_default($like = NULL, $limit = 0, $gid = NULL, $uids = NULL, $op = 'query') {
  262. $users = array();
  263. $where = $join = $args = array();
  264. $order = '';
  265. // Get roles that can subscribe. If none, returm empty (array or 0 for count)
  266. $rids = _notifications_team_get_roles('subscribe to content');
  267. if (!$rids) {
  268. return ($op == 'count') ? 0 : array();
  269. }
  270. // Remove authenticated user if there
  271. if (isset($rids[DRUPAL_AUTHENTICATED_RID])) {
  272. unset($rids);
  273. }
  274. // Populate $gid automatically from group context.
  275. // Avoid this behavior if $gid is specified explicitly.
  276. if (empty($gid) && module_exists('og') && $oggroup = og_get_group_context()) {
  277. $gid = $oggroup->nid;
  278. }
  279. // Build query
  280. $sql_select = "SELECT DISTINCT u.uid, u.name, u.mail";
  281. $sql_from = "FROM {users} u";
  282. $where[] = "u.status > 0";
  283. $order = "ORDER BY u.name ASC";
  284. // Limit to certain users if passed $uids
  285. if ($uids) {
  286. $where[] = 'u.uid IN (' . db_placeholders($uids) . ')';
  287. $args = $uids;
  288. }
  289. // Add group condition if gid
  290. if ($gid) {
  291. $join[] = "INNER JOIN {og_uid} ou ON ou.uid = u.uid";
  292. $where[] = "ou.nid = %d";
  293. $args[] = $gid;
  294. $where[] = "ou.is_active >= 1";
  295. $where[] = "ou.is_admin >= 0";
  296. }
  297. // Add permission/role condition. If no roles (only authenticated user, add an uid condition)
  298. if ($rids) {
  299. $join[] = "LEFT JOIN {users_roles} r ON u.uid = r.uid";
  300. $where[] = "(r.rid IN (" . db_placeholders($rids) . ') OR u.uid = 1)';
  301. $args = array_merge($args, $rids);
  302. }
  303. else {
  304. $where[] = "u.uid > 0";
  305. }
  306. // Add string matching condition
  307. if (!empty($like)) {
  308. $where[] = "LOWER(u.name) LIKE LOWER('%s%%')";
  309. $args[] = $like;
  310. }
  311. $sql_from .= ' ' . implode(' ', $join);
  312. $sql_where = ' WHERE ' . implode(' AND ', $where);
  313. // If it is a counting query, without order by, just count and return
  314. if ($op == 'count') {
  315. $sql = implode(' ', array('SELECT COUNT(DISTINCT u.uid)', $sql_from, $sql_where));
  316. return db_result(db_query($sql, $args));
  317. }
  318. else {
  319. $sql = implode(' ', array($sql_select, $sql_from, $sql_where, $order));
  320. $result = $limit ? db_query_range($sql, $args, 0, $limit) : db_query($sql, $args);
  321. }
  322. while ($row = db_fetch_object($result)){
  323. $users[$row->uid] = $row;
  324. }
  325. return $users;
  326. }
  327. /**
  328. * Define a "delicious" like form subscribing users to nodes.
  329. * TODO - prepopulate with current user|case owner|case assignee
  330. */
  331. function notifications_team_form($nid) {
  332. $form = array();
  333. $gid = module_exists('og') && ($group = og_get_group_context()) ? $group->nid : 0;
  334. $count = notifications_team_get_users(NULL, 0, $gid, NULL, 'count');
  335. if ($count) {
  336. // Check whether we need to list all or just an autocomplete form
  337. $acomplete = $count > variable_get('notifications_team_max_options', 20);
  338. // Get existing subscriptions.
  339. if (is_numeric($nid)) {
  340. $subscriptions = notifications_team_get_subscriptions($nid);
  341. $subscribers = array_keys($subscriptions);
  342. }
  343. else {
  344. $subscriptions = $subscribers = array();
  345. }
  346. // Select all users if not autocomplete or users with subscriptions otherwise
  347. if ($acomplete) {
  348. $users = notifications_team_get_users(NULL, 0, $gid, $subscribers);
  349. }
  350. else {
  351. $users = notifications_team_get_users(NULL, 0, $gid);
  352. }
  353. // Build user names to display
  354. $user_names = array();
  355. if ($acomplete) {
  356. // have an autocomplete box and only have users on the checkboxes that are already subscribed
  357. foreach($subscribers as $uid) {
  358. $user = $users[$uid];
  359. $user_names[$uid] = isset($user->display) ? $user->display : $user->name;
  360. }
  361. asort($user_names);
  362. }
  363. elseif (count($users)) {
  364. foreach ($users as $user) {
  365. $user_names[$user->uid] = isset($user->display) ? $user->display : $user->name;
  366. }
  367. }
  368. else {
  369. // If we don't have any user available, display no form
  370. return array();
  371. }
  372. // Build the form.
  373. $form['notifications_team'] = array(
  374. '#tree' => TRUE,
  375. '#theme' => 'notifications_team_form',
  376. );
  377. $form['notifications_team']['selected'] = array(
  378. '#type' => 'hidden',
  379. '#default_value' => implode(',', $subscribers),
  380. );
  381. if ($acomplete) {
  382. $form['notifications_team']['listed'] = array(
  383. '#type' => 'textfield',
  384. '#autocomplete_path' => 'notifications_team/autocomplete/'. $gid,
  385. '#default_value' => '',
  386. '#description' => t('Enter list of usernames separated by commas'),
  387. '#required' => FALSE,
  388. );
  389. }
  390. else {
  391. $form['team_checkall'] = array(
  392. '#type' => 'checkbox',
  393. '#title' => t('Notify all users'),
  394. '#weight' => 0,
  395. );
  396. }
  397. if ($user_names) {
  398. $form['notifications_team']['options'] = array(
  399. '#type' => 'markup',
  400. '#value' => $user_names,
  401. );
  402. }
  403. }
  404. return $form;
  405. }
  406. /**
  407. * Get existing subscriptions for a node, indexed by uid
  408. */
  409. function notifications_team_get_subscriptions($nid, $reset = FALSE) {
  410. static $subscriptions;
  411. if (!isset($subscriptions[$nid]) || $reset) {
  412. $params = array('type' => 'thread', 'event_type' => 'node');
  413. $conditions = array('nid' => $nid);
  414. $subscriptions[$nid] = notifications_get_subscriptions($params, $conditions, TRUE, 'uid');
  415. }
  416. return $subscriptions[$nid];
  417. }
  418. /**
  419. * Theme function for rendering the js-enabled team notifications widget.
  420. */
  421. function theme_notifications_team_form($form) {
  422. // Add javascript
  423. drupal_add_js(drupal_get_path('module', 'notifications_team') .'/notifications_team.js', 'module');
  424. drupal_add_css(drupal_get_path('module', 'notifications_team') .'/notifications_team.css');
  425. $output = '';
  426. // Render each of the user selector options
  427. if ($form['options']['#value']) {
  428. $options = '';
  429. foreach ($form['options']['#value'] as $uid => $name) {
  430. $options .= "<div><span class='uid-$uid'>$name</span></div>";
  431. }
  432. $form['options']['#value'] = $options;
  433. }
  434. // Render the entire form element
  435. $output .= "<div class='notifications-team clear-block'>". drupal_render($form) ."</div>";
  436. return $output;
  437. }
  438. /**
  439. * Render user's data to display as HTML
  440. */
  441. function theme_notifications_team_user_display($data, $separator, $user) {
  442. return implode($separator, $data);
  443. }
  444. /**
  445. * Render user's data to display as plain text, for autocomplete
  446. */
  447. function theme_notifications_team_user_plaintext($data, $separator, $user) {
  448. // Convert separator to plaintext
  449. return theme_notifications_team_user_display($data, $separator, $user);
  450. }
  451. /**
  452. * Implementation of hook_comment().
  453. * Acts as a pseudo-submit handler for the notifications team UI on the
  454. * comment form to avoid submit handler clashes with other modules (in
  455. * particular, comment_upload).
  456. */
  457. function notifications_team_comment(&$comment, $op) {
  458. switch ($op) {
  459. case 'insert':
  460. case 'update':
  461. // Only run if the notifications_team key is actually set.
  462. if (isset($comment['notifications_team'])) {
  463. $uids = explode(',', $comment['notifications_team']['selected']);
  464. if ($comment['notifications_team']['listed']) {
  465. $textunames = explode(',', $comment['notifications_team']['listed']);
  466. foreach($textunames AS $uname) {
  467. $u = db_fetch_object(db_query("SELECT uid FROM {users} WHERE name = '%s'", trim($uname)));
  468. if ($u) {
  469. $uids[] = $u->uid;
  470. }
  471. }
  472. }
  473. $nid = $comment['nid'];
  474. notifications_team_update($nid, $uids, empty($comment['notifications_content_disable']));
  475. }
  476. break;
  477. }
  478. }
  479. /**
  480. * Implementation of hook_nodeapi
  481. *
  482. * TODO Use notifications_ui_notifications('event trigger'...) and not hook_nodeapi. This would allow us to
  483. * unify subscriptions processing for both nodes and comments into one place. ie we wouldn't need notifications_team_form_submit()
  484. */
  485. function notifications_team_nodeapi(&$node, $op, $teaser) {
  486. if (($op == 'update' || $op == 'insert') && $node->nid) {
  487. if (isset($node->notifications_team)) {
  488. $new_uids = explode(',', $node->notifications_team['selected']);
  489. if ($node->notifications_team['listed']) {
  490. $textunames = explode(',', $node->notifications_team['listed']);
  491. foreach($textunames AS $uname) {
  492. $u = db_fetch_object(db_query("SELECT uid FROM {users} WHERE name = '%s'", trim($uname)));
  493. if ($u) {
  494. $new_uids[] = $u->uid;
  495. }
  496. }
  497. }
  498. notifications_team_update($node->nid, $new_uids, empty($node->notifications_content_disable));
  499. }
  500. }
  501. }
  502. /**
  503. * Update subscriptions for a node.
  504. *
  505. * @param $nid
  506. * node id
  507. * @param $new_uids
  508. * ids of users to subscribe to the node.
  509. */
  510. function notifications_team_update($nid, $new_uids, $displaymsg = FALSE, $reset = FALSE) {
  511. // Get and wipe existing subs for this thread
  512. $subscriptions = notifications_team_get_subscriptions($nid, $reset);
  513. $allowed = notifications_team_get_users(NULL, 0, 0);
  514. // Create subscriptions
  515. $doneuids = array();
  516. $count = 0;
  517. global $user;
  518. // Template subscription
  519. $template = array(
  520. 'type' => 'thread',
  521. 'event_type' => 'node',
  522. 'fields' => array('nid' => $nid),
  523. );
  524. foreach ($new_uids as $uid) {
  525. if (is_numeric($uid)) {
  526. if (in_array($uid, $doneuids)) {
  527. continue;
  528. }
  529. $doneuids[] = $uid;
  530. if (!empty($subscriptions[$uid])) {
  531. // We don't change existing subscriptions, just create new ones
  532. unset($subscriptions[$uid]);
  533. $result = TRUE;
  534. }
  535. // Only allow for subscribing users who have permission.
  536. elseif (isset($allowed[$uid])) {
  537. $subscription = $template + array('uid' => $uid);
  538. // allow retention of personalized settings such as send method if user remains subscribed
  539. $result = notifications_save_subscription($subscription);
  540. }
  541. else {
  542. $result = FALSE;
  543. }
  544. if ($result && $user->uid != $uid) {
  545. $count++;
  546. }
  547. }
  548. }
  549. // Delete all the subscriptins that were not 'revalidated'
  550. foreach ($subscriptions as $subs) {
  551. notifications_delete_subscription($subs->sid);
  552. }
  553. if ($count > 0 && $displaymsg) {
  554. drupal_set_message(format_plural($count,"1 other user has been notified.","@count other users have been notified."));
  555. }
  556. }
  557. /**
  558. * Implementation of hook_form_alter().
  559. *
  560. * Adds the notifications_team_form and it's submission handler.
  561. *
  562. * For comments, we do it only when comment events are enabled. For insert/edit we don't check event enabled
  563. * as when creating / editing the node we may want to change which users get notifications for comments
  564. */
  565. function notifications_team_form_alter(&$form, &$form_state, $form_id) {
  566. global $user;
  567. if($form_id == 'node_type_form') {
  568. if (isset($form['identity']['type'])) {
  569. module_load_include('admin.inc', 'notifications_ui');
  570. // Just in case we want to add more settings here
  571. $form['notifications']['notifications_team_type'] = array(
  572. '#type' => 'checkboxes',
  573. '#title' => t('Team UI'),
  574. '#default_value' => notifications_team_node_options($form['#node_type']->type),
  575. '#options' => array(
  576. 'node' => t('<strong>In node form</strong>. A Team UI subform will be available when creating or editing nodes.'),
  577. 'comment' => t('<strong>In comment form</strong>. A Team UI subform will be available when posting comments.'),
  578. ),
  579. '#description' => t('Enable different display options for Team UI subscription forms.'),
  580. );
  581. if (!variable_get('notifications_team_per_type', 0)) {
  582. $form['notifications']['notifications_team_type']['#disabled'] = TRUE;
  583. $form['notifications']['notifications_team_type']['#description'] .= ' <strong>' . t('To enable these options check the <a href="@notifications-team-settings">Notifications Team settings</a>', array('@notifications-team-settings' => url('admin/messaging/notifications/team_ui'))) . '</strong>';
  584. }
  585. }
  586. }
  587. if (user_access('subscribe other users')) {
  588. if (isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id &&
  589. ($form['nid']['#value'] && notifications_event_enabled('node', 'update') || !$form['nid']['#value'] && notifications_event_enabled('node', 'insert') )
  590. ) {
  591. _notifications_team_addform($form, $form['type']['#value'], 'node', $form['nid']['#value']);
  592. if (isset($form_state['node_preview'])) {
  593. $form['notifications']['notifications_team']['selected']['#default_value'] = $form_state['values']['notifications_team']['selected'];
  594. }
  595. }
  596. elseif ($form_id == "comment_form" && notifications_event_enabled('node', 'comment')) {
  597. $node = node_load($form['nid']['#value']);
  598. _notifications_team_addform($form, $node->type, 'comment', $node->nid);
  599. }
  600. }
  601. }
  602. function notifications_team_ui_settings_form() {
  603. $form['notifications_team_max_options'] = array(
  604. '#type' => 'textfield',
  605. '#title' => t('Max Checkboxes'),
  606. '#default_value' => variable_get('notifications_team_max_options', 20),
  607. '#description' => t('Maximum number of available users to show as individual checkboxes before using autocomplete form.'),
  608. );
  609. $views = array('' => '--');
  610. if (module_exists('views')) {
  611. $all_views = views_get_all_views();
  612. foreach ($all_views as $view) {
  613. // Only 'users' views that have fields will work for our purpose.
  614. if ($view->base_table == 'users' && !empty($view->display['default']->display_options['fields'])) {
  615. if ($view->type == 'Default') {
  616. $views[t('Default Views')][$view->name] = $view->name;
  617. }
  618. else {
  619. $views[t('Existing Views')][$view->name] = $view->name;
  620. }
  621. }
  622. }
  623. }
  624. $form['notifications_team_user_view'] = array(
  625. '#title' => t('View for user selection'),
  626. '#type' => 'select',
  627. '#options' => $views,
  628. '#default_value' => variable_get('notifications_team_user_view', ''),
  629. '#description' => t('Optionally you can define a view for the list of available users. This view must have at least <i>user id</i> and <i>name</i> fields. For the autocomplete option to work properly you need CCK module enabled.'),
  630. '#disabled' => count($views) == 1,
  631. );
  632. $form['form_displays'] = array(
  633. '#type' => 'fieldset',
  634. '#title' => t('Team UI Display'),
  635. '#collapsible' => TRUE,
  636. '#description' => t('You can use the global settings here or set different options for each content type. In the second case these will be the defaults for new content types.'),
  637. );
  638. $form['form_displays']['notifications_team_per_type'] = array(
  639. '#type' => 'radios',
  640. '#default_value' => variable_get('notifications_team_per_type', 0),
  641. '#options' => array(
  642. t('Use global settings on this page for all enabled content types.'),
  643. t('Set up for each content type on <a href="@content-type-settings">Administer Content Types</a>.', array('@content-type-settings' => url('admin/content/types'))),
  644. ),
  645. );
  646. $form['form_displays']['notifications_team_options'] = array(
  647. '#title' => t('Global settings'),
  648. '#type' => 'checkboxes',
  649. '#default_value' => variable_get('notifications_team_options', array('node', 'comment')),
  650. '#options' => array(
  651. 'node' => t('<strong>In node form</strong>. A Team UI subform will be available when creating or editing nodes.'),
  652. 'comment' => t('<strong>In comment form</strong>. A Team UI subform will be available when posting comments.'),
  653. ),
  654. '#description' => t('Enable different display options for Team UI subscription forms.'),
  655. );
  656. return system_settings_form($form);
  657. }
  658. /**
  659. * Helper function adds new ui elements, and - if needed - submit hook.
  660. *
  661. * @param $form
  662. * The form api form array.
  663. * @param $nid
  664. * Node id of the node to be subscribed to.
  665. * @param $node_type
  666. * Type of node, used to determine if subs are active.
  667. * @param $location
  668. * Form_alter location - either 'node' or 'comment'.
  669. */
  670. function _notifications_team_addform(&$form, $node_type, $location = 'node', $nid = NULL) {
  671. // Check to see it thread subscriptions are active for this content type.
  672. if (notifications_content_type_enabled($node_type, 'thread') && notifications_team_node_options($node_type, $location)) {
  673. $subscriptions_form = notifications_team_form($nid);
  674. if (count($subscriptions_form)) {
  675. if (isset($form['notifications'])) {
  676. $form['notifications'] = array_merge($form['notifications'], $subscriptions_form);
  677. }
  678. else {
  679. // We need to add the full notifications fieldset
  680. $form['notifications'] = $subscriptions_form;
  681. $form['notifications']['#type'] = 'fieldset';
  682. $form['notifications']['#title'] = t('Notifications');
  683. $form['notifications']['#collapsible'] = TRUE;
  684. }
  685. }
  686. }
  687. }
  688. /**
  689. * Get settings value for content types
  690. *
  691. * @param $type
  692. * Content type to get settings for
  693. * @param $option
  694. * Optional option to check (each option can be enabled or disabled)
  695. */
  696. function notifications_team_node_options($type = NULL, $option = NULL) {
  697. // We can use global options or per content type options. The default is both
  698. $options = variable_get('notifications_team_options', array('node', 'comment'));
  699. if ($type && variable_get('notifications_team_per_type', 0)) {
  700. $options = variable_get('notifications_team_type_' . $type, $options);
  701. }
  702. return $option ? in_array($option, $options, TRUE) : $options;
  703. }
  704. /**
  705. * Helper function for autocompletion. Ony for user names
  706. */
  707. function notifications_team_autocomplete($oggroup = 0, $notify = '') {
  708. // The user enters a comma-separated list of destinations. We only autocomplete the last tag.
  709. $array = split(',', $notify);
  710. foreach ($array as $key => $entry) {
  711. $array[$key] = trim($entry);
  712. }
  713. $string = trim(array_pop($array));
  714. $matches = array();
  715. if ($string) {
  716. $prefix = count($array) ? implode(', ', $array) .', ' : '';
  717. foreach (notifications_team_get_users($string, 10, $oggroup) as $user) {
  718. $display = isset($user->plaintext) ? $user->plaintext : check_plain($user->name);
  719. $matches[$prefix . $user->name] = $prefix . $display;
  720. }
  721. }
  722. drupal_json($matches);
  723. }
  724. /**
  725. * Implementation of hook_views_api().
  726. */
  727. function notifications_team_views_api() {
  728. return array(
  729. 'api' => 2,
  730. );
  731. }
  732. /**
  733. * Implementation of hook views_query_alter()
  734. */
  735. function notifications_team_views_query_alter($view, $query) {
  736. if ($options = $view->display_handler->get_option('notifications_team_options')) {
  737. if (!empty($options['string']) && !empty($options['search_fields'])) {
  738. $match_clauses = array(
  739. 'contains' => "LIKE '%%%s%%'",
  740. 'equals' => "= '%s'",
  741. 'starts_with' => "LIKE '%s%%'",
  742. );
  743. $clause = isset($match_clauses[$options['match']]) ? $match_clauses[$options['match']] : $match_clauses['contains'];
  744. // Add condition for each search field, this will be an OR group
  745. $group = $query->set_where_group('OR');
  746. foreach ($options['search_fields'] as $table => $table_fields) {
  747. foreach ($table_fields as $field) {
  748. $alias = $query->ensure_table($table);
  749. $query->add_where($group, "$alias.$field $clause", $options['string']);
  750. }
  751. }
  752. }
  753. elseif ($options['ids']) {
  754. $alias = $query->ensure_table($options['table']);
  755. $field = $options['field_id'];
  756. $query->add_where(NULL, "$alias.$field IN (" . db_placeholders($options['ids']) . ')', $options['ids']);
  757. }
  758. }
  759. }