array( 'title' => t('Smartqueue per User'), 'description' => t('Provides a nodequeue for each user of one or more specified roles.'), ) ); } /** * Implementation of hook_nodequeue_form(). */ function smartqueue_users_nodequeue_form($queue, &$form) { $qid = $queue->qid; $form['placeholder']['smartqueue_users'] = array( '#type' => 'fieldset', '#title' => t('Smartqueue per user settings'), ); $form['placeholder']['smartqueue_users']['restrict_by_author'] = array( '#type' => 'checkbox', '#title' => t("Restrict contents of user nodequeue to content that is created by the nodequeue's owner"), '#description' => t("When this box is checked, each user subqueue can only contain content created by that subqueue's author."), '#default_value' => (int)_smartqueue_users_settings_get('restrict_by_author', $qid), ); $form['placeholder']['smartqueue_users']['subqueue_limit'] = array( '#type' => 'textfield', '#title' => t('Maximum number of subqueues per user'), '#description' => t('Set this to limit the number of subqueues a user can create. Leave blank or 0 for unlimited.'), '#default_value' => (int)_smartqueue_users_settings_get('subqueue_limit', $qid), '#maxlength' => 2, '#size' => 2, ); $form['placeholder']['smartqueue_users']['subqueue_privacy_default'] = array( '#type' => 'radios', '#title' => t('Default privacy of subqueues'), '#description' => t("Select the default privacy for each user's subqueues."), '#options' => _smartqueue_users_form_privacy_options(), '#default_value' => (int)_smartqueue_users_settings_get('subqueue_privacy_default', $qid), ); $form['placeholder']['smartqueue_users']['subqueue_privacy_changeable'] = array( '#type' => 'checkbox', '#title' => t('Users can change the default privacy on their own subqueues.'), '#default_value' => (int)_smartqueue_users_settings_get('subqueue_privacy_changeable', $qid), ); $form['placeholder']['smartqueue_users']['manipulation_method'] = array( '#type' => 'radios', '#title' => t('Manipulation method'), '#description' => t('Choose how the subqueue manipulation will be displayed at the bottom of the subqueue view page.'), '#options' => _smartqueue_users_form_manipulation_options(), '#default_value' => (int)_smartqueue_users_settings_get('manipulation_method', $qid), ); if (module_exists('views')) { $form['placeholder']['smartqueue_users']['view'] = array( '#type' => 'select', '#title' => t('Display view'), '#description' => t('Select the view to use for displaying the content of subqueues. It will use the "default" display and the Subqueue ID as the first parameter.'), '#options' => _smartqueue_users_views_options(), '#default_value' => _smartqueue_users_settings_get('view', $qid), ); } } /** * Implementation of hook_nodequeue_form_validate(). */ function smartqueue_users_nodequeue_form_validate(&$queue, $form_state, &$form) { // Validate that subqueue limit is either empty or a number. $subqueue_limit = $form_state['values']['subqueue_limit']; if (empty($subqueue_limit)) { $form_state['values']['subqueue_limit'] = 0; } else if (!is_numeric($subqueue_limit)) { form_set_error('subqueue_limit', t('The maximum number of subqueues per user must be a number or blank.')); } } /** * Implementation of hook_nodequeue_form_submit_finish(). */ function smartqueue_users_nodequeue_form_submit_finish(&$queue, $form_state) { $qid = $queue->qid; _smartqueue_users_settings_set('restrict_by_author', $qid, (bool)$form_state['values']['restrict_by_author']); _smartqueue_users_settings_set('subqueue_limit', $qid, (int)$form_state['values']['subqueue_limit']); _smartqueue_users_settings_set('subqueue_privacy_default', $qid, (int)$form_state['values']['subqueue_privacy_default']); _smartqueue_users_settings_set('subqueue_privacy_changeable', $qid, (bool)$form_state['values']['subqueue_privacy_changeable']); _smartqueue_users_settings_set('manipulation_method', $qid, (int)$form_state['values']['manipulation_method']); _smartqueue_users_settings_set('view', $qid, $form_state['values']['view']); } /** * Implementation of hook_queue_access(). */ function smartqueue_users_queue_access($queue, $account = NULL) { return (user_access('manipulate all queues', $account) || user_access('manipulate all user queues', $account) || user_access('manipulate own user queue', $account)); } /** * Implementation of hook_subqueue_access(). */ function smartqueue_users_subqueue_access($subqueue, $account, $queue) { // Load the subqueue's account. $subqueue_account = user_load(smartqueue_users_get_subqueue_owner($subqueue)); return smartqueue_users_can_manipulate($subqueue_account, $account); } /** * Implementation of hook_nodequeue_subqueues(). * * We provide only subqueues that belong to the current user, to * prevent too much subqueues from appearing. */ function smartqueue_users_nodequeue_subqueues(&$queue, $node) { global $user; if (($node->uid != $user->uid) && _smartqueue_users_settings_get('restrict_by_author', $queue->qid)) { // This queue restricts content of subqueues to same owners, and this node is not owned by $user. return FALSE; } return array_shift(smartqueue_users_get_subqueue_references($user, $queue)); } /** * Implementation of hook_nodequeue_autocomplete(). */ function smartqueue_users_nodequeue_autocomplete($queue, $subqueue, $string, $where, $where_args) { $matches = array(); // Add a filter to restrict by auther when relevant. if (_smartqueue_users_settings_get('restrict_by_author', $queue->qid)) { $where .= ' AND uid = %d'; $where_args[] = smartqueue_users_get_subqueue_owner($subqueue); } $result = db_query_range(db_rewrite_sql("SELECT n.nid, n.title FROM {node} n WHERE $where"), $where_args, 0, 10); while ($node = db_fetch_object($result)) { $matches[$node->nid] = check_plain($node->title) ." [nid: $node->nid]"; } return $matches; } /** * Implementation of hook_nodequeue_table(). */ function smartqueue_users_nodequeue_table($table_id, &$header, &$rows, &$attributes, &$caption, $queue = NULL, $subqueues = NULL) { if ($table_id == 'nodequeue_view_subqueues' && $queue->owner == 'smartqueue_users') { // Add Users column array_splice($header, -1, 0, t('User')); // Add the users to the Users column $i = 0; foreach ($subqueues as $subqueue) { $account = user_load(smartqueue_users_get_subqueue_owner($subqueue)); array_splice($rows[$i], -1, 0, theme('username', $account)); $i++; } } } /** * Menu hooks. */ /** * Implementation of hook_menu(). */ function smartqueue_users_menu() { $items = array(); $items['user/%user_uid_optional/queue'] = array( 'title' => 'My Queues', 'page arguments' => array(1), 'page callback' => 'smartqueue_users_profile_page', 'access arguments' => array(1), 'access callback' => 'user_view_access', 'type' => MENU_LOCAL_TASK | MENU_SUGGESTED_ITEM, 'file' => 'includes/pages.inc', ); $items['user/%user/queue/%nodequeue/add'] = array( 'title' => 'Add a subqueue to a user queue', 'page arguments' => array(1, 3), 'page callback' => 'smartqueue_users_subqueue_add', 'access arguments' => array(1), 'access callback' => 'smartqueue_users_can_manipulate', 'type' => MENU_CALLBACK, 'file' => 'includes/manipulate.inc', ); $items['user/%user/queue/%nodequeue/view/%subqueue'] = array( 'title' => 'View a subqueue from a user queue', 'page arguments' => array(1, 3, 5), 'page callback' => 'smartqueue_users_subqueue_view', 'access arguments' => array(1, 3, 5), 'access callback' => 'smartqueue_users_can_view', 'type' => MENU_CALLBACK, 'file' => 'includes/pages.inc', ); $items['user/%user/queue/%nodequeue/edit/%subqueue'] = array( 'title' => 'Edit a subqueue in a user queue', 'page arguments' => array(1, 3, 5), 'page callback' => 'smartqueue_users_subqueue_edit', 'access arguments' => array(1), 'access callback' => 'smartqueue_users_can_manipulate', 'type' => MENU_CALLBACK, 'file' => 'includes/manipulate.inc', ); $items['user/%user/queue/%nodequeue/delete/%subqueue'] = array( 'title' => 'Delete a subqueue from a user queue', 'page arguments' => array(1, 3, 5), 'page callback' => 'smartqueue_users_subqueue_remove', 'access arguments' => array(1), 'access callback' => 'smartqueue_users_can_manipulate', 'type' => MENU_CALLBACK, 'file' => 'includes/manipulate.inc', ); return $items; } /** * Theme hooks. */ /** * Implementation of hook_theme(). */ function smartqueue_users_theme($existing, $type, $theme, $path) { $path = drupal_get_path('module', 'smartqueue_users') . '/theme'; $base = array( 'file' => 'theme.inc', 'path' => $path, ); return array( 'smartqueue_users_profile_page' => $base + array( 'arguments' => array('account' => array(), 'queues' => array(), 'subqueues' => array()), 'template' => 'smartqueue-users-profile-page', ), 'smartqueue_users_subqueue_empty' => $base + array( 'arguments' => array('subqueue'), ), 'smartqueue_users_privacy' => $base + array( 'arguments' => array('privacy'), ), ); } /** * User hooks. */ /** * Implementation of hook_perm(). */ function smartqueue_users_perm() { return array('manipulate own user queue', 'manipulate all user queues'); } /** * Implementation of hook_user(). */ function smartqueue_users_user($op, &$edit, &$account, $category = NULL) { switch ($op) { case 'delete': // Remove all the subqueues that belong to this user. $db_result = db_query("SELECT sqid FROM {nodequeue_subqueue} WHERE reference LIKE '%d-%%' AND qid IN (SELECT qid FROM {nodequeue_queue} WHERE owner = 'smartqueue_users')", $account->uid); while ($sqid = db_result($db_result)) { smartqueue_users_remove_subqueue($sqid); } break; } } /** * Block hooks. */ /** * Implementation of hook_block(). */ function smartqueue_users_block($op = 'list', $delta = 0, $edit = array()) { switch ($op) { case 'list': return array( array( 'info' => t('User queues'), 'cache' => BLOCK_CACHE_PER_PAGE, 'title' => t('Queues'), ), ); break; case 'configure': $form = array(); if (user_access('use PHP for block visibility')) { $form['argument_php'] = array( '#type' => 'textarea', '#title' => t('Argument PHP'), '#description' => t('PHP code that returns a user ID. Return 0 to hide the block. You can use the arg() function to get URL arguments.'), '#default_value' => _smartqueue_users_variable_get('block_argument_php'), ); } else { $form['argument_php'] = array( '#type' => 'markup', '#value' => '
' . _smartqueue_users_variable_get('block_argument_php') . '
', '#prefix' => '
', '#suffix' => '
' . t('PHP code that returns a user ID. Only users with the use PHP for block visibility permissions can edit this.') . '
', ); } return $form; break; case 'save': _smartqueue_users_variable_set('block_argument_php', $edit['argument_php']); break; case 'view': // Get the URL from the PHP code $uid = drupal_eval(''); // If we got a relevant uid then we continue if (is_numeric($uid) && $uid > 0) { // Load the given account $account = user_load($uid); // Get the smartqueue_users queues. $queues = smartqueue_users_get_all_queues(); // Get the existing subqueues for each smartqueue_users queue. $subqueues = array(); foreach ($queues as $qid => $queue) { $subqueues[$qid] = nodequeue_load_subqueues_by_reference(smartqueue_users_get_subqueue_references($account, $queue)); // Add the privacy setting for each subqueue. foreach ($subqueues[$qid] as $sqid => $subqueue) { $subqueues[$qid][$sqid]->privacy = smartqueue_users_subqueue_get_privacy($subqueue); } } // Get the themed content. $content = theme('smartqueue_users_profile_page', $account, $queues, $subqueues); return array( 'subject' => t("!user's queues", array('!user' => $account->name)), 'content' => $content, ); } break; } } /** * External modules integration hooks. */ /** * Implementation of hook_views_api(). * * Integration with Views. */ function smartqueue_users_views_api() { return array( 'api' => 2.0, 'path' => drupal_get_path('module', 'smartqueue_users') .'/includes/views', ); } /** * User access related functions. */ /** * Check whether a given user account has reached the subqueue limit * for the given queue. * * @return * TRUE if the user has reached the limit. FALSE otherwise. */ function smartqueue_users_reached_subqueue_limit($uid, $qid) { // Get the subqueue limit setting for this queue. $limit = _smartqueue_users_settings_get('subqueue_limit', $qid); // $limit == 0 means no limit, so always false. if ($limit == 0) { return FALSE; } // Count how many subqueues exist for this user in this queue. $num_existing = db_result(db_query("SELECT COUNT(sqid) FROM {nodequeue_subqueue} WHERE qid = %d AND reference LIKE '%d-%%'", $qid, $uid)); return !($num_existing < $limit); } /** * Check whether a user can manipulate the the subqueues of the first argument account. */ function smartqueue_users_can_manipulate($subqueue_account, $checking_account = NULL) { // If no account to check against was provided, default to current user. if (empty($checking_account)) { global $user; $checking_account = $user; } $can_manipulate = user_access('manipulate all user queues', $checking_account) || user_access('manipulate all queues', $checking_account); $can_manipulate = $can_manipulate || (($subqueue_account->uid == $checking_account->uid) && user_access('manipulate own user queue', $checking_account)); return $can_manipulate; } /** * Check wether the current user can view the provided subqueue. */ function smartqueue_users_can_view($account, $queue, $subqueue) { $checking_account = $account; $subqueue_account = user_load(smartqueue_users_get_subqueue_owner($subqueue)); if ($subqueue->qid != $queue->qid) { return FALSE; // Sanity check. } if (_smartqueue_users_sanity_check($checking_account, $queue, $subqueue, TRUE)) { return TRUE; // Users can always view their own subqueues. } // Allow viewing for public subqueues. if (smartqueue_users_subqueue_get_privacy($subqueue) == SMARTQUEUE_USERS_PRIVACY_PUBLIC) { return TRUE; } // Allow viewing for users who can manipulate this user's subqueues. if (smartqueue_users_can_manipulate($subqueue_account, $checking_account)) { return TRUE; } // If all else fails, disallow viewing. return FALSE; } /** * Getters and filters for queues and subqueues lists. */ /** * Get all the queues that belong to smartqueue_users. * * @return * An array of queue objects where the key is the qid. */ function smartqueue_users_get_all_queues() { // Get a list of qids that belong to smartqueue_users. $db_result = db_query("SELECT qid FROM {nodequeue_queue} WHERE owner = 'smartqueue_users'"); $qids = array(); while ($qid = db_result($db_result)) { $qids[] = $qid; } return nodequeue_load_queues($qids); } /** * Filter out subqueues that are not viewable by the provided user. * * @param $account * The user account to check viewing permissions for. * @param $queue * The queue that the subqueues belong to. * @param $subqueues * A keyed array of subqueues. (sqid => subqueue object) * @return The $subqueues array without the unviewable subqueues. */ function smartqueue_users_subqueue_filter_viewable($account, $queue, $subqueues) { $filtered = array(); foreach ($subqueues as $sqid => $subqueue) { if (smartqueue_users_can_view($account, $queue, $subqueue)) { $filtered[$sqid] = $subqueue; } } return $filtered; } /** * Subqueue manipulators. */ /** * Set the privacy of a subqueue. */ function smartqueue_users_subqueue_set_privacy($subqueue, $privacy) { if (db_result(db_query('SELECT COUNT(privacy) FROM {smartqueue_users_subqueue} WHERE sqid = %d', $subqueue->sqid)) == 0) { db_query('INSERT INTO {smartqueue_users_subqueue} (sqid, privacy) VALUES (%d, %d)', $subqueue->sqid, $privacy); } else { db_query('UPDATE {smartqueue_users_subqueue} SET privacy = %d WHERE sqid = %d LIMIT 1', $privacy, $subqueue->sqid); } } /** * Get the privacy of a subqueue. */ function smartqueue_users_subqueue_get_privacy($subqueue) { // Only return a subqueue specific privacy setting if users can change the default privacy of subqueue in that queue. if (_smartqueue_users_settings_get('subqueue_privacy_changeable', $subqueue->qid)) { // If the result is a strict FALSE then there is no subqueue specific privacy setting. if (($privacy = db_result(db_query('SELECT privacy FROM {smartqueue_users_subqueue} WHERE sqid = %d', $subqueue->sqid))) !== FALSE) { return $privacy; } } // Otherwise, return the default privacy for subqueues in this queue return _smartqueue_users_settings_get('subqueue_privacy_default', $subqueue->qid); } /** * Removes a subqueue. */ function smartqueue_users_remove_subqueue($sqid) { nodequeue_remove_subqueue($sqid); db_query('DELETE FROM {smartqueue_users_subqueue} WHERE sqid = %d LIMIT 1', $sqid); } /** * Get the uid of this subqueue owner. */ function smartqueue_users_get_subqueue_owner($subqueue) { return (int)array_shift(explode('-', $subqueue->reference)); } /** * Calculate the next unique reference string for the provided uid/qid. */ function smartqueue_users_get_next_reference_string($uid, $qid) { $max_reference = db_result(db_query("SELECT MAX(reference) FROM {nodequeue_subqueue} WHERE qid = %d AND reference LIKE '%d-%%'", $qid, $uid)); $rfid = ((int)array_pop(explode('-', $max_reference))) + 1; return "$uid-$rfid"; } /** * Calculate an array to be used for nodequeue_load_subqueues_by_reference(). */ function smartqueue_users_get_subqueue_references($account, $queue) { $db_result = db_query("SELECT reference FROM {nodequeue_subqueue} WHERE qid = %d AND reference LIKE '%d-%%'", $queue->qid, $account->uid); $references = array($queue->qid => array()); while ($reference = db_result($db_result)) { $references[$queue->qid][] = $reference; } return $references; } /** * Private functions. */ /** * Sanity check. * This function check that the provided subqueue is a subqueue of * the provided queue, and that it references the provided account. * * If it isn't, then we probably shouldn't proceed, and we invoke a * 404. * If the return argument is set, simply return FALSE on error, * Otherwise, always return TRUE. */ function _smartqueue_users_sanity_check($account, $queue, $subqueue, $return = FALSE) { if ($subqueue->qid != $queue->qid || smartqueue_users_get_subqueue_owner($subqueue) != $account->uid) { if ($return) { return FALSE; } else { drupal_not_found(); } } return TRUE; } /** * Privacy options for the nodequeue form. */ function _smartqueue_users_form_privacy_options() { return array( SMARTQUEUE_USERS_PRIVACY_PUBLIC => t('Public'), SMARTQUEUE_USERS_PRIVACY_PRIVATE => t('Private'), ); } /** * Manipulation options for the nodequeue form. */ function _smartqueue_users_form_manipulation_options() { return array( SMARTQUEUE_USERS_MANIPULATION_UI => t("Inline (Nodequeue's default UI)"), SMARTQUEUE_USERS_MANIPULATION_LINK => t("External (Link to nodequeue's default UI)"), SMARTQUEUE_USERS_MANIPULATION_HIDDEN => t('Hidden (provide your own)'), ); } /** * Views options for the nodequeue form. */ function _smartqueue_users_views_options() { $views = array(-1 => t('-Default display-')); foreach (views_get_all_views() as $view_id => $view) { if ($view->base_table == 'node' && !$view->disabled) { $views[$view_id] = $view_id; } } return $views; } /** * Smartqueue per user's persistent variables helper getter function. */ function _smartqueue_users_variable_get($var) { // If a value is returned by variable_get, return that value if (($value = variable_get("smartqueue_users_$var", NULL)) !== NULL) { return $value; } // Otherwise, return the default value for this variable switch ($var) { case 'restrict_by_author': case 'subqueue_limit': case 'subqueue_privacy_default': case 'subqueue_privacy_changeable': case 'manipulation_method': case 'view': return array(); break; case 'block_argument_php': return "if (arg(0) == 'user' && is_numeric(arg(1))) {\n". " return arg(1);\n". "}\n". "return 0;"; default: return NULL; break; } } /** * Smartqueue per user's persistent variables helper setter function. */ function _smartqueue_users_variable_set($var, $value) { variable_set("smartqueue_users_$var", $value); } /** * Smartqueue per user's settings getter. */ function _smartqueue_users_settings_get($var, $qid) { $qid = (int)$qid; if ($qid) { // $qid is present, editing an existing nodequeue, get the settings $setting = _smartqueue_users_variable_get($var); if (isset($setting[$qid])) { return $setting[$qid]; } } // No $qid (new nodequeue) or no existing setting, get the defaults switch ($var) { case 'restrict_by_author': return FALSE; break; case 'subqueue_limit': return 1; break; case 'subqueue_privacy_default': return SMARTQUEUE_USERS_PRIVACY_PUBLIC; break; case 'subqueue_privacy_changeable': return FALSE; break; case 'manipulation_method': return SMARTQUEUE_USERS_MANIPULATION_UI; break; case 'view': return -1; break; } } /** * Smartqueue per user's settings setter. */ function _smartqueue_users_settings_set($var, $qid, $value) { $qid = (int)$qid; $setting = _smartqueue_users_variable_get($var); $setting[$qid] = $value; _smartqueue_users_variable_set($var, $setting); }