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) {
if ($type == 'view') {
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['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' => 'admin/user/access')),
'#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' => 'admin/user/access')),
'#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', null, null, 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) {
$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'] = array(0 => t('not published'), 1 => t('published'));
}
if ($settings['sticky'] && ($admin || user_access('make posts sticky'))) {
$return['sticky'] = array(0 => t('not sticky'), 1 => t('sticky'));
}
if ($settings['promote'] && ($admin || user_access('promote posts'))) {
$return['promote'] = array(0 => t('not promoted'), 1 => t('promoted'));
}
if (module_exists('comment') && $settings['comment'] && ($admin || user_access('administer comments'))) {
$return['comment'] = array(0 => t('comments disabled'), 1 => t('comments read only'), 2 => t('comments read/write'));
}
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'] = array(0 => t('blocked'), 1 => t('active'));
}
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'] = array(0 => t('published'), 1 => t('not published'));
}
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')
);
}