You are here

fasttoggle.module in Fasttoggle 6

Same filename and directory in other branches
  1. 8.3 fasttoggle.module
  2. 5 fasttoggle.module
  3. 7 fasttoggle.module

Enables fast toggling of binary or not so binary settings.

File

fasttoggle.module
View source
<?php

/**
 * @file
 * Enables fast toggling of binary or not so binary settings.
 */

/**
 * Displays the current state of a setting (e.g. "published", "active").
 */
define('FASTTOGGLE_LABEL_STATUS', 0x0);

/**
 * Displays the action that will be performed (e.g. "unpublish", "block").
 */
define('FASTTOGGLE_LABEL_ACTION', 0x1);

/**
 * Read custom strings from settings.php
 */
define('FASTTOGGLE_LABEL_CUSTOM', 0x2);
require_once drupal_get_path('module', 'fasttoggle') . '/fasttoggle.inc';

/**
 * Return a link in the resulting HTML format.
 */
define('FASTTOGGLE_FORMAT_HTML', 0x0);

/**
 * Return a link as the structure passed to l().
 */
define('FASTTOGGLE_FORMAT_LINK_ARRAY', 0x1);

/**
 * Return a link as the structure for a form build.
 */
define('FASTTOGGLE_FORMAT_FORM', 0x2);

/**
 * Implementation of hook_menu().
 */
function fasttoggle_menu() {
  $items = array();
  $items['admin/settings/fasttoggle'] = array(
    'title' => 'Fasttoggle',
    'description' => 'Configure what fast toggling options are available.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'fasttoggle_settings_form',
    ),
    'file' => 'fasttoggle.admin.inc',
    'access arguments' => array(
      'administer fasttoggle',
    ),
  );
  $items['node/%node/toggle/%/%'] = array(
    'title' => 'Toggle',
    'page callback' => 'fasttoggle_node_option',
    'page arguments' => array(
      1,
      3,
      4,
    ),
    'access callback' => TRUE,
    // Access checking is handled in hook_fasttoggle_options().
    'type' => MENU_CALLBACK,
    'file' => 'fasttoggle.toggle.inc',
  );
  $items['user/%user/toggle/%/%'] = array(
    'title' => 'Toggle',
    'page callback' => 'fasttoggle_user_option',
    'page arguments' => array(
      1,
      3,
      4,
    ),
    'access callback' => TRUE,
    // Access checking is handled in hook_fasttoggle_options().
    'type' => MENU_CALLBACK,
    'file' => 'fasttoggle.toggle.inc',
  );

  // Note: _comment is required so that it maps to _comment_load
  $items['comment/%_comment/toggle/%/%'] = array(
    'title' => 'Toggle',
    'page callback' => 'fasttoggle_comment_option',
    'page arguments' => array(
      1,
      3,
      4,
    ),
    'access callback' => TRUE,
    // Access checking is handled in hook_fasttoggle_options().
    'type' => MENU_CALLBACK,
    'file' => 'fasttoggle.toggle.inc',
  );
  return $items;
}
function fasttoggle_role_permission($role) {
  return t("toggle role '" . $role . "'");
}

/**
 * Implementation of hook_perm().
 */
function fasttoggle_perm() {
  $available_roles = fasttoggle_sitewide_toggleable_roles();
  $roles = array();
  if (!empty($available_roles)) {
    foreach ($available_roles as $key => $name) {
      $roles[] = fasttoggle_role_permission($name);
    }
  }
  $fixed_roles = array(
    'promote posts',
    'make posts sticky',
    'moderate posts',
    'moderate users',
    'moderate comments',
    'administer fasttoggle',
  );
  $result = array_merge($roles, $fixed_roles);
  asort($result);
  return $result;
}

/**
 * Implementation of hook_user().
 *
 * Add togglable links to user pages.
 */
function fasttoggle_user($op, &$edit, &$account) {
  if ($op == 'view') {
    $links = fasttoggle_link('user', $account, TRUE);
    if (!empty($links['fasttoggle_status'])) {
      $link = $links['fasttoggle_status'];
      $account->content['fasttoggle'] = array(
        '#value' => t('Status') . ': ' . l($link['title'], $link['href'], $link),
      );
      unset($links['fasttoggle_status']);
    }
    if (!empty($links)) {
      foreach ($links as $name => $link) {
        $account->content[$name] = array(
          '#value' => t('Role') . ': ' . l($link['title'], $link['href'], $link),
        );
      }
    }
  }
}

/**
 * Implementation of hook_help().
 */
function fasttoggle_help($path, $arg) {
  switch ($path) {
    case 'admin/settings/fasttoggle':
      return t('Configure what fast toggling options are available.');
      break;
  }
}

/**
 * Add fasttoggle abilities to a link
 *
 * @param $title
 *   The caption of the link
 * @param $callback
 *   The callback URL that will be the queried when the user clicks on that link.
 *   If queried via JS, it should perform the action because $_POST['confirm']
 *   is set to true. Return a JSON structure that has the key 'text' that contains
 *   the updatd link text.
 *   If the action is not confirmed, return a rendered confirmation form.
 *   If you return JSON in your callback function, set the content type of the
 *   header to text/javascript and the encoding to utf-8. Currently, only one
 *   JSON parameter is used: text.
 * @param $html
 *   (optional; defaults to true) Set whether this function should return a the
 *   HTML code for the fast toggle link or a link structure for use in hook_link
 *   hooks.
 * @param $token
 *   (optional; defaults to an empty string) Provide a salt for the token
 *   authentification added to each toggle link. If the string is empty, the
 *   generic token for the user on this site is used.
 * @param $selector_class
 *   Add a class name to the link so that it can be uniquely identified when
 *   replacing the link during subsequent invocations of the fasttoggle
 *   functionality.
 * @param $class
 *   (optional; defaults to an empty string) Add a class name to the link so
 *   that it can be styled with CSS.
 *
 * @return
 *   Either a complete HTML link or a link array structure for use in hook_link.
 */
function fasttoggle($title, $callback, $format = FASTTOGGLE_FORMAT_HTML, $token = '', $selector_class = '', $class = '') {
  static $sent = FALSE;

  // Only include the support files once.
  if (!$sent) {
    $sent = TRUE;
    drupal_add_js(drupal_get_path('module', 'fasttoggle') . '/fasttoggle.js');
    drupal_add_css(drupal_get_path('module', 'fasttoggle') . '/fasttoggle.css', 'module', 'all', FALSE);
  }
  $attributes = array(
    'class' => 'fasttoggle' . (!empty($selector_class) ? ' ' . $selector_class : '') . (!empty($class) ? ' ' . $class : ''),
    'title' => t('Toggle this setting'),
  );
  $query = drupal_get_destination() . '&token=' . drupal_get_token($token);
  switch ($format) {
    case FASTTOGGLE_FORMAT_HTML:
      return l($title, $callback, array(
        'attributes' => $attributes,
        'query' => $query,
      ));
    case FASTTOGGLE_FORMAT_LINK_ARRAY:
      return array(
        'title' => $title,
        'href' => $callback,
        'query' => $query,
        'attributes' => $attributes,
      );
    case FASTTOGGLE_FORMAT_FORM:
      return array(
        '#type' => 'link',
        '#title' => $title,
        '#href' => $callback,
        '#options' => array(
          'query' => $query,
          'attributes' => $attributes,
        ),
      );
  }
}

/**
 * Enable modules to add properties to comments through hook_comment().
 *
 * To support toggling, a property needs to be loaded onto the base object.
 * hook_nodeapi() and hook_user() support a 'load' op but _comment_load()
 * loads data only from the comments table. This function allows modules
 * to load properties onto comments through a 'load' op in hook_comment()
 * and hence to produce custom comment properties that support toggling.
 */
function fasttoggle_load_comment(&$comment) {
  if ($extra = comment_invoke_comment($comment, 'load')) {
    foreach ($extra as $key => $value) {
      $comment->{$key} = $value;
    }
  }
}

/**
 * Return an array of toggleable options of the object and the name of each state.
 *
 * @param $type
 *   The object type the functions should return options for (e.g. node, comment, ...).
 * @param ...
 *   Parameters for the fasttoggle_options hook.
 */
function fasttoggle_get_options($type) {
  $args = func_get_args();
  array_unshift($args, 'fasttoggle_options');
  return call_user_func_array('module_invoke_all', $args);
}
function fasttoggle_get_user_option_value($user, $attribute_name) {
  return intval($user->{$attribute_name});
}
function fasttoggle_get_user_option_array($user, $option) {
  return array(
    $option => !$user->{$option},
  );
}
function fasttoggle_get_user_role_option_value($user, $attribute_name) {
  return intval(isset($user->roles[$attribute_name]));
}
function fasttoggle_get_user_role_array($user, $role) {
  $result = array(
    'roles' => $user->roles,
  );
  if (isset($user->roles[$role])) {
    unset($result['roles'][$role]);
  }
  else {
    $result['roles'][$role] = TRUE;
  }
  return $result;
}

/**
 * Implementation of hook_fasttoggle_options().
 */
function fasttoggle_fasttoggle_options($type, $obj) {
  $return = array();
  switch ($type) {
    case 'node':

      // $obj = node
      $allow = node_access('update', $obj);

      // Get an array with all enabled fast toggle links
      $settings = variable_get('fasttoggle_togglable_options_' . $obj->type, array());
      if (in_array('status', $settings) && $allow && user_access('moderate posts')) {
        $return['status']['status']['label'] = _fasttoggle_get_label('node_status');
      }
      if (in_array('sticky', $settings) && $allow && user_access('make posts sticky')) {
        $return['status']['sticky']['label'] = _fasttoggle_get_label('node_sticky');
      }
      if (in_array('promote', $settings) && $allow && user_access('promote posts')) {
        $return['status']['promote']['label'] = _fasttoggle_get_label('node_promote');
      }
      if (in_array('comment', $settings) && $allow && module_exists('comment') && user_access('administer comments') && user_access('moderate comments')) {
        $return['status']['comment']['label'] = _fasttoggle_get_label('node_comment');
      }
      break;
    case 'user':

      // $obj = user
      // Get an array with all enabled fast toggle links
      $settings = variable_get('fasttoggle_user_settings', array(
        'status' => TRUE,
      ));
      $allow_u1 = variable_get('fasttoggle_allow_block_user1', 0);
      if (($obj->uid != 1 || $allow_u1) && $settings['status'] && (user_access('administer users') || user_access('moderate users'))) {
        $return['status']['status']['label'] = _fasttoggle_get_label('user_status');
      }

      // Roles
      $available_roles = fasttoggle_user_toggleable_roles();
      $role_labels = _fasttoggle_get_label('role');
      foreach ($available_roles as $roleid => $rolename) {
        foreach ($role_labels as $key => $value) {
          $labels[$key] = $role_labels[$key] . $rolename;
        }
        $return['role'][$roleid]['label'] = $labels;
        $return['role'][$roleid]['role'] = $rolename;
        $return['role'][$roleid]['value_fn'] = 'fasttoggle_get_user_role_option_value';
        $return['role'][$roleid]['value_key'] = $roleid;
        $return['role'][$roleid]['array_fn'] = 'fasttoggle_get_user_role_array';
      }
      break;
    case 'comment':

      // $obj = comment
      // Get an array with all enabled fast toggle links
      $settings = variable_get('fasttoggle_comment_settings', array(
        'status' => TRUE,
      ));
      if ($settings['status'] && user_access('administer comments') && user_access('moderate comments')) {
        $return['status']['status']['label'] = _fasttoggle_get_label('comment_status');
      }
      break;
  }
  return $return;
}

/**
 * Implementation of hook_form_alter().
 */
function fasttoggle_form_alter(&$form, $form_state, $form_id) {
  switch ($form_id) {
    case 'node_admin_content':

      // Add published/unpublished toggle links to the node overview page.
      if (variable_get('fasttoggle_enhance_node_overview_page', 0) && isset($form['admin']['nodes']['#options']) && user_access('moderate posts')) {
        $labels = _fasttoggle_get_label('node_status');
        foreach ($form['admin']['status'] as $key => $detail) {
          $node = node_load($key);
          if (node_access('update', $node)) {
            $status = intval($detail['#value'] == t('published'));

            // Get an array with all enabled fast toggle links
            $settings = variable_get('fasttoggle_togglable_options_' . $node->type, array());
            if (in_array('status', $settings) && user_access('moderate posts')) {
              $form['admin']['status'][$key]['#value'] = fasttoggle($labels[$status], 'node/' . $key . '/toggle/status/status', FASTTOGGLE_FORMAT_HTML, 'status_status_' . $key, 'fasttoggle-status-node-' . $key . '-status-status', 'fasttoggle-status-node-status-status-' . $status);
            }
          }
        }
      }
      break;
    case 'user_admin_account':

      // Add blocked/unblocked toggle links to the user overview page.
      $settings = variable_get('fasttoggle_user_settings', array(
        'status' => TRUE,
      ));
      if (variable_get('fasttoggle_enhance_user_overview_page', 0) && $settings['status'] !== 0 && isset($form['status']) && (user_access('administer users') || user_access('moderate users'))) {
        $allow_u1 = variable_get('fasttoggle_allow_block_user1', 0);
        $labels = _fasttoggle_get_label('user_status');
        foreach ($form['status'] as $key => $data) {
          if ($key != 1 || $allow_u1) {
            $status = intval($data['#value'] == t('active'));
            $form['status'][$key]['#value'] = fasttoggle($labels[$status], 'user/' . $key . '/toggle/status/status', FASTTOGGLE_FORMAT_HTML, 'status_status_' . $key, 'fasttoggle-status-user-status-' . $key . '-status-status', 'fasttoggle-status-user-status-status-' . $status);
          }
        }
      }
      break;
  }
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Adds Fasttoggle settings to the node type form.
 */
function fasttoggle_form_node_type_form_alter(&$form, $form_state) {
  $type = $form['#node_type']->type;
  $options = $form['workflow']['node_options']['#options'];
  unset($options['revision']);
  if (module_exists('comment')) {
    $options['comment'] = t('Comment setting');
  }
  $form['fasttoggle'] = array(
    '#type' => 'fieldset',
    '#title' => t('Fasttoggle settings'),
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
    '#group' => 'additional_settings',
  );
  $form['fasttoggle']['fasttoggle_togglable_options'] = array(
    '#type' => 'checkboxes',
    '#title' => t('Togglable options'),
    '#default_value' => variable_get('fasttoggle_togglable_options_' . $type, array()),
    '#options' => $options,
    '#description' => t('The node options that can be toggled with Fasttoggle.'),
  );
  $form['fasttoggle']['fasttoggle_add_to_node_links'] = array(
    '#type' => 'checkboxes',
    '#title' => t('Add to node links'),
    '#default_value' => variable_get('fasttoggle_add_to_node_links_' . $type, array()),
    '#options' => $options,
    '#description' => t('Which options to add to node links.'),
    '#attached' => array(
      'js' => array(
        drupal_get_path('module', 'fasttoggle') . '/fasttoggle.js' => array(
          'type' => 'file',
        ),
      ),
    ),
  );
}

/**
 * Implementation of hook_link().
 */
function fasttoggle_link($type, $obj = NULL, $teaser = FALSE) {
  $links = array();
  $options = fasttoggle_get_options($type, $obj);
  if (!empty($options)) {
    switch ($type) {
      case 'node':
        foreach ($options as $group => $flags) {
          foreach ($flags as $key => $data) {
            $links['fasttoggle_' . $key] = fasttoggle($data['label'][intval($obj->{$key})], 'node/' . $obj->nid . '/toggle/status/' . $key, FASTTOGGLE_FORMAT_LINK_ARRAY, $group . '_' . $key . '_' . $obj->nid, 'fasttoggle-status-node-status-' . $key . '-' . intval($obj->{$key}));
          }
        }
        break;
      case 'comment':
        fasttoggle_load_comment($obj);
        foreach ($options as $group => $flags) {
          foreach ($flags as $key => $data) {
            $links['fasttoggle_' . $key] = fasttoggle($data['label'][intval($obj->{$key})], 'comment/' . $obj->cid . '/toggle/status/' . $key, FASTTOGGLE_FORMAT_LINK_ARRAY, $group . '_' . $key . '_' . $obj->cid, 'fasttoggle-status-comment-status-' . $key . '-' . (1 - intval($obj->{$key})));
          }
        }
        break;

      // User is not one of the standard types for hook_link(). This
      // use enables adding of user links to a user profile.
      case 'user':
        foreach ($options as $group => $flags) {
          foreach ($flags as $key => $data) {
            if ($group == "role") {
              $rolename = $data['role'];
              $current_roles = array_flip($obj->roles);
              $current_state = isset($current_roles[$rolename]) ? 1 : 0;
              $links[$data['value_key']] = fasttoggle($data['label'][$current_state], 'user/' . $obj->uid . '/toggle/role/' . $data['value_key'], FASTTOGGLE_FORMAT_LINK_ARRAY, $group . '_' . $data['value_key'] . '_' . $obj->uid, 'fasttoggle-status-user-role-' . $data['value_key'] . '-' . $current_state);
            }
            else {
              $links['fasttoggle_' . $key] = fasttoggle($data['label'][intval($obj->{$key})], 'user/' . $obj->uid . '/toggle/' . $group . '/' . $key, FASTTOGGLE_FORMAT_LINK_ARRAY, $group . '_' . $key . '_' . $obj->uid, 'fasttoggle-status-user-status-' . $key . '-' . $obj->{$key});
            }
          }
        }
        break;
    }
  }
  return $links;
}

/**
 * Implementation of hook_fasttoggle_labels().
 */
function fasttoggle_fasttoggle_labels($style) {
  switch ($style) {
    case FASTTOGGLE_LABEL_ACTION:
      $labels = array(
        'node_status' => array(
          0 => t('publish'),
          1 => t('unpublish'),
        ),
        'node_sticky' => array(
          0 => t('make sticky'),
          1 => t('make unsticky'),
        ),
        'node_promote' => array(
          0 => t('promote'),
          1 => t('demote'),
        ),
        'node_comment' => array(
          0 => t('lock comments'),
          1 => t('unlock comments'),
          2 => t('hide comments'),
        ),
        'user_status' => array(
          0 => t('unblock'),
          1 => t('block'),
        ),
        'comment_status' => array(
          0 => t('unpublish'),
          1 => t('publish'),
        ),
        'role' => array(
          0 => t('add role '),
          1 => t('revoke role '),
        ),
      );
      break;
    default:
      $labels = array(
        'node_status' => array(
          0 => t('not published'),
          1 => t('published'),
        ),
        'node_sticky' => array(
          0 => t('not sticky'),
          1 => t('sticky'),
        ),
        'node_promote' => array(
          0 => t('not promoted'),
          1 => t('promoted'),
        ),
        'node_comment' => array(
          0 => t('comments disabled'),
          1 => t('comments read only'),
          2 => t('comments read/write'),
        ),
        'user_status' => array(
          0 => t('blocked'),
          1 => t('active'),
        ),
        'comment_status' => array(
          0 => t('published'),
          1 => t('not published'),
        ),
        'role' => array(
          0 => t('lacks role '),
          1 => t('has role '),
        ),
      );
      break;
  }
  return $labels;
}

/**
 * Returns an array with labels for a given setting.
 */
function _fasttoggle_get_label($label, $style = NULL) {
  static $labels = array();
  if (!isset($style)) {
    $style = variable_get('fasttoggle_label_style', FASTTOGGLE_LABEL_STATUS);
  }
  if (!isset($labels[$style])) {
    $labels[$style] = module_invoke_all('fasttoggle_labels', $style);

    // Allow custom labels in settings.php.
    if ($style == FASTTOGGLE_LABEL_CUSTOM) {
      $labels[$style] = array_merge($labels[$style], variable_get('fasttoggle_labels', array()));
    }
  }
  return $labels[$style][$label];
}
function fasttoggle_views_api() {
  return array(
    'api' => 2,
    'path' => drupal_get_path('module', 'fasttoggle') . '/views',
  );
}
function fasttoggle_menu_contextual_links_alter(&$links, $router_item, $root_path) {
  if ($root_path == 'node/%') {
    if (isset($router_item['map'][0]) && $router_item['map'][0] == 'node') {
      if (isset($router_item['map'][1]) && is_object($router_item['map'][1])) {
        $node = $router_item['map'][1];
        $options = fasttoggle_get_options('node', $node);
        $link_list = variable_get('fasttoggle_add_to_node_links_' . $node->type, array());
        $options = array_intersect_key($options, array_flip($link_list));
        foreach ($options as $group => $flags) {
          foreach ($flags as $key => $data) {
            $link = fasttoggle($data['label'][intval($node->{$key})], 'node/' . $node->nid . '/toggle/status/' . $key, FASTTOGGLE_FORMAT_LINK_ARRAY, $group . '_' . $key . '_' . $node->nid, 'fasttoggle-status-node-' . $node->nid . '-' . $group . '-' . $key, 'fasttoggle-status-node-' . $group . '-' . $key . '-' . $node->{$key});

            // massage to $link so it fits the expected format.
            $link['localized_options']['query'] = $link['query'];
            unset($link['query']);
            $link['localized_options']['attributes'] = $link['attributes'];
            unset($link['attributes']);
            $links['fasttoggle_' . $group . '_' . $key] = $link;
          }
        }
      }
    }
  }
}

Functions

Namesort descending Description
fasttoggle Add fasttoggle abilities to a link
fasttoggle_fasttoggle_labels Implementation of hook_fasttoggle_labels().
fasttoggle_fasttoggle_options Implementation of hook_fasttoggle_options().
fasttoggle_form_alter Implementation of hook_form_alter().
fasttoggle_form_node_type_form_alter Implements hook_form_FORM_ID_alter().
fasttoggle_get_options Return an array of toggleable options of the object and the name of each state.
fasttoggle_get_user_option_array
fasttoggle_get_user_option_value
fasttoggle_get_user_role_array
fasttoggle_get_user_role_option_value
fasttoggle_help Implementation of hook_help().
fasttoggle_link Implementation of hook_link().
fasttoggle_load_comment Enable modules to add properties to comments through hook_comment().
fasttoggle_menu Implementation of hook_menu().
fasttoggle_menu_contextual_links_alter
fasttoggle_perm Implementation of hook_perm().
fasttoggle_role_permission
fasttoggle_user Implementation of hook_user().
fasttoggle_views_api
_fasttoggle_get_label Returns an array with labels for a given setting.

Constants

Namesort descending Description
FASTTOGGLE_FORMAT_FORM Return a link as the structure for a form build.
FASTTOGGLE_FORMAT_HTML Return a link in the resulting HTML format.
FASTTOGGLE_FORMAT_LINK_ARRAY Return a link as the structure passed to l().
FASTTOGGLE_LABEL_ACTION Displays the action that will be performed (e.g. "unpublish", "block").
FASTTOGGLE_LABEL_CUSTOM Read custom strings from settings.php
FASTTOGGLE_LABEL_STATUS Displays the current state of a setting (e.g. "published", "active").