subscriptions_ui.module in Subscriptions 2.0.x
Provides a user interface for Subscriptions.
File
subscriptions_ui/subscriptions_ui.moduleView source
<?php
/**
* @file
* Provides a user interface for Subscriptions.
*/
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\node\NodeInterface;
/**
* Implements hook_ENTITY_TYPE_view().
*/
function subscriptions_ui_node_view(array &$build, NodeInterface $node, EntityViewDisplayInterface $display, $view_mode) {
if ($view_mode != 'full') {
return;
}
if (!subscriptions_ui_can_subscribe($node)) {
return;
}
$config = \Drupal::config('subscriptions_ui.settings');
$form_in_block = $config
->get('form_in_block');
$link_only = $config
->get('link_only');
if (!$form_in_block) {
return;
}
if (!$link_only) {
return;
}
}
/**
* Implements hook_node_view().
*
* Inject the node subform or a 'Subscribe' link into node pages
* (depending on the Display Settings).
*
* @param object $node
* @param string $view_mode
* @param string $langcode
*
* @return
*
* @ingroup hooks
* @ingroup form
*/
function old_subscriptions_ui_node_view($node, $view_mode, $langcode) {
global $user;
if ($node->nid && $view_mode == 'full' && subscriptions_ui_can_subscribe()) {
$arg2 = subscriptions_arg(2);
$block = variable_get('subscriptions_form_in_block', 0);
$link = variable_get('subscriptions_form_link_only', 0);
if (!$block && (!$link && (empty($arg2) || $arg2 == 'view') || $link && $arg2 == 'subscribe')) {
if ($form = drupal_get_form('subscriptions_ui_node_form', $node, $arg2 == 'subscribe')) {
$node->content['subscriptions_ui'] = [
'subscriptions_ui_form' => $form,
'#weight' => 100,
];
return;
}
}
subscriptions_suspended($user->uid, TRUE);
if (variable_get('subscriptions_form_link_only', 0) && $arg2 != 'subscribe' && (!variable_get('subscriptions_avoid_empty_subscribe_links', 0) || module_invoke_all('subscriptions', 'node_options', $user, $node))) {
/** @var $blocked_types array */
$blocked_types = variable_get('subscriptions_blocked_content_types', []);
if (in_array($node->type, $blocked_types) && !user_access('subscribe to all content types')) {
return;
}
$node->content['links']['node']['#links']['subscriptions-subscribe'] = [
'href' => current_path() . '/subscribe',
'title' => t('Subscribe') . (in_array($node->type, $blocked_types) ? SUBSCRIPTIONS_UNAVAILABLE : ''),
'html' => TRUE,
'fragment' => 'subscribe',
'attributes' => [
'title' => t('Receive notifications about changes and/or comments to this page (and possibly similar pages).'),
],
];
}
}
}
/**
* Implements hook_block_info().
*
* Tell Drupal about the Subscriptions Interface block.
*
* @ingroup hooks
*/
function subscriptions_ui_block_info() {
$blocks[0]['info'] = t('Subscriptions interface');
$blocks[0]['cache'] = DRUPAL_CACHE_PER_PAGE;
$blocks[0]['region'] = 'content';
return $blocks;
}
/**
* Implements hook_block_view().
*
* Define the Subscriptions Interface block for node pages (depending on the
* Display Settings).
*
* @param int $delta
*
* @return array|null
*
* @ingroup hooks
*/
function subscriptions_ui_block_view($delta = 0) {
$arg2 = subscriptions_arg(2);
if (subscriptions_ui_can_subscribe() && variable_get('subscriptions_form_in_block', 0) && (!variable_get('subscriptions_form_link_only', 0) && (empty($arg2) || $arg2 == 'view') || variable_get('subscriptions_form_link_only', 0) && $arg2 == 'subscribe')) {
return [
'subject' => t('Subscriptions'),
'content' => drupal_get_form('subscriptions_ui_node_form', menu_get_object()),
];
}
return NULL;
}
/**
* Checks if any other module wants to provide the UI.
*
* @param \Drupal\node\NodeInterface $node
* (optional) A node object. Defaults to NULL.
*
* @return bool
* Returns TRUE if no other module will provide the UI, FALSE otherwise.
*/
function subscriptions_ui_can_subscribe(NodeInterface $node = NULL) : bool {
$user = \Drupal::currentUser();
if (!$user
->isAuthenticated()) {
return FALSE;
}
if (empty($node)) {
return FALSE;
}
$permission = \Drupal::moduleHandler()
->invokeAll('subscriptions_ui_get_permission_to_handle', [
$node,
]);
$permission = array_filter($permission);
if (!empty($permission)) {
return FALSE;
}
}
/**
* Returns TRUE on node/NID pages if the NID is not blocked
* and no other module wants to provide the UI.
*
* @return bool
*/
function old_subscriptions_ui_can_subscribe() {
global $user;
$arg1 = subscriptions_arg(1, 'nid');
return $user->uid && subscriptions_arg(0) == 'node' && is_numeric($arg1) && module_invoke('subscriptions_ui', 'get_permission_to_handle', $arg1, 'subscriptions_ui') !== FALSE;
}
/**
* Returns the form definition for the node subform.
*
* @param $form
* @param $form_state
* @param $node
* Must be a valid node object.
* @param $expand
* Force the fieldset to expand if TRUE.
*
* @return array|null
*
* @ingroup form
* @ingroup hooks
*/
function subscriptions_ui_node_form($form, &$form_state, $node, $expand = NULL) {
global $user;
$account = $user;
$expand = $expand === TRUE || variable_get('subscriptions_form_expanded', 0);
if (subscriptions_node_is_blocked($node->nid)) {
return NULL;
}
/** @var $blocked_types array */
$blocked_types = variable_get('subscriptions_blocked_content_types', []);
if (in_array($node->type, $blocked_types)) {
if (!user_access('subscribe to all content types', $account)) {
return NULL;
}
$is_blocked = TRUE;
}
$show_node_info = variable_get('node_submitted_' . $node->type, 1);
$node_options = module_invoke_all('subscriptions', 'node_options', $account, $node);
// Allow other modules to alter the node options.
drupal_alter('subscriptions_node_options', $node_options);
if (!$node_options || !user_access('subscribe to content', $account)) {
return [];
}
uasort($node_options, '_subscriptions_cmp_by_weight');
foreach ([
db_query("SELECT sid, module, field, value, author_uid, send_interval, send_updates, send_comments FROM {subscriptions} WHERE module = :module AND field = :field AND value = :value AND recipient_uid = :recipient_uid", [
':module' => 'node',
':field' => 'nid',
':value' => $node->nid,
':recipient_uid' => $account->uid,
], [
'fetch' => PDO::FETCH_ASSOC,
]),
db_query("SELECT sid, module, field, value, author_uid, send_interval, send_updates, send_comments FROM {subscriptions} WHERE module = :module AND field <> :field AND recipient_uid = :recipient_uid", [
':module' => 'node',
':field' => 'nid',
':recipient_uid' => $account->uid,
], [
'fetch' => PDO::FETCH_ASSOC,
]),
] as $result) {
foreach ($result as $s) {
$subscriptions[$s['field']][$s['value']][$s['author_uid']] = $s;
}
}
// Process all options building the array of indexed params for each
$nonlabeled_options = $options = $params = $default_comments = $default_updates = $default_subscriptions = [];
$index = 1;
// If we start with zero, get some value sent as 0 => 0
$default_send_intervals = [];
foreach ($node_options as $field => $field_options) {
foreach ($field_options as $option) {
if (!is_array($option) || isset($option['#access']) && !$option['#access']) {
continue;
}
if ((!$show_node_info || !variable_get('subscriptions_show_by_author_options', 1)) && isset($option['params']['author_uid']) && $option['params']['author_uid'] >= 0) {
continue;
}
if ($option['params']['module'] == 'node' && $option['params']['field'] == 'type' && !empty($is_blocked)) {
$option['name'] .= ' ' . SUBSCRIPTIONS_UNAVAILABLE;
}
//$options[$index] = (isset($option['link']) ? l($option['name'], 'subscriptions/add/' . $option['link'], array('query' => drupal_get_destination(), 'html' => TRUE)) : $option['name']);
$options[$index] = $option['name'];
$nonlabeled_options[$index] = '';
$params[$index] = $param = $option['params'] + [
'author_uid' => -1,
];
if (isset($subscriptions[$param['field']][$param['value']][$param['author_uid']])) {
$default_subscriptions[] = $index;
$default_send_intervals[$index] = $subscriptions[$param['field']][$param['value']][$param['author_uid']]['send_interval'];
if ($subscriptions[$param['field']][$param['value']][$param['author_uid']]['send_comments']) {
$default_comments[] = $index;
}
if ($subscriptions[$param['field']][$param['value']][$param['author_uid']]['send_updates']) {
$default_updates[] = $index;
}
}
else {
$default_send_intervals[$index] = _subscriptions_get_setting('send_interval', $account);
if (_subscriptions_get_setting('send_comments', $account)) {
$default_comments[] = $index;
}
if (_subscriptions_get_setting('send_updates', $account)) {
$default_updates[] = $index;
}
}
$index++;
}
}
$form['params'] = [
'#type' => 'value',
'#value' => $params,
];
$form['wrapper'] = [
'#type' => 'fieldset',
'#title' => filter_xss(t('Subscribe') . (!empty($is_blocked) ? ' ' . SUBSCRIPTIONS_UNAVAILABLE : ''), [
'span',
]),
'#collapsible' => TRUE,
'#collapsed' => !$expand,
'#theme' => 'subscriptions_ui_table',
'#attributes' => [
'id' => 'subscribe',
],
];
$form['wrapper']['subscriptions'] = [
'#type' => 'checkboxes',
'#default_value' => $default_subscriptions,
'#options' => $options,
'#access' => TRUE,
];
$form['wrapper']['updates'] = [
'#type' => 'checkboxes',
'#default_value' => $default_updates,
'#options' => $nonlabeled_options,
'#access' => _subscriptions_get_setting('send_updates_visible', $user) > 0,
];
if (module_exists('comment') && user_access('access comments')) {
$form['wrapper']['comments'] = [
'#type' => 'checkboxes',
'#default_value' => $default_comments,
'#options' => $nonlabeled_options,
'#access' => _subscriptions_get_setting('send_comments_visible', $user) > 0,
];
}
$form['wrapper']['footer'] = [
'#type' => 'item',
'#description' => t('The master checkboxes in the left-most column turn the given subscription on or off. Depending on the setup of the site, you may have additional options for active subscriptions.'),
'#weight' => 9,
];
$form['wrapper']['submit'] = [
'#type' => 'submit',
'#value' => t('Save'),
'#weight' => 10,
];
$form['account'] = [
'#type' => 'value',
'#value' => $account,
];
$form['send_intervals'] = [
'#type' => 'value',
'#value' => $default_send_intervals,
];
return $form;
}
/**
* Implements hook_theme().
*
* @return array
*/
function subscriptions_ui_theme() {
return [
'subscriptions_ui_table' => [
'render element' => 'element',
],
];
}
/**
* Theme subscriptions node subform table.
*
* @param array $element
*
* @return string
*
* @ingroup themeable
*/
function theme_subscriptions_ui_table($element) {
$rows = [];
$headers = [];
$header_strings = [
[
'class' => 'subscriptions-table',
'width' => '30%',
],
[
'data' => t('On updates'),
'width' => '1*',
'style' => 'writing-mode: lr-tb',
],
[
'data' => t('On comments'),
],
];
$element = $element['element'];
foreach (element_children($element['subscriptions']) as $key) {
$row = [];
foreach ([
'subscriptions',
'updates',
'comments',
] as $eli => $elv) {
if (isset($element[$elv]) && $element[$elv]['#access']) {
$row[] = drupal_render($element[$elv][$key]);
$headers[$eli] = $header_strings[$eli];
}
}
$rows[] = $row;
}
$col_indexes = array_keys($headers);
unset($headers[end($col_indexes)]['width']);
$output = theme('table', [
'header' => $headers,
'rows' => $rows,
]);
$output .= drupal_render_children($element);
drupal_add_js(drupal_get_path('module', 'subscriptions') . '/subscriptions_tableselect.js');
return $output;
}
/**
* Node subscriptions node subform submit handler.
*
* @param array $form
* @param array $form_state
*
* @ingroup form
*/
function subscriptions_ui_node_form_submit(array $form, array &$form_state) {
$recipient_uid = $form_state['values']['account']->uid;
$default_send_intervals = $form_state['values']['send_intervals'];
foreach ($form_state['values']['subscriptions'] as $index => $value) {
$params = $form_state['values']['params'][$index];
$args = [
$params['module'],
$params['field'],
$params['value'],
$params['author_uid'],
$recipient_uid,
];
if ($value) {
$args[] = $default_send_intervals[$index];
$args[] = !empty($form_state['values']['updates'][$index]);
$args[] = !empty($form_state['values']['comments'][$index]);
call_user_func_array('subscriptions_write_subscription', $args);
}
else {
subscriptions_delete($args['4'], $args['0'], $args['1'], $args['2'], $args['3']);
}
}
$form_state['redirect'] = str_replace('/subscribe', '', current_path());
}
/**
* Implementation of hook form_alter().
*
* Adds the Display Settings part to the admin/settings/subscriptions form.
*
* @param array $form
* @param array $form_state
*
* @ingroup hooks
* @ingroup form
*/
function subscriptions_ui_form_subscriptions_settings_form_alter(array &$form, array &$form_state) {
$tr = 't';
$form['display_settings'] = [
'#type' => 'fieldset',
'#title' => t('Display settings'),
'#collapsible' => TRUE,
'#weight' => -4,
];
$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.', [
'!here' => l(t('here'), 'admin/structure/block'),
'%content' => 'content',
'%block_title' => $tr('Block title'),
'!none' => '<em><none></em>',
]);
$form['display_settings']['subscriptions_form_in_block'] = [
'#type' => 'radios',
'#title' => t('Node form position'),
'#options' => [
t('Fieldset above node links (and comments)'),
// 0
t('Fieldset in %block block (below the comments)', [
'%block' => t('Subscriptions interface'),
]),
],
'#default_value' => variable_get('subscriptions_form_in_block', 0),
'#description' => filter_xss($description, [
'a',
'br',
'b',
'em',
]),
];
$form['display_settings']['subscriptions_form_link_only'] = [
'#type' => 'radios',
'#title' => t('Node form visibility'),
'#options' => [
t('Always display the fieldset'),
// 0
t('Display only a @subscribe link that makes the fieldset visible', [
'@subscribe' => t('Subscribe'),
]),
],
'#default_value' => variable_get('subscriptions_form_link_only', 0),
'#description' => t('What to display. Default is the first option.'),
];
$form['display_settings']['subscriptions_form_expanded'] = [
'#type' => 'checkbox',
'#title' => t('Expand the node form fieldset'),
'#default_value' => variable_get('subscriptions_form_expanded', 0),
'#description' => t('Displays the fieldset with the node page subscriptions sub-form in expanded state. Default is OFF.'),
];
$form['display_settings']['note'] = [
'#markup' => '<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>',
];
$form['display_settings']['subscriptions_show_by_author_options'] = [
'#type' => 'checkbox',
'#title' => t("Show 'by author' subscriptions options"),
'#default_value' => variable_get('subscriptions_show_by_author_options', 1),
'#description' => t("If you don't want your users to subscribe 'by author', then turn this off. Default is ON."),
];
}
/**
* Asks for permission to display the subscriptions interface
* for the given node.
*
* This should be used as follows:
* if (module_invoke('subscriptions_ui', 'get_permission_to_handle', $nid,
* 'mymodule') !== FALSE) { my_module_display_interface($nid);
* }
* and mymodule needs to implement hook_subscriptions_ui(), see below.
*
* @param int $nid
* @param string $module
*
* @return bool
*/
function subscriptions_ui_get_permission_to_handle($nid, $module) {
if (subscriptions_node_is_blocked($nid) || !user_access('subscribe to content')) {
return FALSE;
}
static $permissions = [];
if (empty($permissions[$nid])) {
foreach (module_implements('subscriptions_ui') as $m) {
$perm = module_invoke($m, 'subscriptions_ui', $nid);
if (empty($permissions[$nid]) || $permissions[$nid]['priority'] < $perm['priority']) {
$permissions[$nid] = $perm;
}
}
}
return $permissions[$nid]['module'] == $module;
}
/**
* Implements hook_subscriptions_ui().
*
* subscriptions_ui is willing to handle all $nids.
* Other modules can return a higher priority with their name
* (or a different name!) depending on the $nid, $user, etc.
*
* @param int $nid
*
* @return array
*/
function subscriptions_ui_subscriptions_ui($nid) {
return [
'priority' => 0,
'module' => 'subscriptions_ui',
];
}
/**
* Implements hook_field_extra_fields().
*
* Enables CCK (admin/content/types/CONTENT_TYPE/fields) to configure the
* position of the Subscribe fieldset within the node.
*
* @return array
*
* @ingroup hooks
*/
function subscriptions_ui_field_extra_fields() {
$extra = [];
if (variable_get('subscriptions_form_in_block', 0)) {
$types = db_query("SELECT type FROM {block_node_type} WHERE module = :module AND delta = :delta", [
':module' => 'subscriptions_ui',
':delta' => 0,
])
->fetchCol();
if (empty($types)) {
$types = array_keys(node_type_get_types());
}
foreach ($types as $type) {
$extra['node'][$type]['display']['subscriptions_ui'] = [
'label' => t('Subscribe'),
'description' => t('!Subscriptions_UI module form.', [
'!Subscriptions_UI' => 'Subscriptions UI',
]),
'weight' => 100,
];
}
}
return $extra;
}
Functions
Name | Description |
---|---|
old_subscriptions_ui_can_subscribe | Returns TRUE on node/NID pages if the NID is not blocked and no other module wants to provide the UI. |
old_subscriptions_ui_node_view | Implements hook_node_view(). |
subscriptions_ui_block_info | Implements hook_block_info(). |
subscriptions_ui_block_view | Implements hook_block_view(). |
subscriptions_ui_can_subscribe | Checks if any other module wants to provide the UI. |
subscriptions_ui_field_extra_fields | Implements hook_field_extra_fields(). |
subscriptions_ui_form_subscriptions_settings_form_alter | Implementation of hook form_alter(). |
subscriptions_ui_get_permission_to_handle | Asks for permission to display the subscriptions interface for the given node. |
subscriptions_ui_node_form | Returns the form definition for the node subform. |
subscriptions_ui_node_form_submit | Node subscriptions node subform submit handler. |
subscriptions_ui_node_view | Implements hook_ENTITY_TYPE_view(). |
subscriptions_ui_subscriptions_ui | Implements hook_subscriptions_ui(). |
subscriptions_ui_theme | Implements hook_theme(). |
theme_subscriptions_ui_table | Theme subscriptions node subform table. |