nid && count(fasttoggle_get_options('node', $node))) {
$items[] = array(
'path' => 'node/'. arg(1) .'/toggle',
'title' => t('toggle'),
'callback' => 'fasttoggle_node_option',
'callback arguments' => array($node),
'access' => true,
'type' => MENU_CALLBACK,
);
}
}
// The callback for toggling user settings
elseif (arg(0) == 'admin' && arg(1) == 'user' && is_numeric(arg(2)) && arg(3) == 'toggle' && arg(4) != '') {
$user = user_load(array('uid' => arg(2)));
if ($user->uid && count(fasttoggle_get_options('user', $user))) {
$items[] = array(
'path' => 'admin/user/'. arg(2) .'/toggle',
'title' => t('status'),
'callback' => 'fasttoggle_user_option',
'callback arguments' => array($user),
'access' => true,
'type' => MENU_CALLBACK,
);
}
}
elseif (arg(0) == 'comment' && arg(1) == 'toggle' && is_numeric(arg(2)) && arg(3) != '') {
$comment = _comment_load(arg(2));
if ($comment->cid && count(fasttoggle_get_options('comment', $comment))) {
$items[] = array(
'path' => 'comment/toggle/'. arg(2),
'title' => t('status'),
'callback' => 'fasttoggle_comment_option',
'callback arguments' => array($comment),
'access' => true,
'type' => MENU_CALLBACK,
);
}
}
}
else {
$items[] = array(
'path' => 'admin/settings/fasttoggle',
'title' => t('Fasttoggle'),
'description' => t('Configure what fast toggling options are available.'),
'callback' => 'drupal_get_form',
'callback arguments' => array('fasttoggle_settings_form'),
);
}
return $items;
}
/**
* Implementation of hook_perm().
*/
function fasttoggle_perm() {
return array('promote posts', 'make posts sticky', 'moderate posts', 'moderate users', 'moderate comments', 'administer fasttoggle');
}
/**
* Implementation of hook_user().
*
* Add togglable links to user pages.
*/
function fasttoggle_user($type, &$edit, &$user) {
$settings = variable_get('fasttoggle_user_settings', array('status' => TRUE));
if ($type == 'view' && $settings['status'] && (user_access('administer users') || user_access('moderate users'))) {
return array(
t('Settings') => array(
'fasttoggle' => array(
'title' => '',
'value' => theme('links', fasttoggle_link('user', $user), array('class' => 'links inline')),
'class' => 'fasttoggle',
),
),
);
}
}
/**
* Implementation of hook_help().
*/
function fasttoggle_help($section) {
switch ($section) {
case 'admin/settings/fasttoggle':
return t('Configure what fast toggling options are available.');
break;
}
}
/**
* (Menu callback) Configures what fast toggling options are available.
*/
function fasttoggle_settings_form() {
$form = array();
$form['fasttoggle_label_style'] = array(
'#type' => 'radios',
'#title' => t('Label style'),
'#description' => t('Select what kind of labels you want for fasttoggle links. See the README.txt for information about providing your own labels.'),
'#options' => array(
FASTTOGGLE_LABEL_STATUS => t('Status (reflects the current state, e.g. "published", "active")'),
FASTTOGGLE_LABEL_ACTION => t('Action (shows what happens upon a click, e.g. "unpublish", "block")'),
),
'#default_value' => variable_get('fasttoggle_label_style', FASTTOGGLE_LABEL_STATUS),
);
$custom_labels = variable_get('fasttoggle_labels', '');
if (!empty($custom_labels)) {
$form['fasttoggle_label_style']['#options'][FASTTOGGLE_LABEL_CUSTOM] = t('Custom (configure in your settings.php)');
}
$form['nodes'] = array(
'#type' => 'fieldset',
'#title' => t('Posts'),
'#description' => t('Select what options for fast toggling of post settings are available.'),
'#access' => user_access('administer fasttoggle'),
);
$form['nodes']['fasttoggle_node_settings'] = array(
'#type' => 'checkboxes',
'#title' => t('Available settings'),
'#options' => array(
'status' => t('Status (published/unpublished)'),
'sticky' => t('Sticky (stays at the top of listings)'),
'promote' => t('Promoted (visible on the front page)'),
'comment' => t('Topic opened/closed (users are allowed/disallowed to post comments)'),
),
'#default_value' => array_keys(array_filter(variable_get('fasttoggle_node_settings', array('status' => TRUE, 'sticky' => TRUE, 'promote' => TRUE, 'comment' => FALSE)))),
);
$form['nodes']['help_text'] = array(
'#value' => t('Configure access restrictions for these settings on the access control page.', array('@url' => url('admin/user/access', NULL, 'module-fasttoggle'))),
'#prefix' => '
',
'#suffix' => '
',
);
$form['comments'] = array(
'#type' => 'fieldset',
'#title' => t('Comments'),
'#description' => t('Select what options for fast toggling of comment settings are available.'),
'#access' => user_access('administer fasttoggle'),
);
$form['comments']['fasttoggle_comment_settings'] = array(
'#type' => 'checkboxes',
'#title' => t('Available settings'),
'#options' => array(
'status' => t('Status (published/unpublished)'),
),
'#default_value' => array_keys(array_filter(variable_get('fasttoggle_comment_settings', array('status' => TRUE)))),
);
$form['comments']['help_text'] = array(
'#value' => t('Configure access restrictions for these settings on the access control page.', array('@url' => url('admin/user/access', NULL, 'module-fasttoggle'))),
'#prefix' => '',
'#suffix' => '
',
);
$form['users'] = array(
'#type' => 'fieldset',
'#title' => t('Users'),
'#description' => t('Select what options for fast toggling of user settings are available.'),
'#access' => user_access('administer fasttoggle'),
);
$form['users']['fasttoggle_user_settings'] = array(
'#type' => 'checkboxes',
'#title' => t('Available settings'),
'#options' => array(
'status' => t('Status (unblocked/blocked)'),
),
'#default_value' => array_keys(array_filter(variable_get('fasttoggle_user_settings', array('status' => TRUE)))),
);
$form['users']['help_text'] = array(
'#value' => t('Get a listing of all users on the user overview page.', array('@url' => 'admin/user/user')),
'#prefix' => '',
'#suffix' => '
',
);
return system_settings_form($form);
}
/**
* 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.
*
* @return
* Either a complete HTML link or a link array structure for use in hook_link.
*/
function fasttoggle($title, $callback, $html = true, $token = '') {
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', 'title' => t('Toggle this setting'));
$query = drupal_get_destination() .'&token='. drupal_get_token($token);
if ($html) {
return l($title, $callback, $attributes, $query);
}
else {
return array('title' => $title, 'href' => $callback, 'query' => $query, 'attributes' => $attributes);
}
}
/**
* 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);
}
/**
* Implementation of hook_fasttoggle_options().
*/
function fasttoggle_fasttoggle_options($type, $obj = NULL) {
$return = array();
switch ($type) {
case 'node': // $obj = node
$admin = user_access('administer nodes');
// Get an array with all enabled fast toggle links
$settings = variable_get('fasttoggle_node_settings', array('status' => TRUE, 'sticky' => TRUE, 'promote' => TRUE, 'comment' => FALSE));
if ($settings['status'] && ($admin || user_access('moderate posts'))) {
$return['status'] = _fasttoggle_get_label('node_status');
}
if ($settings['sticky'] && ($admin || user_access('make posts sticky'))) {
$return['sticky'] = _fasttoggle_get_label('node_sticky');
}
if ($settings['promote'] && ($admin || user_access('promote posts'))) {
$return['promote'] = _fasttoggle_get_label('node_promote');
}
if (module_exists('comment') && $settings['comment'] && ($admin || user_access('administer comments'))) {
$return['comment'] = _fasttoggle_get_label('comment_admin');
}
break;
case 'user': // $obj = user
// Get an array with all enabled fast toggle links
$settings = variable_get('fasttoggle_user_settings', array('status' => TRUE));
if ($settings['status'] && (user_access('administer users') || user_access('moderate users'))) {
$return['status'] = _fasttoggle_get_label('user_status');
}
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'] = _fasttoggle_get_label('comment_status');
}
break;
}
return $return;
}
/**
* Implementation of hook_form_alter().
*/
function fasttoggle_form_alter($form_id, &$form) {
switch ($form_id) {
case 'node_admin_nodes':
// Add published/unpublished toggle links to the node overview page.
if (isset($form['status'])) {
foreach ($form['status'] as $key => $status) {
$form['status'][$key]['#value'] = fasttoggle($status['#value'], 'node/'. $key .'/toggle/status', true, 'status_'. $key);
}
}
break;
case 'user_admin_account':
// Add blocked/unblocked toggle links to the user overview page.
if (isset($form['status'])) {
foreach ($form['status'] as $key => $status) {
$form['status'][$key]['#value'] = fasttoggle($status['#value'], 'admin/user/'. $key .'/toggle/status', true, 'status_'. $key);
}
}
break;
}
}
/**
* 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 (array_keys($options) as $key) {
$links['fasttoggle_'. $key] = fasttoggle($options[$key][intval($obj->$key)], 'node/'. $obj->nid .'/toggle/'. $key, false, $key .'_'. $obj->nid);
}
break;
case 'comment':
foreach (array_keys($options) as $key) {
$links['fasttoggle_'. $key] = fasttoggle($options[$key][intval($obj->$key)], 'comment/toggle/'. $obj->cid .'/'. $key, false, $key .'_'. $obj->cid);
}
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 (array_keys($options) as $key) {
$links['fasttoggle_'. $key] = fasttoggle($options[$key][intval($obj->$key)], 'admin/user/'. $obj->uid .'/toggle/'. $key, false, $key .'_'. $obj->uid);
}
break;
}
}
return $links;
}
/**
* Menu callback. Toggle options for a node if the action is confirmed via
* POST. Otherwise, display a confirmation form.
*/
function fasttoggle_node_option($node, $option) {
$options = fasttoggle_get_options('node', $node);
// Check if the action is valid. This is essential to ensure the user has
// access to the action.
if (isset($options[$option]) && isset($_GET['token']) && drupal_valid_token($_GET['token'], $option .'_'. $node->nid, true)) {
// The action is confirmed: either via form submit or via AJAX/POST
if (isset($_POST['confirm']) && $_POST['confirm']) {
// Get the next ID.
while(key($options[$option]) != $node->$option) next($options[$option]);
if (next($options[$option]) === FALSE) reset($options[$option]);
// Save the node.
$node->$option = key($options[$option]);
node_save($node);
// Output the new status for the updated link text on AJAX changes
if (isset($_POST['javascript']) && $_POST['javascript']) {
drupal_set_header('Content-Type: text/javascript; charset=utf-8');
echo drupal_to_js(array(
'text' => $options[$option][intval($node->$option)],
'callback' => 'node',
'option' => $option,
'status' => $node->$option,
));
exit;
}
else {
drupal_goto();
}
}
else {
// The action is not confirmed. The user came here through a regular link;
// no AJAX was involved. That means, we need a confirmation form so that
// we get a POST form.
return drupal_get_form('fasttoggle_node_option_confirm', $node, $options[$option][intval(!$node->$option)]);
}
}
else {
return MENU_NOT_FOUND;
}
}
/**
* Confirmation form for the option change of a node.
*/
function fasttoggle_node_option_confirm($node, $option) {
return confirm_form(array(),
t('Are you sure you want to set the post %title to %option?', array('%title' => $node->title, '%option' => $option)),
$_GET['destination'] ? $_GET['destination'] : 'node/'. $node->nid,
'',
t('Change'), t('Cancel')
);
}
/**
* Menu callback. Toggle the status of a user if the action is confirmed via
* POST. Otherwise, display a confirmation form.
*/
function fasttoggle_user_option($user, $option) {
$options = fasttoggle_get_options('user', $user);
// Check if the action is valid. This is essential to ensure the user has
// access to the action.
if (isset($options[$option]) && isset($_GET['token']) && drupal_valid_token($_GET['token'], $option .'_'. $user->uid, true)) {
if (isset($_POST['confirm']) && $_POST['confirm']) {
$array = array($option => !$user->$option);
$user = user_save($user, $array);
// Output the new option for the updated link text on AJAX changes
if (isset($_POST['javascript']) && $_POST['javascript']) {
drupal_set_header('Content-Type: text/javascript; charset=utf-8');
echo drupal_to_js(array(
'text' => $options[$option][intval($array[$option])],
));
exit;
}
else {
drupal_goto();
}
}
else {
// The action is not confirmed. The user came here through a regular link;
// no AJAX was involved. That means, we need a confirmation form so that
// we get a POST form.
return drupal_get_form('fasttoggle_user_option_confirm', $user, $options[$option][intval($array[$option])]);
}
}
else {
return MENU_NOT_FOUND;
}
}
/**
* Confirmation form for the status change of a user.
*/
function fasttoggle_user_option_confirm($user, $option) {
return confirm_form(array(),
t('Are you sure you want to set the user %user to %option?', array('%user' => $user->name, '%option' => $option)),
$_GET['destination'] ? $_GET['destination'] : 'user/'. $user->uid,
'',
t('Change'), t('Cancel')
);
}
/**
* Menu callback. Toggle options for a comment if the action is confirmed via
* POST. Otherwise, display a confirmation form.
*/
function fasttoggle_comment_option($comment, $option) {
$options = fasttoggle_get_options('comment', $comment);
// Check if the action is valid. This is essential to ensure the user has
// access to the action.
if (isset($options[$option]) && isset($_GET['token']) && drupal_valid_token($_GET['token'], $option .'_'. $comment->cid, true)) {
// The action is confirmed: either via form submit or via AJAX/POST
if (isset($_POST['confirm']) && $_POST['confirm']) {
$comment->$option = !$comment->$option;
comment_save((array)$comment);
// Output the new status for the updated link text on AJAX changes
if (isset($_POST['javascript']) && $_POST['javascript']) {
drupal_set_header('Content-Type: text/javascript; charset=utf-8');
echo drupal_to_js(array(
'text' => $options[$option][intval($comment->$option)],
'callback' => 'comment',
'option' => $option,
'status' => $comment->$option,
));
exit;
}
else {
drupal_goto();
}
}
else {
// The action is not confirmed. The user came here through a regular link;
// no AJAX was involved. That means, we need a confirmation form so that
// we get a POST form.
return drupal_get_form('fasttoggle_comment_option_confirm', $comment, $options[$option][intval(!$comment->$option)]);
}
}
else {
return MENU_NOT_FOUND;
}
}
/**
* Confirmation form for the option change of a comment.
*/
function fasttoggle_comment_option_confirm($comment, $option) {
return confirm_form(array(),
t('Are you sure you want to set the comment %title to %option?', array('%title' => $comment->subject, '%option' => $option)),
$_GET['destination'] ? $_GET['destination'] : 'comment/'. $comment->cid,
'',
t('Change'), t('Cancel')
);
}
/**
* 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')),
'comment_admin' => array(0 => t('lock comments'), 1 => t('unlock comments'), 2 => t('hide comments')),
'user_status' => array(0 => t('activate'), 1 => t('unblock')),
'comment_status' => array(0 => t('unpublish'), 1 => t('publish')),
);
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')),
'comment_admin' => 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')),
);
break;
}
return $labels;
}
/**
* Returns an array with labels for a given setting.
*/
function _fasttoggle_get_label($label) {
static $labels;
if ($labels == NULL) {
$style = variable_get('fasttoggle_label_style', FASTTOGGLE_LABEL_STATUS);
$labels = module_invoke_all('fasttoggle_labels', $style);
// Allow custom labels in settings.php.
if ($style == FASTTOGGLE_LABEL_CUSTOM) {
$labels = array_merge($labels, variable_get('fasttoggle_labels', array()));
}
}
return $labels[$label];
}
/**
* Implementation of hook_views_tables().
*/
function fasttoggle_views_tables() {
$tables['fasttoggle'] = array(
'fields' => array(
'fasttoggle' => array(
'name' => t('Node: Fasttoggle'),
'handler' => 'fasttoggle_handler_field',
'query_handler' => 'fasttoggle_node_query_handler',
'sortable' => false,
'option' => array(
'#type' => 'select',
'#options' => array(
'status' => t('Status'),
'promote' => t('Promoted'),
'sticky' => t('Sticky'),
'comment' => t('Comment settings'),
),
),
'notafield' => 'true',
'help' => t('This field contains a fasttoggle link for the selected action for the current node.'),
),
),
);
return $tables;
}
/**
* Views query callback.
*/
function fasttoggle_node_query_handler($fielddata, $fieldinfo, &$query) {
foreach(array('status', 'comment', 'promote', 'sticky') as $field) {
if (!in_array('node.'. $field, $query->fields)) {
$query->fields[] = 'node.'. $field;
}
}
}
/**
* Views handler callback.
*/
function fasttoggle_handler_field($fieldinfo, $fielddata, $value, $data) {
$options = fasttoggle_get_options('node', $data);
$key = $fielddata['options'];
if (isset($options[$key]) && isset($data->$key)) {
return fasttoggle($options[$key][intval($data->$key)], 'node/'. $data->nid .'/toggle/'. $key, true, $key .'_'. $data->nid);
}
}