'Lists', 'page callback' => 'drupal_get_form', 'page arguments' => array('flag_lists_settings_form'), 'access callback' => 'user_access', 'access arguments' => array('administer flags'), 'description' => 'Configure default settings allowing users to mark content with personal flags.', 'file' => 'flag_lists.admin.inc', 'type' => MENU_LOCAL_TASK, 'weight' => 100, ); $items[FLAG_ADMIN_PATH . '/lists/settings'] = array( 'title' => 'Settings', 'page callback' => 'drupal_get_form', 'page arguments' => array('flag_lists_settings_form'), 'access callback' => 'user_access', 'access arguments' => array('administer flags'), 'description' => 'Configure default settings allowing users to mark content with personal flags.', 'file' => 'flag_lists.admin.inc', 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => 1, ); $items[FLAG_ADMIN_PATH . '/lists/list'] = array( 'title' => 'List', 'page callback' => 'flag_lists_admin_page', 'access callback' => 'user_access', 'access arguments' => array('administer flags'), 'file' => 'flag_lists.admin.inc', 'type' => MENU_LOCAL_TASK, 'weight' => 2, ); $items[FLAG_ADMIN_PATH . '/lists/template'] = array( 'title' => 'New template', 'page callback' => 'drupal_get_form', 'page arguments' => array('flag_lists_create_template_form'), 'access callback' => 'user_access', 'access arguments' => array('administer flags'), 'file' => 'flag_lists.admin.inc', 'type' => MENU_LOCAL_TASK, 'weight' => 3, ); if (module_exists('devel_generate')) { $items['admin/config/development/generate/flag-lists'] = array( 'title' => 'Generate lists', 'description' => 'Generate a given number of lists and listings on site content. Optionally delete existing lists and listings.', 'page callback' => 'drupal_get_form', 'page arguments' => array('flag_lists_generate_lists_form'), 'access callback' => 'user_access', 'access arguments' => array('administer flags'), 'file' => 'flag_lists.admin.inc', ); } $items['flag-lists/add/%'] = array( 'title' => 'Add a list', 'page callback' => 'flag_lists_add', 'page arguments' => array(2), 'access callback' => 'user_access', 'access arguments' => array('create flag lists'), 'file' => 'flag_lists.admin.inc', 'type' => MENU_NORMAL_ITEM, ); // Callback for adding a new list through JS $items['flag-lists/add/%/js'] = array( 'title' => 'Add a list', 'page callback' => 'flag_lists_add_js', 'page arguments' => array(2), 'access callback' => 'user_access', 'access arguments' => array('create flag lists'), 'file' => 'flag_lists.admin.inc', 'type' => MENU_CALLBACK, ); // Callback for autocomplete of lists in views filter $items['flag-lists/autocomplete_list_callback'] = array( 'title' => 'Find a list', 'page callback' => 'flag_lists_autocomplete_list_callback', 'access callback' => 'user_access', 'access arguments' => array('create flag lists'), 'file' => 'flag_lists.admin.inc', 'type' => MENU_CALLBACK, ); $items['flag/lists/edit/%'] = array( 'title' => 'Edit a list', 'page callback' => 'drupal_get_form', 'page arguments' => array('flag_lists_form', 3), 'access callback' => 'flag_lists_is_owner', 'access arguments' => array(2, 3), 'file' => 'flag_lists.admin.inc', 'type' => MENU_CALLBACK, ); $items['flag/lists/delete/%'] = array( 'title' => 'Delete a list', 'page callback' => 'drupal_get_form', 'page arguments' => array('flag_lists_delete_confirm', 3), 'access callback' => 'flag_lists_is_owner', 'access arguments' => array(2, 3), 'file' => 'flag_lists.admin.inc', 'type' => MENU_CALLBACK, ); $items[FLAG_ADMIN_PATH . '/flag-lists/rebuild'] = array( 'title' => 'Rebuild all flag lists', 'page callback' => 'drupal_get_form', 'page arguments' => array('flag_lists_rebuild_confirm'), 'access callback' => 'user_access', 'access arguments' => array('administer flag lists'), 'file' => 'flag_lists.admin.inc', 'type' => MENU_CALLBACK, ); $items['flag-lists'] = array( 'title' => 'Flag', 'page callback' => 'flag_lists_page', 'access callback' => 'user_access', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); $items['user/%user/flag/lists'] = array( 'title' =>drupal_ucfirst(variable_get('flag_lists_name', 'list')), 'page callback' => 'flag_lists_user_page', 'page arguments' => array(1), 'access callback' => 'user_access', 'access arguments' => array('view flag lists'), 'type' => MENU_LOCAL_TASK, ); $items['user/%user/flag/lists/%'] = array( 'title' =>drupal_ucfirst(variable_get('flag_lists_name', 'list') . ' ' . 'content'), 'page callback' => 'flag_lists_user_list', 'page arguments' => array(1, 4), 'access callback' => 'user_access', 'access arguments' => array('view flag lists'), 'type' => MENU_CALLBACK, ); return $items; } /** * User flag page. Display a list of user-created flag lists. */ function flag_lists_user_page($user) { // Can we use our default view? if (module_exists('views')) { $view = views_get_view('flag_lists_user_lists', FALSE); if (!empty($view)) { $view->set_display('default'); $view->set_arguments(array($user->uid)); $view->pre_execute(); $output = $view->render(); /* drupal_set_title(str_replace(array_keys($view->build_info['substitutions']), $view->build_info['substitutions'], $view->build_info['title'])); */ } return $output; } else { return theme('flag_lists_user_page', array('uid' => $user->uid)); } } /** * Theme the output for a user flag administration page. */ function theme_flag_lists_user_page($variables) { $uid = $variables['uid']; $account = user_load($uid); drupal_set_title(t('Lists')); if ($flags = flag_lists_get_user_flags(NULL, $account)) { // Build the list of flag lists for this node. foreach ($flags as $flag) { $ops = theme('flag_lists_ops', array('flag' => $flag)); $items[] = l($flag->title, "user/$uid/flag/lists/" . $flag->fid) . $ops; } } drupal_add_css(drupal_get_path('module', 'flag_lists') . '/theme/flag_lists.css'); return theme('item_list', array('items' => $items)); } /** * List the contents of a user-defined list */ function flag_lists_user_list($user, $fid) { $uid = $user->uid; // Can we use our default view? if (module_exists('views')) { $view = views_get_view('flag_lists_user_list', FALSE); if (!empty($view)) { $view->set_display('default'); $view->set_arguments(array($fid)); $view->pre_execute(); $output = $view->render(); drupal_set_title(str_replace(array_keys($view->build_info['substitutions']), $view->build_info['substitutions'], $view->build_info['title']), PASS_THROUGH); } return $output; } else { return theme('flag_lists_user_list', array('uid' => $uid, 'fid' => $fid)); } } /** * Theme the output of user-defined list page */ function theme_flag_lists_user_list($variables) { $uid = $variables['uid']; $fid = $variables['fid']; $flag = flag_lists_get_flag($fid); drupal_set_title($flag->title); $content = flag_lists_get_flagged_content($fid, $uid); foreach ($content as $item) { if ($item->entity_type == 'node') { $node = node_load($item->entity_id); $items[] = l($node->title, 'node/' . $node->nid); } } $breadcrumb = menu_get_active_breadcrumb(); $breadcrumb[] = l(t('@name lists', array('@name' => drupal_ucfirst(variable_get('flag_lists_name', 'list')))), 'user/' . arg(1) . '/flag/lists'); drupal_set_breadcrumb($breadcrumb); return theme('item_list', array('items' => $items)); } /** * Implementation of hook_theme(). */ function flag_lists_theme() { $path = drupal_get_path('module', 'flag') . '/theme'; return array( 'flag_lists_list' => array( 'variables' => array('node' => NULL, 'create' => NULL, 'ops' => NULL, 'use_flags' => NULL), ), 'flag_lists_admin_page' => array( 'variables' => array('flags' => NULL), ), 'flag_lists_user_page' => array( 'variables' => array('uid' => NULL), ), 'flag_lists_user_list' => array( 'variables' => array('flag_name' => NULL), ), 'flag_lists_ops' => array( 'variables' => array('flag' => NULL), ) ); } /** * Implementation of hook_permission(). */ function flag_lists_permission() { return array( 'create flag lists' => array( 'title' => t('Create flag lists'), 'description' => t(''), ), 'edit own flag lists' => array( 'title' => t('Edit own flag lists'), 'description' => t(''), ), 'delete own flag lists' => array( 'title' => t('Delete own flag lists'), 'description' => t(''), ), 'view flag lists' => array( 'title' => t('View flag lists'), 'description' => t(''), ) ); } /** * Implementation of hook_form_alter(). */ function flag_lists_form_alter(&$form, &$form_state, $form_id) { switch ($form_id) { case 'flag_form': // A template flag should always have a record in the flag_lists_types table. $result = db_select('flag_lists_types', 'f')->fields('f')->execute(); foreach ($result as $type) { $types[$type->name] = $type->type; } if (isset($types[$form['name']['#default_value']])) { $form['name']['#type'] = 'value'; $form['global']['#type'] = 'value'; $form['title']['#description'] = t('A short, descriptive title for this template. It will be used in administrative interfaces to refer to this template.'); // Warn about types that already have a template. foreach ($form['access']['types']['#options'] as $option => $value) { if (in_array($option, $types) && $form['access']['types']['#default_value'] != $option) { $form['access']['types']['#options'][$option] .= '' . t('(Already has a template.)') . ''; } } $form['access']['types']['#description'] .= t('A type may only be selected in one list template.'); // Unset anon permissions for now. @todo allow anon listing. unset($form['access']['roles']['flag']['#options'][1]); unset($form['access']['roles']['unflag']['#options'][1]); foreach (element_children($form['display']) as $display) { $form['display'][$display]['#type'] = 'value'; } $form['display']['link_type']['#default_value'] = 'fl_template'; $form['display']['#description'] = t('Unlike normal flags, lists are only displayed in a block provided by this module or in views blocks. See the block admin page to place the block.'); unset($form['display']['link_options_confirm']['flag_confirmation']); unset($form['display']['link_options_confirm']['unflag_confirmation']); $form['display']['link_options_intro']['#children'] = ''; $form['#validate'][] = 'flag_lists_template_validate'; $form['#submit'][] = 'flag_lists_template_submit'; } break; case 'views_exposed_form': // Force the exposed filters to perform actions on the page itself because // the views default viwe didn't come with a page display if ($form['#id'] == 'views-exposed-form-flag-lists-default') { $form['#action'] = '/' . implode('/', arg()); } break; } // Flag lists operations related changes if (strpos($form_id, 'views_form_') === 0) { $flo = _flag_lists_ops_get_field($form_state['build_info']['args'][0]); // Not a FLO-enabled views form. if (empty($flo)) { return; } // Add FLO's custom callbacks. $form['#validate'][] = 'flag_lists_ops_form_validate'; $form['#submit'][] = 'flag_lists_ops_form_submit'; // Allow FLO to work when embedded using views_embed_view(), or in a block. if (empty($flo->view->override_path)) { if (!empty($flo->view->preview) || $flo->view->display_handler instanceof views_plugin_display_block) { $flo->view->override_path = $_GET['q']; } } // Quickfix for FLO & exposed filters using ajax. See http://drupal.org/node/1191928. $query = drupal_get_query_parameters($_GET, array('q')); $form['#action'] = url($flo->view->get_url(), array('query' => $query)); // Add basic FLO functionality. if ($form_state['step'] == 'views_form_views_form') { $form = flag_lists_ops_form($form, $form_state, $flo); } } } /** * Add the Flag list select menu widget. */ function flag_lists_ops_form($form, &$form_state, $flo) { $form['#attached']['js'][] = drupal_get_path('module', 'flag_lists') . '/js/flag_lists_ops.js'; $form['#attached']['css'][] = drupal_get_path('module', 'flag_lists') . '/css/flag_lists_ops.css'; $form['#prefix'] = '
'; $form['#suffix'] = '
'; $form_state['flo_operation'] = $flo->options['flo']['operation']; // Force browser to reload the page if Back is hit. if (preg_match('/msie/i', $_SERVER['HTTP_USER_AGENT'])) { drupal_add_http_header('Cache-Control', 'no-cache'); // works for IE6+ } else { drupal_add_http_header('Cache-Control', 'no-store'); // works for Firefox and other browsers } global $user; global $base_url; $account = user_load($user->uid); $items = array(); if ($flags = flag_lists_get_user_flags(NULL, $account)) { // Build the list of flag lists for this node. foreach ($flags as $flag) { $items[((string) $flag->fid)] = $flag->title; } } // Group items into a fieldset for easier theming. $form['flag_lists_' . $form_state['flo_operation']] = array( '#type' => 'fieldset', '#title' => t('@name operations', array( '@name' => drupal_ucfirst( variable_get('flag_lists_name', 'list')))), '#tree' => TRUE, '#attributes' => array('class' => array('flag-lists-ops-fieldset')), ); switch ($flo->options['flo']['operation']) { case 'unflag': $null_text = t('Remove from a @name', array('@name' => variable_get('flag_lists_name', 'list'))); $operation = 'unflag'; $form['flag_lists_' . $form_state['flo_operation']]['list'] = array( '#type' => 'button', '#value' => t('Remove from @name', array('@name' => variable_get('flag_lists_name', 'list'))), '#ajax' => array( 'callback' => 'flag_lists_ops_form_ajax_callback', 'wrapper' => 'flag-list-ops-container-' . $flo->options['flo']['operation'], ), ); break; default: $null_text = t('Add to a @name', array('@name' => variable_get('flag_lists_name', 'list'))); $operation = 'flag'; drupal_add_library('system', 'ui.dialog'); $form['flag_lists_' . $form_state['flo_operation']]['list'] = array( '#type' => 'select', '#options' => array('0' => t('- ' . $null_text . ' -')) + $items, '#default_value' => '0', '#ajax' => array( 'callback' => 'flag_lists_ops_form_ajax_callback', 'wrapper' => 'flag-list-ops-container-' . $flo->options['flo']['operation'], ), '#attributes' => array( 'class' => array( 'flag-lists-ops-dropdown', ), ), ); // Add the necessary JS for creating a new list via AJAX $result = db_select('flag_lists_types') ->fields('flag_lists_types') ->execute(); $list_types = array(); foreach ($result as $row) { if (!empty($row->type)) { $list_types[] = $row->type; } } drupal_add_js(array('flag_lists' => array('types' => $list_types, 'json_path' => $base_url . '/flag-lists/add/%/js', 'listname' => variable_get('flag_lists_name', 'list'), 'form_token' => drupal_get_token(variable_get('flag_lists_name','list')))), 'setting'); break; } // Get the $ops from the originating form. if (!empty($form_state['values']['flag_lists_' . $form_state['flo_operation']]['list'])) { $list = $form_state['values']['flag_lists_' . $form_state['flo_operation']]['list']; } if (!empty($_REQUEST['flag_lists_ops'])) { $ops = $_REQUEST['flag_lists_ops']; $ops = is_array($ops) ? $ops : array($ops); } if (!empty($ops) && !empty($list) && $form_state['values']['flag_lists_' . $form_state['flo_operation']]['operation'] == 'unflag') { $hidden_deleted_values = ''; foreach ($ops as $nid) { $hidden_deleted_values .= ''; } } $form['flag_lists_' . $form_state['flo_operation']]['operation'] = array( '#type' => 'hidden', '#value' => $operation, ); $form['flag_lists_' . $form_state['flo_operation']]['go'] = array( '#type' => 'submit', '#value' => t('Go'), '#attributes' => array( 'class' => array('flag-lists-ops-go'), ), ); unset($form['actions']['submit']); // Generate a status message for AJAX submission. $form['flag_lists_' . $form_state['flo_operation']]['status_message'] = array('#markup' => ''); $form['flag_lists_' . $form_state['flo_operation']]['#prefix'] = '
'; $form['flag_lists_' . $form_state['flo_operation']]['#suffix'] = (!empty($hidden_deleted_values)) ? $hidden_deleted_values : '' . '
'; return $form; } function flag_lists_ops_form_ajax_callback(&$form, &$form_state) { // The form has already been submitted and updated. We can return the replaced // item as it is. $message = ''; if (!flag_lists_ops_form_validate($form, $form_state)) { $message = flag_lists_ops_form_submit($form, $form_state); } $form['flag_lists_' . $form_state['flo_operation']]['status_message']['#markup'] = '
' . $message . '
'; if ($form_state['flo_operation'] == 'flag') { $form['flag_lists_' . $form_state['flo_operation']]['list']['#value'] = '0'; } $form['flag_lists_' . $form_state['flo_operation']]['status_message']['#attributes']['class'][] = 'alert-success'; return $form['flag_lists_' . $form_state['flo_operation']]; } function flag_lists_ops_form_validate($form, &$form_state) { global $user; $error_count = 0; // Check to see if an items are selected, if not fail right away. if (!isset($_REQUEST['flag_lists_ops']) || empty($_REQUEST['flag_lists_ops'])) { form_set_error('', t('No content selected.')); $error_count++; return $error_count; } switch ($form_state['values']['flag_lists_' . $form_state['flo_operation']]['operation']) { case 'unflag': $user_flag_lists = flag_lists_get_user_flags(); foreach ($user_flag_lists as $key => $op) { $ops[$key] = explode('_', $key); if (empty($ops[$key][3]) || !($flag = flag_lists_get_flag($ops[$key][3]))) { form_set_error('flag_lists][remove', t('Invalid options list selected to remove from.')); $error_count++; } else { if ($flag->uid != $user->uid) { form_set_error('flag_lists][remove', t('You are only allowed to remove content from your own lists.')); $error_count++; } } } break; default: if (empty($form_state['values']['flag_lists_' . $form_state['flo_operation']]['list'])) { form_set_error('flag_lists][list', t('No list selected. Please select a list to add to.')); $error_count++; } else { if (!($flag = flag_lists_get_flag($form_state['values']['flag_lists_' . $form_state['flo_operation']]['list']))) { form_set_error('flag_lists][list', t('Invalid list selected. Please select a list to add to.')); $error_count++; } else { if ($flag->uid != $user->uid) { form_set_error('flag_lists][list', t('Invalid list selected. Please select a list to add to.')); $error_count++; } } } break; } return $error_count; } function flag_lists_ops_form_submit($form, &$form_state) { // Get the $ops from the originating form. $ops = $_REQUEST['flag_lists_ops']; $ops = is_array($ops) ? $ops : array($ops); $success_count = 0; // Get the operation, or set it switch ($form_state['values']['flag_lists_' . $form_state['flo_operation']]['operation']) { case 'unflag': $operation = 'unflag'; $message = 'removed from'; $user_flag_lists = flag_lists_get_user_flags(); foreach ($user_flag_lists as $key => $op) { // Iterate over all flags by this user list($k1,$k2,$owner,$ofid) = explode('_', $key); foreach ($ops as $op) { // Iterate over all selected items list($nid,$fid) = array_merge( explode('-', $op), array(FALSE)); if ($fid <> 0 && $fid == $ofid) { if (($flag = flag_lists_get_flag($fid)) && ($node = node_load($nid))) { if (flag_lists_do_flag($flag, $operation, $nid)) { $success_count++; } } } } } break; default: $operation = 'flag'; $message = 'added to'; if ($flag = flag_lists_get_flag($form_state['values']['flag_lists_' . $form_state['flo_operation']]['list'])) { foreach ($ops as $nid) { if (flag_lists_do_flag($flag, $operation, $nid)) { $success_count++; } } } break; } if (!empty($flag->title) && $success_count <> 0) { $message = t('@count item(s) ' . $message . ' !listname !title', array('@count' => $success_count, '!listname' => variable_get('flag_lists_name','list'), '!title' => $flag->title)); } else { $message = t('No items affected.'); } if ($_GET['q'] != 'system/ajax') { drupal_set_message($message); } else { return $message; } } /** * Gets the FLO field if it exists on the passed-in view. * * @return * The field object if found. Otherwise, FALSE. */ function _flag_lists_ops_get_field($view) { foreach ($view->field as $field_name => $field) { if ($field instanceof flag_lists_handler_field_ops) { // Add in the view object for convenience. $field->view = $view; return $field; } } return FALSE; } function flag_lists_template_validate($form, &$form_state) { $types = array_filter($form_state['values']['types']); $errors = array(); foreach ($types as $type) { $result = db_select('flag_lists_types', 'f') ->fields('f') ->condition('type', $type) ->condition('name', $form_state['values']['name'], '<>') ->execute(); foreach ($result as $errors) { $content_types[] = $errors->type; $templates[] = $errors->name; } } if (isset($content_types) && count($content_types)) { $content_types = implode(', ', $content_types); $templates = implode(', ', array_unique($templates)); form_set_error('types', t('The flaggable content type(s) "@type" is(are) already assigned to the template(s) "@template." A content type may be assigned to only one template. To reassign a content type you must first remove its other assignment.', array( '@type' => $content_types, '@template' => $templates ))); } } function flag_lists_template_submit($form, &$form_state) { $types = array_filter($form_state['values']['types']); // Clean out the old types, then add the new. $num_deleted = db_delete('flag_lists_types') ->condition('name', $form_state['values']['name']) ->execute(); foreach ($types as $type) { db_insert('flag_lists_types') ->fields(array( 'name' => $form_state['values']['name'], 'type' => $type, )) ->execute(); } } /** * Helper function to build an array of all lists available to or owned by the * current user and that are available on the current content type. */ function flag_lists_get_content_fids() { global $user; // This is a node view. We only care about nodes for now. if (arg(0) == 'node' && is_numeric(arg(1)) && is_null(arg(2))) { $type = db_select('node', 'n') ->fields('n', array('type')) ->condition('nid', arg(1)) ->execute() ->fetchField(); // Get current user's flags for this node. $query = db_select('flag_lists', 'fc') ->fields('f', 'fid') ->condition('fc.uid', $user->uid) ->condition('fn.type', $type); $query->leftJoin('flag_types', 'fn', 'fn.fid = fc.fid'); $query->leftJoin('flag', 'f', 'fc.fid = f.fid'); $fc_result = $query->execute(); foreach ($fc_result as $row) { $fids[] = $row->fid; } } // This is the flag / unflag callback elseif (arg(0) == 'flag' && (arg(1) == 'flag' || arg(1) == 'unflag')) { // Get the flag for this request. $fids[] = db_select('flag', 'f') ->fields('f', array('fid')) ->condition('name', arg(2)) ->execute() ->fetchField(); } // Get the regular flags for this node. The flag module will narrow by role, // etc. when flag_get_flags() is called. These flag ids are always returned. $query = db_select('flag', 'f') ->fields('f', array('fid')) ->condition('fc.fid', NULL); $query->leftJoin('flag_lists', 'fc', 'fc.fid = f.fid'); $f_result = $query->execute(); foreach ($f_result as $obj) { $fids[] = $obj->fid; } if (is_array($fids)) { return array_unique($fids); } else { return array(); } } /** * Implements hook_block_info(); */ function flag_lists_block_info() { return array( 'flag_lists' => array( 'info' => drupal_ucfirst(t('@name', array('@name' => variable_get('flag_lists_name','list')))), 'cache' => DRUPAL_NO_CACHE, ), 'flag_lists_list' => array( 'info' => t('My @name', array('@name' => variable_get('flag_lists_name', 'list'))), 'cache' => DRUPAL_NO_CACHE, ), ); } /** * Implements hook_block_configure(). */ function flag_lists_block_configure($delta = '') { $form = array(); switch ($delta) { case 'flag_lists': $form = array( 'create_lists' => array( '#type' => 'checkbox', '#title' => t('Show link to add new list'), '#default_value' => variable_get('flag_lists_create_lists', 1), '#description' => t('Checking this adds a link to the create new list form.'), ), 'ops' => array( '#type' => 'checkbox', '#title' => t('Show edit and delete links'), '#default_value' => variable_get('flag_lists_ops', 1), '#description' => t('Checking this appends edit and delete links to each list name for users with access.'), ), 'include_flags' => array( '#type' => 'checkbox', '#title' => t('Include flag module flags'), '#default_value' => variable_get('flag_lists_include_flags', 0), '#description' => t('Checking this will append flag module flags to the list of lists.'), ), ); break; } return $form; } /** * Implements hook_block_save(). */ function flag_lists_block_save($delta = '', $edit = array()) { switch ($delta) { case 'flag_lists': variable_set('flag_lists_create_lists', $edit['create_lists']); variable_set('flag_lists_ops', $edit['ops']); variable_set('flag_lists_include_flags', $edit['include_flags']); break; } } /** * Implements hook_block_view(). */ function flag_lists_block_view($delta = '') { $block = array(); switch ($delta) { case 'flag_lists': if (user_access('create flag lists')) { $block = array( 'subject' => t('My @name', array('@name' => variable_get('flag_lists_name', 'list'))), 'content' => theme('flag_lists_list', array( 'node' => NULL, 'create' => variable_get('flag_lists_create_lists', 0), 'ops' => variable_get('flag_lists_ops', 0), 'use_flags' => variable_get('flag_lists_include_flags', 0) )), ); } break; case 'flag_lists_list': if (user_access('create flag lists')) { global $user; $account = user_load($user->uid); $block = array( 'subject' => t('My @name', array('@name' => variable_get('flag_lists_name', 'list'))), 'content' => flag_lists_user_page($account), ); } break; } return (!empty($block['content'])) ? $block : array(); } /** * Implementation of hook_user_delete(). */ function flag_lists_user_delete($account) { // Remove personal flags by this user. $num_deleted = db_delete('flag_lists_flags') ->condition('uid', $account->uid) ->execute(); } /** * Build a flag's messages. */ function flag_lists_set_messages(&$flag) { // Get the parent flag. These are cached by the flag module. $pflag = flag_get_flag(NULL, $flag->pfid); $title = $flag->title; $lists_name = t('@name', array('@name' => variable_get('flag_lists_name', 'list'))); $flag->flag_short = $pflag->flag_short; $flag->flag_long = $pflag->flag_long; $flag->flag_message = $pflag->flag_message; $flag->unflag_short = $pflag->unflag_short; $flag->unflag_long = $pflag->unflag_long; $flag->unflag_message = $pflag->unflag_message; } /** * Implementation of hook_flag_access(). * * Make sure a user can only see his/her own personal flags. */ function flag_lists_flag_access($flag, $entity_id, $action, $account) { if ( !empty($flag->name) && (strpos($flag->name, 'flag_lists') === 0) ) { switch ($action) { case 'flag': case 'unflag': $fid = db_select('flag_lists_flags', 'f') ->fields('f') ->condition('f.uid', $account->uid) ->execute() ->fetchField(); if (!empty($fid)) { return array('flag_lists' => TRUE); } else { return array('flag_lists' => FALSE); } } } } /** * Implementation of hook_link(). */ // There may be a better way to keep flag lists out of the links, but this // works for now. @todo Find a better way to keep flags lists out of links. function flag_lists_link_alter(&$links, $node) { if (!variable_get('flag_lists_use_links', 1)) { foreach ($links as $name => $link) { if (stristr($name, 'flag-fl_')) { unset($links[$name]); } } } } /** * Implementation of hook_flag_alter(). */ function flag_lists_flag_alter(&$flag) { } /** * Implementation of hook_flag_delete(). * * This is not in flag yet. */ function flag_lists_flag_delete($flag) { // Template flag is being deleted. Clean up our tables. // Collect the sub-flag fids so we can delete counts and content records. $results = db_select('flag_lists_flags', 'f') ->fields('f', array('fid', 'name')) ->condition('pfid', $flag->fid) ->execute(); foreach ($results as $fid) { db_delete('flag_lists_counts') ->condition('fid', $flag->fid) ->execute(); db_delete('flag_lists_content') ->condition('fid', $flag->fid) ->execute(); } // flag_lists_types uses the template flag name, not our own fid. db_delete('flag_lists_types') ->condition('name', $flag->name) ->execute(); // Now delete the sub-flags. $num_deleted = db_delete('flag_lists_flags') ->condition('pfid', $flag->fid) ->execute(); if (!empty($num_deleted)) { drupal_set_message(t('The template flag "@title" and all its sub-flags have been deleted.', array('@title' => $flag->title))); } } /** * Implementation of hook_views_api(). */ function flag_lists_views_api() { return array( 'api' => 3.0, 'path' => drupal_get_path('module', 'flag_lists') . '/includes', ); } /** * Helper function to test if a flag is owned by the current user, or current * user can administer flags. */ function flag_lists_is_owner($action, $name) { global $user; if (user_access('administer flags')) { return TRUE; } // If we don't have an fid, then we have the flag name. if (is_numeric($name)) { $query = db_select('flag_lists_flags', 'f')->condition('fid', $name); $query->addField('f', 'name'); $name = $query->execute()->fetchField(); } if (!user_access($action . ' own flag lists')) { return FALSE; } if (db_select('flag_lists_flags', 'f')->fields('f')->condition('f.name', $name)->condition('f.uid', $user->uid) ->countQuery()->execute()->fetchField() ) { return TRUE; } return FALSE; } /** * Get a single user's lists, and merge in flag module flags */ function flag_lists_get_user_flags($content_type = NULL, $account = NULL, $use_flags = FALSE) { $flags = array(); $lists = array(); if (!isset($account)) { $account = $GLOBALS['user']; } // Get flag lists flags $query = db_select('flag_lists_flags', 'fl') ->fields('fl') ->condition('fl.uid', $account->uid); $query->leftJoin('flag', 'f', 'fl.pfid = f.fid'); $query->leftJoin('flag_lists_types', 'ft', 'ft.name = f.name'); $query->addField('ft', 'type'); if ($content_type) { $query->condition('ft.type', $content_type); } $result = $query->execute(); foreach ($result as $row) { if (!isset($lists[$row->name])) { $lists[$row->name] = flag_flag::factory_by_row($row); $lists[$row->name]->module = 'flag_lists'; } else { $lists[$row->name]->types[] = $row->type; } } // Get regular flags. if ($use_flags) { $flags = flag_get_flags('node', $content_type, $account); foreach ($flags as $key => $flag) { if (!isset($flag->module)) { // Assume flag is from flag module $flags[$key]->module = 'flag'; } // Strip out any list templates if (stristr($flag->name, 'fl_template') !== FALSE) { unset($flags[$key]); } } } $flags = array_merge($lists, $flags); return $flags; } /** * Theme function to return edit, delete links. * * @param $flag * The flag whose links are being built. */ function theme_flag_lists_ops($variables) { $flag = $variables['flag']; $links = array( 'flags_edit' => array( 'title' => t('edit'), 'href' => 'flag/lists/edit/' . $flag->name, 'query' => drupal_get_destination() ), 'flags_delete' => array( 'title' => t('delete'), 'href' => 'flag/lists/delete/' . $flag->name, 'query' => drupal_get_destination() ), ); return theme('links', array('links' => $links, 'attributes' => array('class' => 'flag_lists_ops'))); } /** * Theme a list of lists * * @param $node * The listable node * @param boolean $create * Show the create list form. * @param boolean $ops * Show the edit / delete links for lists * @param boolean $use_flags * Show flags from the flag module * @return */ // @todo Separate out the code from the theming better. function theme_flag_lists_list($variables) { $node = $variables['node']; $create = $variables['create']; $ops = $variables['ops']; $use_flags = $variables['use_flags']; $items = array(); // Make sure we have a node. if (is_object($node) && user_access('create flag lists')) { $content_type = $node->type; $entity_id = $node->nid; } // Or at least confirm we are on a node page and use has access. elseif (arg(0) == 'node' && is_numeric(arg(1)) && user_access('create flag lists')) { $entity_id = arg(1); $query = db_select('node')->condition('nid', $entity_id); $query->addField('node', 'type'); $content_type = $query->execute()->fetchField(); } else { return; } // Do we have a list template for this node type, or are we s if (!flag_lists_template_exists($content_type) && !$use_flags) { return; } global $user; if ($flags = flag_lists_get_user_flags($content_type, $user, $use_flags)) { // Build the list of lists for this node. foreach ($flags as $flag) { if ($flag->module == 'flag_lists') { $action = _flag_lists_is_flagged($flag, $entity_id, $user->uid, 0) ? 'unflag' : 'flag'; } else { $action = $flag->is_flagged($entity_id) ? 'unflag' : 'flag';; } // Do we need the ops? if ($ops && $flag->module == 'flag_lists') { $ops_links = theme('flag_lists_ops', array('flag' => $flag)); $link = $flag->theme($action, $entity_id) . $ops_links; } else { $link = $flag->theme($action, $entity_id); } // If it's a list, fix the link. if ($flag->module == 'flag_lists') { flag_lists_fix_link($link, $action); } $items[] = $link; } } if ($create && flag_lists_template_exists($content_type)) { $items[] = l(t('Make a new @name', array('@name' => variable_get('flag_lists_name', t('list')))), 'flag-lists/add/' . $content_type, array('query' => drupal_get_destination())); } // Return if nothing to display. if (empty($items) || !count($items)) { return; } drupal_add_css(drupal_get_path('module', 'flag_lists') . '/theme/flag_lists.css'); return theme('item_list', array( 'items' => $items, 'type' => 'ul', 'attributes' => array('class' => 'flag-lists-links') )); } // Do we still need this, and/or do we need our own cache? /** * Clear the flag cache. * * This is a less severe cache clear than provided by flag. All flag lists * users must be authorized, so we don't need to flush the page cache. For now, * flag lists titles won't be in the menu, so no need to clear that. */ function _flag_lists_clear_cache() { // We're not using _flag_clear_cache because we probably don't need the menu // rebuild and don't need to clear the page cache. if (module_exists('views')) { views_invalidate_cache(); } } /** * Update ALL flag lists with settings form values. */ function flag_lists_rebuild() { $flags = flag_lists_get_flags(); foreach ($flags as $flag) { flag_lists_set_messages($flag); $flag->link_type = 'toggle'; flag_lists_save($flag); } } /** * Build array of all flag lists. * * @return If limit and header arguments are provided, the paged flags, otherwise * an array of all flags. */ function flag_lists_get_flags($limit = NULL, $header = NULL) { $flags = array(); if ($limit) { $query = db_select('flag_lists_flags', 'fl') ->fields('fl') ->groupBy('fl.fid') ->extend('PagerDefault') ->limit($limit); $query->leftJoin('flag_types', 'ft', 'ft.fid = fl.pfid'); $query->addExpression('GROUP_CONCAT(ft.type)', 'types'); $result = $query->execute(); } else { $query = db_select('flag_lists_flags', 'fl') ->fields('fl') ->groupBy('fl.fid'); $query->leftJoin('flag_types', 'ft', 'ft.fid = fl.pfid'); $query->addExpression('GROUP_CONCAT(ft.type)', 'types'); $result = $query->execute(); } foreach ($result as $row) { $flags[$row->name] = flag_flag::factory_by_row($row); $flags[$row->name]->types = explode(',', $row->types); $flags[$row->name]->uid = $row->uid; } return $flags; } /** * Get a specific flag. * * Using this instead of flag_get_flag() for performance. */ function flag_lists_get_flag($fid) { // If we don't have an fid, then we have the flag name. if (!is_numeric($fid)) { $query = db_select('flag_lists_flags') ->condition('name', $fid); $query->addField('flag_lists_flags', 'fid'); $fid = $query->execute()->fetchField(); } $query = db_select('flag_lists_flags', 'fl') ->fields('fl') ->condition('fl.fid', $fid); $query->leftJoin('flag_types', 'ft', 'ft.fid = fl.pfid'); $query->addField('ft', 'type'); $result = $query->execute(); foreach ($result as $row) { if (!isset($flag->name)) { $flag = flag_flag::factory_by_row($row); } else { $flag->types[] = $row->type; } } return $flag; } /** * Get all flagged content in a flag. * * Using this instead of flag_get_flagged_content() because we need to make sure that we use flag_lists_get_flags() * * @param * The flag name for which to retrieve flagged content. */ function flag_lists_get_flagged_content($fid, $uid) { $return = array(); $flag = flag_lists_get_flag($fid); $result = db_select('flag_lists_content', 'f') ->fields('f') ->condition('f.fid', $flag->fid) ->condition('f.uid', $uid) ->execute(); foreach ($result as $row) { $return[] = $row; } return $return; } /** * Implementation of hook_flag_link(). * * When Flag uses a link type provided by this module, it will call this * implementation of hook_flag_link(). It returns a single link's attributes, * using the same structure as hook_link(). Note that "title" is provided by * the Flag configuration if not specified here. * * @param $flag * The full flag object of for the flag link being generated. * @param $action * The action this link will perform. Either 'flag' or 'unflag'. * @param $entity_id * The ID of the node, comment, user, or other object being flagged. * @return * An array defining properties of the link. */ function flag_lists_flag_link($flag, $action, $entity_id) { return array(); } /** * Implementation of hook_flag_link_type_info(). */ function flag_lists_flag_link_type_info() { return array( 'fl_template' => array( 'title' => t('Flag Lists toggle'), 'description' => t('If you are creating a Flag lists template flag, you must select this link type.'), 'options' => array(), 'uses standard js' => TRUE, 'uses standard css' => TRUE, ), ); } function flag_lists_flag_default_flags() { $flags = array(); // Exported flag: "Flag lists template". $flags['fl_template'] = array( 'entity_type' => 'node', 'title' => 'Flag lists template', 'global' => 0, 'types' => array(), 'flag_short' => 'Add to your [flag_lists:title] [flag_lists:term]', 'flag_long' => 'Add this post to your [flag_lists:title] [flag_lists:term]', 'flag_message' => 'This post has been added to your [flag_lists:title] [flag_lists:term]', 'unflag_short' => 'Remove this from your [flag_lists:title] [flag_lists:term]', 'unflag_long' => 'Remove this post from your [flag_lists:title] [flag_lists:term]', 'unflag_message' => 'This post has been removed from your [flag_lists:title] [flag_lists:term]', 'unflag_denied_text' => '', 'link_type' => 'toggle', 'weight' => 0, 'api_version' => 3, 'module' => 'flag_lists', 'show_on_page' => 0, 'show_on_teaser' => 0, 'show_on_form' => 0, 'status' => FALSE, 'import_roles' => array( 'flag' => array(), 'unflag' => array(), ), ); return $flags; } /** * Saves a flag to the database. It is a wrapper around update($flag) and insert($flag). */ function flag_lists_save(&$flag, $account = NULL) { if (!isset($account)) { $account = $GLOBALS['user']; } if (isset($flag->fid)) { flag_lists_update($flag); $flag->is_new = FALSE; module_invoke_all('flag_lists', $flag, $account); } else { flag_lists_insert($flag); $flag->is_new = TRUE; module_invoke_all('flag_lists', $flag, $account); } // Clear the page cache for anonymous users. // cache_clear_all('*', 'cache_page', TRUE); } /** * Saves an existing flag to the database. Better use save($flag). */ function flag_lists_update($flag) { $num_updated = db_update('flag_lists_flags') ->fields(array( 'title' => $flag->title, 'name' => $flag->name, 'options' => $flag->get_serialized_options($flag), )) ->condition('fid', $flag->fid) ->execute(); } /** * Saves a new flag to the database. Better use save($flag). */ function flag_lists_insert($flag) { $flag->fid = db_insert('flag_lists_flags') ->fields(array( 'pfid' => $flag->pfid, 'uid' => $flag->uid, 'entity_type' => $flag->entity_type, 'name' => $flag->name, 'title' => $flag->title, 'options' => $flag->get_serialized_options($flag), )) ->execute(); $flag->name = 'flag_lists_' . $flag->uid . '_' . $flag->fid; flag_lists_update($flag); } /** * Delete a flag_lists flag. * */ function flag_lists_fl_delete($flag, $account = NULL) { if (!isset($account)) { $account = $GLOBALS['user']; } db_delete('flag_lists_counts')->condition('fid', $flag->fid)->execute(); db_delete('flag_lists_content')->condition('fid', $flag->fid)->execute(); db_delete('flag_lists_flags')->condition('fid', $flag->fid)->execute(); $flag->is_deleted = TRUE; module_invoke_all('flag_lists', $flag, $account); _flag_lists_clear_cache(); drupal_set_message(t('The @name @title has been deleted.', array('@name' => variable_get('flag_lists_name', 'list'), '@title' => $flag->title))); } /** * Menu callback for (un)flagging a node. * * Used both for the regular callback as well as the JS version. We use this * instead of the flag module's because our flags are not in the flags table. */ function flag_lists_page($action = NULL, $flag_name = NULL, $entity_id = NULL) { global $user; // Shorten up the variables that affect the behavior of this page. $js = isset($_REQUEST['js']); $token = isset($_REQUEST['token']) ? $_REQUEST['token'] : ''; // Specifically $_GET to avoid getting the $_COOKIE variable by the same key. $has_js = isset($_GET['has_js']); // Check the flag token, then perform the flagging. if (!flag_check_token($token, $entity_id)) { $error = t('Bad token. You seem to have followed an invalid link.'); } elseif ($user->uid == 0 && !$has_js) { $error = t('You must have JavaScript and cookies enabled in your browser to flag content.'); } else { if (empty($flag_name) || !($flag = flag_lists_get_flag($flag_name))) { // Flag does not exist. $error = t('You are not allowed to flag, or unflag, this content.'); } // Identify it as ours. $flag->module = 'flag_lists'; flag_lists_do_flag($flag, $action, $entity_id); } // If an error was received, set a message and exit. if (isset($error)) { if ($js) { drupal_add_http_header('Content-Type', 'text/javascript; charset=utf-8'); print drupal_to_js(array( 'status' => FALSE, 'errorMessage' => $error, )); exit; } else { drupal_set_message($error); drupal_access_denied(); exit; } } // If successful, return data according to the request type. if ($js) { drupal_add_http_header('Content-Type', 'text/javascript; charset=utf-8'); // $flag = flag_lists_get_flag($flag_name); // $flag->link_type = 'toggle'; $sid = flag_get_sid($user->uid); $new_action = _flag_lists_is_flagged($flag, $entity_id, $user->uid, $sid) ? 'unflag' : 'flag'; $new_link = $flag->theme($new_action, $entity_id, array("after_flagging" => TRUE)); flag_lists_fix_link($new_link, $new_action); drupal_json_output(array( 'status' => TRUE, 'newLink' => $new_link, // Further information for the benefit of custom JavaScript event handlers: 'contentId' => $entity_id, 'contentType' => $flag->entity_type, 'flagName' => $flag->name, 'flagStatus' => $action, )); exit; } else { $flag = flag_lists_get_flag($flag->fid); drupal_set_message($flag->get_label($action . '_message', $entity_id)); drupal_goto(); } } function flag_lists_fix_link(&$link, $action) { // This is a hack to let us use our own flag/unflag callbacks without having // to override $flag->theme and creating our own flag_link type. $link = str_replace('/flag/' . $action . '/', '/flag-lists/' . $action . '/', $link); } /** * Remove all entries of entity_id and type * * @param $entity_id * Entity id which has been flagged. * @param $type * The entity type. */ function _flag_lists_remove_entity($entity_id, $type) { $query = db_select('flag_lists_content') ->condition('entity_id', $entity_id) ->condition('entity_type', $type); $query->fields('flag_lists_content', array('fcid', 'fid', 'uid', 'sid')); $items = $query->execute()->fetchAll(); if ($items) { foreach ($items as $key => $value) { db_delete('flag_lists_content') ->condition('fcid', $value->fcid) ->execute(); watchdog('flag_lists', t('Deleted entry @fcid from flat_lists_content', array('@fcid' => $value->fcid))); } } } /** * Implements hook_entity_delete */ function flag_lists_entity_delete($entity, $type) { foreach (flag_get_flags($type) as $flag) { if (isset($entity->vid)) { $items = _flag_lists_remove_entity($entity->vid, $type); } } } /** * Flags, or unflags, an item. * * @param $action * Either 'flag' or 'unflag'. * @param $entity_id * The ID of the item to flag or unflag. * @param $account * The user on whose behalf to flag. Leave empty for the current user. * @param $skip_permission_check * Flag the item even if the $account user doesn't have permission to do so. * @return * FALSE if some error occured (e.g., user has no permission, flag isn't * applicable to the item, etc.), TRUE otherwise. */ function flag_lists_do_flag($flag, $action, $entity_id, $account = NULL, $skip_permission_check = FALSE) { if (!isset($account)) { $account = $GLOBALS['user']; } if (!$account) { return FALSE; } if (!$skip_permission_check) { if (!$flag->access($entity_id, $action, $account)) { // User has no permission to flag/unflag this object. return FALSE; } } else { // We are skipping permission checks. However, at a minimum we must make // sure the flag applies to this content type: if (!$flag->applies_to_entity_id($entity_id)) { return FALSE; } } // Clear various caches; We don't want code running after us to report // wrong counts or false flaggings. // flag_get_counts(NULL, NULL, TRUE); // flag_get_user_flags(NULL, NULL, NULL, NULL, TRUE); // Find out which user id to use. $uid = $flag->global ? 0 : $account->uid; $sid = flag_get_sid($uid); // Anonymous users must always have a session id. if ($sid == 0 && $account->uid == 0) { return FALSE; } // Perform the flagging or unflagging of this flag. We invoke hook_flag here // because we do our own flagging. $flagged = _flag_lists_is_flagged($flag, $entity_id, $uid, $sid); if ($action == 'unflag') { if ($flagged) { $fcid = _flag_lists_unflag($flag, $entity_id, $uid, $sid); module_invoke_all('flag_unflag', $flag, $entity_id, $account, $fcid); return TRUE; } } elseif ($action == 'flag') { if (!$flagged) { $fcid = _flag_lists_flag($flag, $entity_id, $uid, $sid); module_invoke_all('flag_flag', $flag, $entity_id, $account, $fcid); return TRUE; } } return FALSE; } /** * Returns TRUE if a certain user has flagged this content. * * * This method is similar to is_flagged() except that it does direct SQL and * doesn't do caching. Use it when you want to not affect the cache, or to * bypass it. * */ function _flag_lists_is_flagged($flag, $entity_id, $uid, $sid) { $query = db_select('flag_lists_content') ->condition('fid', $flag->fid) ->condition('uid', $uid) ->condition('sid', $sid) ->condition('entity_id', $entity_id); $query->addField('flag_lists_content', 'fid'); return $query->execute()->fetchField(); } /** * A low-level method to flag content. * * You probably shouldn't call this raw private method: call the * flag_lists_do_flag() function instead. * */ function _flag_lists_flag($flag, $entity_id, $uid, $sid) { $fcid = db_insert('flag_lists_content') ->fields(array( 'fid' => $flag->fid, 'entity_type' => $flag->entity_type, 'entity_id' => $entity_id, 'uid' => $uid, 'sid' => $sid, 'timestamp' => REQUEST_TIME, )) ->execute(); _flag_lists_update_count($flag, $entity_id); return $fcid; } /** * A low-level method to unflag content. * * You probably shouldn't call this raw private method: call the * flag_lists_do_flag() function instead. * */ function _flag_lists_unflag($flag, $entity_id, $uid, $sid) { $query = db_select('flag_lists_content') ->condition('fid', $flag->fid) ->condition('entity_id', $entity_id) ->condition('uid', $uid) ->condition('sid', $sid); $query->addField('flag_lists_content', 'fcid'); $fcid = $query->execute()->fetchField(); if ($fcid) { db_delete('flag_lists_content') ->condition('fcid', $fcid) ->execute(); _flag_lists_update_count($flag, $entity_id); } return $fcid; } /** * Updates the flag count for this content */ function _flag_lists_update_count($flag, $entity_id) { $count = db_select('flag_lists_content', 'f') ->fields('f') ->condition('fid', $flag->fid) ->condition('entity_id', $entity_id) ->countQuery() ->execute() ->fetchField(); if (empty($count)) { $num_deleted = db_delete('flag_lists_counts') ->condition('fid', $flag->fid) ->condition('entity_id', $entity_id) ->execute(); } else { $num_updated = db_update('flag_lists_counts') ->fields(array( 'count' => $count, )) ->condition('fid', $flag->fid) ->condition('entity_id', $entity_id) ->execute(); if (empty($num_updated)) { db_insert('flag_lists_counts') ->fields(array( 'fid' => $flag->fid, 'entity_type' => $flag->entity_type, 'entity_id' => $entity_id, 'count' => $count, )) ->execute(); } } } /** * Checks for a list template for a content type. */ function flag_lists_template_exists($type) { $query = db_select('flag_lists_types') ->condition('type', $type); $query->addField('flag_lists_types', 'type'); $exists = $query->execute()->fetchField(); if (!empty($exists)) { return TRUE; } return FALSE; } /** * Checks for a list title by node type. */ function flag_lists_title_exists($title, $type) { return db_query("SELECT COUNT(flf.fid) FROM {flag_lists_flags} flf LEFT JOIN {flag_types} ft ON flf.pfid=ft.fid WHERE flf.title=:title AND ft.type=:type AND flf.uid=:uid", array( ':title' => $title, ':type' => $type, ':uid' => $GLOBALS['user']->uid ))->fetchField(); } /** * Get a list of template flag names. */ function flag_lists_get_templates() { $templates = array(); $result = db_select('flag_lists_types', 'f') ->fields('f', array( 'name' )) ->distinct() ->execute(); foreach ($result as $obj) { $templates[] = flag_get_flag($obj->name); } return $templates; } /** * Implements hook_token_info(). */ function flag_lists_token_info() { $type = array( 'name' => t('Flag lists'), 'description' => t('Tokens related to flag lists.'), 'needs-data' => 'flag_lists', ); $flag_lists['term'] = array( 'name' => t("Term"), 'description' => t("The terminology used to name the lists, such as list, wishlist, favorites, etc."), ); $flag_lists['title'] = array( 'name' => t("Title"), 'description' => t("The title of the list."), ); return array( 'types' => array('flag_lists' => $type), 'tokens' => array('flag_lists' => $flag_lists), ); } /** * Implements hook_tokens(). */ function flag_lists_tokens($type, $tokens, array $data = array(), array $options = array()) { $sanitize = !empty($options['sanitize']); $replacements = array(); if ($type == 'flag_lists' && !empty($data['flag_lists'])) { $flag_list = $data['flag_lists']; foreach ($tokens as $name => $original) { switch ($name) { case 'title': $replacements[$original] = $sanitize ? check_plain($flag_list->title) : $flag_lists->title; break; case 'term': $replacements[$original] = $sanitize ? check_plain(variable_get('flag_lists_name', 'list')) : variable_get('flag_lists_name', 'list'); break; } } } return $replacements; } /** * Preprocess link title and text for the flag.tpl.php * * This seems to be the only place to do this */ function flag_lists_preprocess_flag(&$variables) { if (module_exists('token') && !empty($variables['flag']->module) && $variables['flag']->module == 'flag_lists') { if (!empty($variables['link_text'])) { $variables['link_text'] = token_replace($variables['link_text'], array('flag_lists' => $variables['flag'])); } if (!empty($variables['link_title'])) { $variables['link_title'] = token_replace($variables['link_title'], array('flag_lists' => $variables['flag'])); } if (!empty($variables['message_text'])) { $variables['message_text'] = token_replace($variables['message_text'], array('flag_lists' => $variables['flag'])); } } } /** * Implements hook_views_form_substitutions(). */ function flag_lists_views_form_substitutions() { // Views check_plains the column label, so Flag lists needs to do the same // in order for the replace operation to succeed. $select_all_placeholder = check_plain(''); $select_all = array( '#type' => 'checkbox', '#default_value' => FALSE, '#attributes' => array('class' => array('flo-table-select-all'), 'title' => array(t('Select all'))), ); return array( $select_all_placeholder => drupal_render($select_all), ); }