/[drupal]/contributions/modules/subscriptions/subscriptions_ui.module
ViewVC logotype

Contents of /contributions/modules/subscriptions/subscriptions_ui.module

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


Revision 1.17 - (show annotations) (download) (as text)
Sun Oct 4 16:22:50 2009 UTC (7 weeks, 1 day ago) by salvis
Branch: MAIN
CVS Tags: HEAD
Changes since 1.16: +8 -4 lines
File MIME type: text/x-php
#591470: Avoid iterating over all thread subscriptions when preparing the node subscribe form, reported by Jeremy.
1 <?php
2 // $Id: subscriptions_ui.module,v 1.16 2009/07/22 16:58:07 salvis Exp $
3
4 /**
5 * @file
6 * Provides a user interface for Subscriptions.
7 */
8
9 /**
10 * Implementation of hook_nodeapi().
11 *
12 * Inject the node subform into node pages (depending on the Display Settings).
13 *
14 * @ingroup hooks
15 * @ingroup form
16 */
17 function subscriptions_ui_nodeapi(&$node, $op, $teaser) {
18 global $user;
19 if ($op == 'view' && $node->nid && !$teaser && subscriptions_ui_can_subscribe()) {
20 if (!variable_get('subscriptions_form_in_block', 0) &&
21 (!variable_get('subscriptions_form_link_only', 0) && (!arg(2) || arg(2) == 'view') ||
22 variable_get('subscriptions_form_link_only', 0) && arg(2) == 'subscribe' )) {
23 if ($form = drupal_get_form('subscriptions_ui_node_form', $node)) {
24 $node->content['subscriptions'] = array(
25 '#value' => $form,
26 '#weight' => 100,
27 );
28 }
29 }
30 }
31 }
32
33 /**
34 * Implementation of hook_block().
35 *
36 * Define the Subscriptions Interface block for node pages (depending on the Display Settings).
37 *
38 * @ingroup hooks
39 */
40 function subscriptions_ui_block($op = 'list', $delta = 0) {
41 switch ($op) {
42 case 'list':
43 $blocks[0]['info'] = t('Subscriptions interface');
44 $blocks[0]['cache'] = BLOCK_CACHE_PER_PAGE;
45 $blocks[0]['region'] = 'content';
46 return $blocks;
47 case 'view':
48 if (subscriptions_ui_can_subscribe() && variable_get('subscriptions_form_in_block', 0) &&
49 (!variable_get('subscriptions_form_link_only', 0) && (!arg(2) || arg(2) == 'view') ||
50 variable_get('subscriptions_form_link_only', 0) && arg(2) == 'subscribe' )) {
51 return array(
52 'subject' => t('Subscriptions'),
53 'content' => drupal_get_form('subscriptions_ui_node_form', menu_get_object()),
54 );
55 }
56 }
57 }
58
59
60 /**
61 * Returns TRUE on node/NID pages if the NID is not blocked
62 * and no other module wants to provide the UI.
63 */
64 function subscriptions_ui_can_subscribe() {
65 global $user;
66
67 return ($user->uid && arg(0) == 'node' && is_numeric(arg(1)) && module_invoke('subscriptions_ui', 'get_permission_to_handle', arg(1), 'subscriptions_ui') !== FALSE);
68 }
69
70 /**
71 * Implementation of hook_link().
72 *
73 * Add a Subscribe link to node pages (depending on the Display Settings).
74 */
75 function subscriptions_ui_link($type, $node = NULL, $teaser = NULL) {
76 global $user;
77
78 if ($type == 'node' && subscriptions_ui_can_subscribe() && empty($teaser)) {
79 if (variable_get('subscriptions_form_link_only', 0) && arg(2) != 'subscribe' && (!variable_get('subscriptions_avoid_empty_subscribe_links', 0) || module_invoke_all('subscriptions', 'node_options', $user, $node))) {
80 $blocked_types = variable_get('subscriptions_blocked_content_types', array());
81 if (!in_array($node->type, $blocked_types) || user_access('subscribe to all content types')) {
82 return array('subscriptions-subscribe' => array(
83 'href' => $_GET['q'] .'/subscribe',
84 'title' => t('Subscribe') . (in_array($node->type, $blocked_types) ? SUBSCRIPTIONS_UNAVAILABLE : ''),
85 'html' => TRUE,
86 'fragment' => 'subscribe',
87 'attributes' => array('title' => t('Receive notifications about changes and/or comments to this page (and possibly similar pages).')),
88 ));
89 }
90 }
91 elseif (variable_get('subscriptions_form_in_block', 0) && arg(2) == 'subscribe') {
92 // Make sure the block is visible
93 global $theme;
94 if (!isset($theme)) {
95 init_theme();
96 }
97 $regions = system_region_list($theme);
98 foreach (array_keys($regions) as $region) {
99 $blocks = block_list($region);
100 foreach (array_keys($blocks) as $block) {
101 if ($block == 'subscriptions_ui_0') {
102 $subscriptions_ui_block_visible = TRUE;
103 }
104 }
105 }
106 if (empty($subscriptions_ui_block_visible)) {
107 drupal_set_message(t('Enable the !module block <!link_tag_begin>here<!link_tag_end>!', array('!module' => 'Subscriptions', '!link_tag_begin' => 'a href="'. url('admin/build/block') .'"', '!link_tag_end' => '/a')), 'error');
108 }
109 }
110 }
111 }
112
113 /**
114 * Returns the form definition for the node subform.
115 *
116 * @param $node
117 * Must be a valid node object.
118 * @param $account
119 * If not given, will be populated with current user (either anonymous).
120 *
121 * @ingroup form
122 * @ingroup hooks
123 */
124 function subscriptions_ui_node_form(&$form_state, $node, $account = NULL) {
125 global $user;
126 if (!isset($account)) {
127 $account = $user;
128 }
129
130 if (subscriptions_node_is_blocked($node->nid)) {
131 return NULL;
132 }
133
134 $blocked_types = variable_get('subscriptions_blocked_content_types', array());
135 if (in_array($node->type, $blocked_types)) {
136 if (!user_access('subscribe to all content types', $account)) {
137 return NULL;
138 }
139 $is_blocked = TRUE;
140 }
141
142 init_theme(); // just in case, before calling theme_get_setting()
143 $show_node_info = theme_get_setting('toggle_node_info_'. $node->type);
144 $node_options = module_invoke_all('subscriptions', 'node_options', $account, $node);
145 if (!$node_options || !user_access('subscribe to content', $account)) {
146 return array();
147 }
148 uasort($node_options, '_subscriptions_cmp_by_weight');
149
150 foreach (array(
151 db_query("SELECT sid, module, field, value, author_uid, send_interval, send_updates, send_comments FROM {subscriptions} WHERE module = 'node' AND field = 'nid' AND value = '%s' AND recipient_uid = %d", $node->nid, $account->uid),
152 db_query("SELECT sid, module, field, value, author_uid, send_interval, send_updates, send_comments FROM {subscriptions} WHERE module = 'node' AND field <> 'nid' AND recipient_uid = %d", $account->uid),
153 ) as $result) {
154 while ($s = db_fetch_array($result)) {
155 $subscriptions[$s['field']][$s['value']][$s['author_uid']] = $s;
156 }
157 }
158 // Process all options building the array of indexed params for each
159 $nonlabeled_options = $options = $params = $default_comments = $default_updates = $default_subscriptions = array();
160 $index = 1; // If we start with zero, get some value sent as 0 => 0
161 foreach ($node_options as $field => $field_options) {
162 foreach ($field_options as $option) {
163 if (!is_array($option)) {
164 continue;
165 }
166 if ((!$show_node_info || !variable_get('subscriptions_show_by_author_options', 1)) && isset($option['params']['author_uid']) && $option['params']['author_uid'] >= 0) {
167 continue;
168 }
169 if ($option['params']['module'] == 'node' && $option['params']['field'] == 'type' && !empty($is_blocked)) {
170 $option['name'] .= '&nbsp;'. SUBSCRIPTIONS_UNAVAILABLE;
171 }
172 //$options[$index] = (isset($option['link']) ? l($option['name'], 'subscriptions/add/'. $option['link'], array('query' => drupal_get_destination(), 'html' => TRUE)) : $option['name']);
173 $options[$index] = $option['name'];
174 $nonlabeled_options[$index] = '';
175 $params[$index] = $param = $option['params'] + array('author_uid' => -1);
176 if (isset($subscriptions[$param['field']][$param['value']][$param['author_uid']])) {
177 $default_subscriptions[] = $index;
178 $default_send_intervals[$index] = $subscriptions[$param['field']][$param['value']][$param['author_uid']]['send_interval'];
179 if ($subscriptions[$param['field']][$param['value']][$param['author_uid']]['send_comments']) {
180 $default_comments[] = $index;
181 }
182 if ($subscriptions[$param['field']][$param['value']][$param['author_uid']]['send_updates']) {
183 $default_updates[] = $index;
184 }
185 }
186 else {
187 $default_send_intervals[$index] = _subscriptions_get_setting('send_interval', $account);
188 if (_subscriptions_get_setting('send_comments', $account))
189 $default_comments[] = $index;
190 if (_subscriptions_get_setting('send_updates', $account))
191 $default_updates[] = $index;
192 }
193 $index++;
194 }
195 }
196
197 $form['params'] = array('#type' => 'value', '#value' => $params);
198
199 $form['wrapper'] = array(
200 '#type' => 'fieldset',
201 '#title' => t('Subscribe') . (!empty($is_blocked) ? '&nbsp;'. SUBSCRIPTIONS_UNAVAILABLE : ''),
202 '#collapsible' => TRUE,
203 '#collapsed' => !variable_get('subscriptions_form_expanded', 0),
204 '#theme' => 'subscriptions_ui_table',
205 '#attributes' => array('id' => 'subscribe'),
206 );
207 $form['wrapper']['subscriptions'] = array(
208 '#type' => 'checkboxes',
209 '#default_value' => $default_subscriptions,
210 '#options' => $options,
211 '#access' => TRUE,
212 );
213 $form['wrapper']['updates'] = array(
214 '#type' => 'checkboxes',
215 '#default_value' => $default_updates,
216 '#options' => $nonlabeled_options,
217 '#access' => _subscriptions_get_setting('send_updates_visible', $user) > 0,
218 );
219 if (module_exists('comment') && user_access('access comments')) {
220 $form['wrapper']['comments'] = array(
221 '#type' => 'checkboxes',
222 '#default_value' => $default_comments,
223 '#options' => $nonlabeled_options,
224 '#access' => _subscriptions_get_setting('send_comments_visible', $user) > 0,
225 );
226 }
227 $form['wrapper']['footer'] = array(
228 '#type' => 'item',
229 '#description' => t('The master checkboxes on the left turn the given subscription on or off. Depending on the setup of the site, you may have additional options for active subscriptions.'),
230 '#weight' => 9,
231 );
232 $form['wrapper']['submit'] = array(
233 '#type' => 'submit',
234 '#value' => t('Save'),
235 '#weight' => 10,
236 );
237 $form['account'] = array('#type' => 'value', '#value' => $account);
238 $form['send_intervals'] = array('#type' => 'value', '#value' => $default_send_intervals);
239 return $form;
240 }
241
242 /**
243 * Implementation of hook_theme().
244 */
245 function subscriptions_ui_theme() {
246 return array(
247 'subscriptions_ui_table' => array(
248 'arguments' => array('element'),
249 )
250 );
251 }
252
253 /**
254 * Theme subscriptions node subform table.
255 *
256 * @ingroup themeable
257 */
258 function theme_subscriptions_ui_table($element) {
259 $rows = array();
260 $headers = array();
261 $header_strings = array(
262 array('class' => 'subscriptions-table', 'width' => '30%'),
263 array('data' => t('On&nbsp;updates'), 'width' => '1*', 'style' => 'writing-mode: lr-tb'),
264 array('data' => t('On&nbsp;comments'))
265 );
266 foreach (element_children($element['subscriptions']) as $key) {
267 $row = array();
268 foreach (array('subscriptions', 'updates', 'comments') as $eli => $elv) {
269 if (isset($element[$elv]) && $element[$elv]['#access']) {
270 $row[] = drupal_render($element[$elv][$key]);
271 $headers[$eli] = $header_strings[$eli];
272 }
273 }
274 $rows[] = $row;
275 }
276 unset($headers[end(array_keys($headers))]['width']);
277 $output = theme('table', $headers, $rows);
278 $output .= drupal_render($element);
279 drupal_add_js(drupal_get_path('module', 'subscriptions') .'/subscriptions_tableselect.js', 'module');
280 return $output;
281 }
282
283 /**
284 * Node subscriptions node subform submit handler.
285 *
286 * @ingroup form
287 */
288 function subscriptions_ui_node_form_submit($form, &$form_state) {
289
290 $recipient_uid = $form_state['values']['account']->uid;
291 $default_send_intervals = $form_state['values']['send_intervals'];
292
293 foreach ($form_state['values']['subscriptions'] as $index => $value) {
294 $params = $form_state['values']['params'][$index];
295 $args = array($params['module'], $params['field'], $params['value'], $params['author_uid'], $recipient_uid);
296 if ($value) {
297 $args[] = $default_send_intervals[$index];
298 $args[] = !empty($form_state['values']['updates'][$index]);
299 $args[] = !empty($form_state['values']['comments'][$index]);
300 call_user_func_array('subscriptions_write_subscription', $args);
301 }
302 else {
303 db_query("DELETE FROM {subscriptions} WHERE module = '%s' AND field = '%s' AND value = '%s' AND author_uid = %d AND recipient_uid = %d", $args);
304 }
305 }
306 $form_state['redirect'] = str_replace('/subscribe', '', $_GET['q']);
307 }
308
309 /**
310 * Implementation of hook form_alter().
311 *
312 * Adds the Display Settings part to the admin/settings/subscriptions form.
313 *
314 * @ingroup hooks
315 * @ingroup form
316 */
317 function subscriptions_ui_form_subscriptions_settings_form_alter(&$form, &$form_state) {
318 global $user;
319 $tr = 't';
320
321 $form['display_settings'] = array(
322 '#type' => 'fieldset',
323 '#title' => t('Display settings'),
324 '#collapsible' => TRUE,
325 '#weight' => -4,
326 );
327 $form['display_settings']['subscriptions_form_in_block'] = array(
328 '#type' => 'radios',
329 '#title' => t('Node form position'),
330 '#options' => array(
331 t('Fieldset above node links (and comments)'), // 0
332 t('Fieldset in %block block (below the comments)', array('%block' => t('Subscriptions interface'))), // 1
333 ),
334 '#default_value' => variable_get('subscriptions_form_in_block', 0),
335 '#description' => t('How to display the subscriptions sub-form on node pages. Default is the first option.<br />To use the block, <b>you must enable the block</b> !here; put it into the %content region and set the %block_title to !none.', array('!here' => l(t('here'), 'admin/build/block'), '%content' => 'content', '%block_title' => $tr('Block title'), '!none' => '<em>&lt;none&gt;</em>')),
336 );
337 $form['display_settings']['subscriptions_form_link_only'] = array(
338 '#type' => 'radios',
339 '#title' => t('Node form visibility'),
340 '#options' => array(
341 t('Always display the fieldset'), // 0
342 t('Display only a @subscribe link that makes the fieldset visible', array('@subscribe' => t('Subscribe'))), // 1
343 ),
344 '#default_value' => variable_get('subscriptions_form_link_only', 0),
345 '#description' => t('What to display. Default is the first option.'),
346 );
347 $form['display_settings']['subscriptions_form_expanded'] = array(
348 '#type' => 'checkbox',
349 '#title' => t('Expand the node form fieldset'),
350 '#default_value' => variable_get('subscriptions_form_expanded', 0),
351 '#description' => t('Displays the fieldset with the node page subscriptions sub-form in expanded state. Default is OFF.'),
352 );
353 $form['display_settings']['note'] = array(
354 '#value' => '<p>'. t("Note: Our <b>favorite display settings</b> are the exact opposites of the defaults, but we chose the defaults, because they work without enabling the Subscriptions block.") .'</p>',
355 );
356 $form['display_settings']['subscriptions_show_by_author_options'] = array(
357 '#type' => 'checkbox',
358 '#title' => t("Show 'by author' subscriptions options"),
359 '#default_value' => variable_get('subscriptions_show_by_author_options', 1),
360 '#description' => t("If you don't want your users to subscribe 'by author', then turn this off. Default is ON."),
361 );
362 }
363
364 /**
365 * Ask for permission to display the subscriptions interface
366 * for the given node.
367 *
368 * This should be used as follows:
369 * if (module_invoke('subscriptions_ui', 'get_permission_to_handle', $nid, 'mymodule') !== FALSE) {
370 * my_module_display_interface($nid);
371 * }
372 * and mymodule needs to implement hook_subscriptions_ui(), see below.
373 */
374 function subscriptions_ui_get_permission_to_handle($nid, $module)
375 {
376 if (subscriptions_node_is_blocked($nid) || !user_access('subscribe to content')) {
377 return FALSE;
378 }
379
380 static $permissions = array();
381 if (empty($permissions[$nid])) {
382 foreach (module_implements('subscriptions_ui') as $m) {
383 $perm = module_invoke($m, 'subscriptions_ui', $nid);
384 if (empty($permissions[$nid]) || $permissions[$nid]['priority'] < $perm['priority'] ) {
385 $permissions[$nid] = $perm;
386 }
387 }
388 }
389 return $permissions[$nid]['module'] == $module;
390 }
391
392 /**
393 * Implementation of hook_subscriptions_ui().
394 *
395 * subscriptions_ui is willing to handle all $nids.
396 * Other modules can return a higher priority with their name
397 * (or a different name!) depending on the $nid, $user, etc.
398 */
399 function subscriptions_ui_subscriptions_ui($nid)
400 {
401 return array('priority' => 0, 'module' => 'subscriptions_ui');
402 }

  ViewVC Help
Powered by ViewVC 1.1.2