You are here

cmf.module in Content Management Filter 5

Same filename and directory in other branches
  1. 6.2 cmf.module
  2. 6 cmf.module
  3. 7 cmf.module

@brief Content management filter module file

This file contains all the functions used by the module.

@attention Copyright (C) 2008 Nuno Veloso <nunoveloso18 (at) gmail (dot) com> @author Nuno André Veloso Matias (http://www.nunoveloso.org)

File

cmf.module
View source
<?php

/**
 * @file
 * @brief Content management filter module file
 * 
 * This file contains all the functions used by the module.
 *
 * @attention Copyright (C) 2008 Nuno Veloso <nunoveloso18 (at) gmail (dot) com>
 * @author Nuno André Veloso Matias (http://www.nunoveloso.org)
 */

/**
 * Implementation of hook_help().
 */
function cmf_help($section = '') {
  switch ($section) {
    case "admin/help#cmf":
      $output = '<p>' . t("This module adds an easier way for administrators to filter the content on a Drupal site for administration purposes.") . '</p>';
      $output .= '<p>' . t("It's an improvement over the content page in the administration area of Drupal. It can show on the same page nodes and comments and adds new filters like role and author.") . '</p>';
      break;
  }
  return $output;
}

/**
 * Implementation of hook_perm().
 */
function cmf_perm() {
  return array(
    'filter and manage site content',
    'view user content list',
  );
}

/**
 * Implementation of hook_menu().
 */
function cmf_menu($may_cache) {
  $items = array();
  $manage_access = user_access('filter and manage site content');
  $view_access = user_access('view user content list');
  $access_profiles = user_access('access user profiles');

  //  if ($may_cache) {
  $items[] = array(
    'path' => 'admin/content/filter',
    'title' => t('Content Management Filter'),
    'description' => t('All-in-one advanced filter and management of your site content.'),
    'callback' => 'cmf_admin_content_page',
    'access' => $manage_access,
  );
  if (arg(0) == 'user' && is_numeric(arg(1)) && arg(1) > 0) {
    $items[] = array(
      'path' => 'user/' . arg(1) . '/cmf',
      'title' => t('CMF'),
      'description' => t('User-specific content management filter'),
      'callback' => 'cmf_admin_content_page',
      'access' => $access_profiles || $view_access,
      'type' => MENU_LOCAL_TASK,
    );
  }
  $items[] = array(
    'path' => 'cmf/userauto',
    'title' => 'User autocomplete',
    'callback' => '_cmf_user_autocomplete',
    'access' => $manage_access || $view_access || $access_profiles,
    'type' => MENU_CALLBACK,
  );

  //  }
  return $items;
}

/** 
 * Called when user goes to example.com/admin/content/filter
 *
 * @return the HTML generated from the $form data structure
 */
function cmf_admin_content_page() {
  if (!isset($_SESSION['cmf_content_kind'])) {
    $_SESSION['cmf_content_kind'] = 'node';
  }
  if (arg(0) == 'user' && is_numeric(arg(1)) && arg(1) > 0) {
    $true = TRUE;
  }
  $output = drupal_get_form('cmf_filter_form', $true);

  // Call the form first, to allow for the form_values array to be populated.
  switch ($_SESSION['cmf_content_kind']) {
    case 'node':
      if ($_POST['operation'] == 'delete' && $_POST['nodes']) {
        return drupal_get_form('node_multiple_delete_confirm');
      }
      else {
        $output .= drupal_get_form('cmf_admin_nodes_form');
      }
      break;
    case 'comment':
      if ($_POST['operation'] == 'delete' && $_POST['comments']) {
        return drupal_get_form('comment_multiple_delete_confirm');
      }
      else {
        $output .= drupal_get_form('cmf_admin_comments_form');
      }
      break;
    case 'both':
      $output .= drupal_get_form('cmf_admin_both_form');
  }
  return $output;
}

/**
 * FILTERS
 */

/**
 * Defines the form for content administration filters.
 *
 * @ingroup forms
 * @see cmf_filter_form_submit()
 * 
 * @param (optional) TRUE if the filter to be built serves the user profile page.
 * @return array with forms properties 
 */
function cmf_filter_form($true = NULL) {
  $session =& $_SESSION['cmf_overview_filter'];
  $session = is_array($session) ? $session : array();
  $filters = cmf_filters($true);
  drupal_add_css(drupal_get_path('module', 'cmf') . '/cmf.css');

  // General settings display (max rows & content kind).
  $form['general'] = array(
    '#type' => 'fieldset',
    '#title' => t('General Settings'),
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
  );
  $form['general']['max-rows'] = array(
    '#type' => 'textfield',
    '#title' => t('Max rows'),
    '#size' => 5,
    '#default_value' => isset($_SESSION['cmf_max_rows']) ? $_SESSION['cmf_max_rows'] : 50,
    '#prefix' => '<div class="container-inline">',
    '#suffix' => '</div>',
  );
  $form['general']['show_nid'] = array(
    '#type' => 'radios',
    '#title' => t('Show node ID'),
    '#options' => array(
      0 => t('No'),
      1 => t('Yes'),
    ),
    '#default_value' => isset($_SESSION['cmf_show_nid']) ? $_SESSION['cmf_show_nid'] : 0,
    '#prefix' => '<div class="container-inline"><div class="cmf-radios">',
    '#suffix' => '</div></div><div class="clear-block"></div>',
  );
  $form['general']['kind'] = array(
    '#type' => 'select',
    '#title' => t('Content'),
    '#options' => array(
      'node' => t('node'),
      'comment' => t('comment'),
      'both' => t('both'),
    ),
    '#default_value' => isset($_SESSION['cmf_content_kind']) ? $_SESSION['cmf_content_kind'] : 'node',
    '#prefix' => '<div class="container-inline">',
  );
  $form['general']['buttons']['apply'] = array(
    '#type' => 'submit',
    '#value' => t('Apply'),
    '#suffix' => '</div>',
  );
  $i = 0;
  $form['filters'] = array(
    '#type' => 'fieldset',
    '#title' => t('Show only items where'),
    '#theme' => 'node_filters',
  );
  foreach ($session as $filter) {
    list($type, $value) = $filter;
    if ($type == 'category') {

      // Load term name from DB rather than search and parse options array.
      $value = taxonomy_get_term($value);
      $value = $value->name;
    }
    elseif ($type == 'title') {

      // Just sanitize it and add quotes.
      $value = "'" . $value . "'";
    }
    else {
      $value = $filters[$type]['options'][$value];
    }

    // Avoid not applicable filter verbose. Note '%' does check_plain.
    if ($type == 'title') {
      if ($i++) {
        $form['filters']['current'][] = array(
          '#value' => t('<em>and</em> where <strong>%a</strong> contains <strong>%b</strong>', array(
            '%a' => $filters[$type]['title'],
            '%b' => $value,
          )),
        );
      }
      else {
        $form['filters']['current'][] = array(
          '#value' => t('<strong>%a</strong> contains <strong>%b</strong>', array(
            '%a' => $filters[$type]['title'],
            '%b' => $value,
          )),
        );
      }
    }
    else {
      if ($i++) {
        $form['filters']['current'][] = array(
          '#value' => t('<em>and</em> where <strong>%a</strong> is <strong>%b</strong>', array(
            '%a' => $filters[$type]['title'],
            '%b' => $value,
          )),
        );
      }
      else {
        $form['filters']['current'][] = array(
          '#value' => t('<strong>%a</strong> is <strong>%b</strong>', array(
            '%a' => $filters[$type]['title'],
            '%b' => $value,
          )),
        );
      }
    }

    // These ifs remove the respective option if it is already being filtered on.
    if ($type == 'type') {
      unset($filters['type']);
    }
    if ($type == 'title') {
      unset($filters['title']);
    }
    if ($type == 'user') {
      unset($filters['users']);
      unset($filters['user']);
    }
    if ($type == 'blocked') {
      unset($filters['blocked']);
    }
    if ($type == 'role') {
      unset($filters['role']);
    }
  }

  /*
   $script = 'document.getElementById(\'edit-user\').style.display="none"';
  //  $script = 'document.getElementById("edit-user").style.visibility="hidden"';
   drupal_add_js($script, 'inline', 'header');
  */

  // preparing select boxes
  foreach ($filters as $key => $filter) {
    $names[$key] = $filter['title'];
    switch ($key) {
      case 'user':
        $form['filters']['status'][$key] = array(
          '#type' => 'select',
          '#options' => $filter['options'],
        );
        break;
      case 'users':
        $form['filters']['status'][$key] = array(
          '#type' => 'textfield',
          '#autocomplete_path' => 'cmf/userauto',
        );
        break;
      case 'title':
        $form['filters']['status'][$key] = array(
          '#type' => 'textfield',
        );
        break;
      default:
        $form['filters']['status'][$key] = array(
          '#type' => 'select',
          '#options' => $filter['options'],
        );
    }
  }

  // building radio buttons
  $keyz = array_keys($names);
  $form['filters']['filter'] = array(
    '#type' => 'radios',
    '#options' => $names,
    '#default_value' => $keyz[0],
  );

  // building buttons depending on the filter state
  $form['filters']['buttons']['submit'] = array(
    '#type' => 'submit',
    '#value' => count($session) ? t('Refine') : t('Filter'),
  );
  if (count($session)) {
    $form['filters']['buttons']['undo'] = array(
      '#type' => 'submit',
      '#value' => t('Undo'),
    );
    $form['filters']['buttons']['reset'] = array(
      '#type' => 'submit',
      '#value' => t('Reset'),
    );
  }
  return $form;
}

/** 
 * Handle post-validation form submission.
 *
 * @ingroup forms
 * @see cmf_filter_form()
 *
 * @param the ID of the passed form
 * @param array with the form properties values
 */
function cmf_filter_form_submit($form_id, $form_values) {
  $filters = cmf_filters();
  switch ($form_values['op']) {
    case t('Filter'):
    case t('Refine'):
      if (isset($form_values['filter'])) {
        $filter = $form_values['filter'];

        // convert AJAX search value to select box value
        if ($filter == 'users') {
          $users = cmf_get_users();
          $uid = db_result(db_query('SELECT uid FROM {users} WHERE name = "%s"', $form_values['users']));
          $form_values['user'] = $uid;
          $filter = 'user';
        }
        if ($filter == 'title') {
          $string = $form_values['title'];
          $filters['title']['options'][$string] = $string;
        }

        // Flatten the options array to accommodate hierarchical/nested options.
        $flat_options = form_options_flatten($filters[$filter]['options']);
        if (isset($flat_options[$form_values[$filter]]) || $filter == 'title') {
          $_SESSION['cmf_overview_filter'][] = array(
            $filter,
            $form_values[$filter],
          );
        }
      }
      break;
    case t('Undo'):
      array_pop($_SESSION['cmf_overview_filter']);
      break;
    case t('Reset'):
      $_SESSION['cmf_overview_filter'] = array();
      break;
    case t('Apply'):
      $_SESSION['cmf_max_rows'] = $form_values['max-rows'];
      $_SESSION['cmf_show_nid'] = $form_values['show_nid'];
      $_SESSION['cmf_content_kind'] = $form_values['kind'];
      if (arg(0) == 'user' && is_numeric(arg(1)) && arg(1) > 0) {
        return 'user/' . arg(1) . '/cmf';
      }
      else {
        return 'admin/content/filter';
      }
      break;
  }
}

/**
 * Theme cmf administration filter form.
 *
 * @themable
 */
function theme_cmf_filter_form($form) {
  $output .= '<div id="cmf_header">';
  $output .= drupal_render($form['general']);

  //  $output .= drupal_render($form['kind']);
  $output .= '</div>';
  $output .= '<div id="node-admin-filter">';
  $output .= drupal_render($form['filters']);
  $output .= '</div>';
  $output .= drupal_render($form);
  return $output;
}

/**
 * List node administration filters that can be applied.
 *
 * @param (optional) TRUE if the filter to be built serves the user profile page
 * @return array with filter properties
 */
function cmf_filters($true = NULL) {

  // Regular filters
  $filters['status'] = array(
    'title' => t('node status'),
    'options' => array(
      'status-1' => t('published'),
      'status-0' => t('not published'),
      'promote-1' => t('promoted'),
      'promote-0' => t('not promoted'),
      'sticky-1' => t('sticky'),
      'sticky-0' => t('not sticky'),
    ),
  );
  $filters['type'] = array(
    'title' => t('node type'),
    'options' => node_get_types('names'),
  );

  // The taxonomy filter
  if ($taxonomy = module_invoke('taxonomy', 'form_all', 1)) {
    $filters['category'] = array(
      'title' => t('category'),
      'options' => $taxonomy,
    );
  }

  // Cmf filters.
  $filters['title'] = array(
    'title' => t('title/subject'),
  );

  // Don't show these on the user page.
  if (!$true) {
    $filters['user'] = array(
      'title' => t('user list'),
      'options' => cmf_get_users(),
    );
    $filters['users'] = array(
      'title' => t('user name'),
    );
    $filters['role'] = array(
      'title' => t('user role'),
      'options' => cmf_get_roles('names'),
    );
    $filters['blocked'] = array(
      'title' => t('user status'),
      'options' => array(
        1 => t('active'),
        0 => t('blocked'),
      ),
    );
  }
  return $filters;
}

/**
 * QUERIES
 */

/** 
 * Build the variable parts of the query to be performed regarding the filter status.
 *
 * @return associative array with WHERE JOIN qury parts and respective arguments
 */
function cmf_build_filter_query() {
  $filters = cmf_filters();

  // Build query
  $where = $args = array();
  $join = '';
  foreach ($_SESSION['cmf_overview_filter'] as $index => $filter) {
    list($key, $value) = $filter;
    switch ($key) {
      case 'status':

        // Note: no exploitable hole as $key/$value have already been checked when submitted
        list($key, $value) = explode('-', $value, 2);
        $where[] = 'n.' . $key . ' = %d';
        break;
      case 'category':
        $table = "tn{$index}";
        $where[] = "{$table}.tid = %d";
        $join .= "INNER JOIN {term_node} {$table} ON n.nid = {$table}.nid ";
        break;
      case 'type':
        $where[] = "n.type = '%s'";
        break;
      case 'user':
        $where[] = "u.uid = %d";
        break;
      case 'role':
        $where[] = "u.uid = ur.uid AND ur.rid = %d";
        $join .= "INNER JOIN {users_roles} ur ON u.uid = ur.uid ";
        break;
      case 'title':
        $where[] = "LOWER(n.title) LIKE LOWER('%%%s%%')";
        break;
      case 'users':
        $where[] = "u.name = '%s'";
        break;
      case 'blocked':
        $where[] = "u.status = %d AND u.uid != 0";
        break;
    }
    $args[] = $value;
  }
  $where = count($where) ? 'WHERE ' . implode(' AND ', $where) : '';
  return array(
    'where' => $where,
    'join' => $join,
    'args' => $args,
  );
}

/** 
 * Build the header of the result table.
 *
 * @return array respecting tablesort_sql()
 */
function cmf_build_header() {
  $header = array();
  if (user_access('filter and manage site content')) {
    $header[] = theme('table_select_header_cell');
  }
  if ($_SESSION['cmf_show_nid']) {
    $header[] = array(
      'data' => t('ID'),
      'field' => 'nid',
    );
  }
  switch ($_SESSION['cmf_content_kind']) {
    case 'node':
      $header[] = array(
        'data' => t('Title'),
        'field' => 'title',
      );
      $header[] = array(
        'data' => t('Kind'),
      );
      $header[] = array(
        'data' => t('Node Type'),
        'field' => 'type',
      );
      if (!(arg(0) == 'user' && is_numeric(arg(1)) && arg(1) > 0)) {
        $header[] = array(
          'data' => t('Author'),
          'field' => 'username',
        );
      }
      $header[] = array(
        'data' => t('Status'),
        'field' => 'status',
      );
      $header[] = array(
        'data' => t('Time'),
        'field' => 'created',
        'sort' => 'desc',
      );
      break;
    case 'comment':
      $header[] = array(
        'data' => t('Subject'),
        'field' => 'subject',
      );
      $header[] = array(
        'data' => t('Kind'),
      );
      $header[] = array(
        'data' => t('Node Type'),
        'field' => 'type',
      );
      if (!(arg(0) == 'user' && is_numeric(arg(1)) && arg(1) > 0)) {
        $header[] = array(
          'data' => t('Author'),
          'field' => 'username',
        );
      }
      $header[] = array(
        'data' => t('Status'),
        'field' => 'status',
      );
      $header[] = array(
        'data' => t('Time'),
        'field' => 'created',
        'sort' => 'desc',
      );
      break;
    case 'both':
      $header[] = array(
        'data' => t('Title') . '/' . t('Subject'),
        'field' => 'title',
      );
      $header[] = array(
        'data' => t('Kind'),
      );
      $header[] = array(
        'data' => t('Node Type'),
        'field' => 'type',
      );
      if (!(arg(0) == 'user' && is_numeric(arg(1)) && arg(1) > 0)) {
        $header[] = array(
          'data' => t('Author'),
          'field' => 'username',
        );
      }
      $header[] = array(
        'data' => t('Node Status'),
        'field' => 'status',
      );
      $header[] = array(
        'data' => t('Time'),
        'field' => 'created',
        'sort' => 'desc',
      );
      break;
  }
  if (user_access('filter and manage site content')) {
    $header[] = array(
      'data' => t('Operations'),
    );
  }
  return $header;
}

/** 
 * Perform adjusted query.
 *
 * @param array respecting tablesort_sql()
 * @return result of permormed query
 */
function cmf_perform_query($header, $kind = NULL) {
  $filter = cmf_build_filter_query();
  if (is_null($kind)) {
    $kind = $_SESSION['cmf_content_kind'];
  }
  if (arg(0) == 'user' && is_numeric(arg(1)) && arg(1) > 0) {
    $filter['where'] .= ' AND u.uid = ' . arg(1);
  }
  switch ($kind) {
    case 'node':
      return pager_query('SELECT n.nid, n.title, n.type, n.status, n.created, ' . 'n.changed, n.promote, n.sticky, n.moderate, ' . 'u.name AS username, u.uid, r.body ' . 'FROM {node} n ' . 'JOIN {node_revisions} r ON r.vid = n.vid ' . 'INNER JOIN {users} u ON n.uid = u.uid ' . $filter['join'] . $filter['where'] . tablesort_sql($header), isset($_SESSION['cmf_max_rows']) ? $_SESSION['cmf_max_rows'] : 50, 0, NULL, $filter['args']);
      break;
    case 'comment':
      return pager_query('SELECT c.cid, c.subject, c.nid, c.comment, c.timestamp AS created, ' . 'c.status, c.name, c.homepage, u.name AS username, u.uid, n.type ' . 'FROM {comments} c ' . 'INNER JOIN {node} n ON c.nid = n.nid ' . 'INNER JOIN {users} u ON u.uid = c.uid ' . $filter['join'] . $filter['where'] . tablesort_sql($header), isset($_SESSION['cmf_max_rows']) ? $_SESSION['cmf_max_rows'] : 50, 0, NULL, $filter['args']);
      break;
    case 'both':
      $args = array_merge($filter['args'], $filter['args']);
      $where = $filter['where'];
      $cwhere = str_replace(array(
        'n.title',
        'n.uid',
      ), array(
        'c.subject',
        'c.uid',
      ), $where);
      $count_query = 'SELECT (' . 'SELECT COUNT(*) FROM {node} n' . ' INNER JOIN {users} u ON n.uid = u.uid ' . $filter['join'] . ' ' . $where . ') + (' . 'SELECT COUNT(*) FROM {comments} c INNER JOIN {node} n ON c.nid = n.nid ' . ' INNER JOIN {users} u ON u.uid = c.uid ' . $filter['join'] . ' ' . $cwhere . ') AS count';
      return pager_query('SELECT 0 AS cid, n.nid, n.title, NULL AS comment, n.type, n.status, n.created, ' . 'n.changed, n.promote, n.sticky, n.moderate, ' . 'u.name AS username, u.uid, r.body ' . 'FROM {node} n ' . 'JOIN {node_revisions} r ON r.vid = n.vid ' . 'INNER JOIN {users} u ON n.uid = u.uid ' . $filter['join'] . ' ' . $where . ' UNION SELECT c.cid, c.nid, c.subject AS title, c.comment, n.type, c.status, c.timestamp AS created, ' . '0 AS changed, 0 AS promote, 0 AS sticky, 0 AS moderate, ' . 'u.name AS username, u.uid, c.comment AS body ' . ' FROM {comments} c INNER JOIN {node} n ON c.nid = n.nid INNER JOIN {users} u ON u.uid = c.uid ' . $filter['join'] . ' ' . $cwhere . tablesort_sql($header), isset($_SESSION['cmf_max_rows']) ? $_SESSION['cmf_max_rows'] : 50, 0, $count_query, $args);
      break;
  }
}

/**
 * RESULTS
 */
include drupal_get_path('module', 'cmf') . "/node.inc";
include drupal_get_path('module', 'cmf') . "/comment.inc";
include drupal_get_path('module', 'cmf') . "/both.inc";

/**
 * AUX
 */

/**
 * Builds a list of available users
 *
 * @param the format in which to return the list
 * @return array of all available users
 */
function cmf_get_users() {
  $result = db_query('SELECT uid, name FROM {users} WHERE uid <> 0 ORDER BY name');
  $users = array();
  $users[0] = variable_get('anonymous', t('anonymous'));
  while ($account = db_fetch_object($result)) {
    $users[$account->uid] = $account->name;
  }
  return $users;
}

/**
 * Menu callback; Retrieve a JSON object containing autocomplete suggestions for existing users.
 */
function _cmf_user_autocomplete($string = '') {
  $matches = array();
  if ($string) {
    $result = db_query("SELECT name FROM {users} WHERE LOWER(name) LIKE LOWER('%s%%')", $string);
    while ($account = db_fetch_object($result)) {
      $matches[$account->name] = check_plain($account->name);
    }
  }
  print drupal_to_js($matches);
  exit;
}

/**
 * Builds a list of available roles
 *
 * @param the format in which to return the list
 * @return array of all available roles
 */
function cmf_get_roles($op) {
  switch ($op) {
    case 'names':
      $result = db_query('SELECT rid, name FROM {role} ORDER BY name');
      break;
  }
  $roles = array();
  for ($i = 0; $i < db_num_rows($result); $i++) {
    $role = db_fetch_object($result);
    $roles[$role->rid] = $role->name;
  }
  return $roles;
}

/**
 * Get the html code of an image
 *
 * @param the pretended image
 * @return html tag img
 */
function _cmf_get_img($action, $title) {
  $path = base_path() . drupal_get_path('module', 'cmf') . '/images/' . $action . '.png';
  if ($title == NULL) {
    $html = '<img src="' . $path . '" alt="untitled image" />';
  }
  else {
    $html = '<img src="' . $path . '" title="' . $title . '" alt="' . $title . '" />';
  }
  return $html;
}

/** 
 * Theme (node) type cell on table result.
 *
 * @ingroup themable
 *
 * @param 0 or node type key
 * @return formated (node) type
 */
function theme_cmf_type($type) {
  return db_result(db_query('SELECT name FROM {node_type} WHERE type = "%s"', $type));
}

/** 
 * Theme user cell on table result.
 *
 * @ingroup themable
 *
 * @param user ID
 * @return clickable username with status
 */
function theme_cmf_user($uid) {
  if ($uid == 0) {
    return variable_get('anonymous', t('anonymous'));
  }
  $result = db_query('SELECT name, status FROM {users} WHERE uid = %d', $uid);
  $user = db_fetch_array($result);
  $url_alias = _cmf_get_user_path($uid);
  $url = $url_alias ? $url_alias : 'user/' . $uid;
  if ($user['status']) {
    $output .= l($user['name'], $url, array());
  }
  else {
    $output .= l(_cmf_get_img('blocked', t('blocked')) . ' ' . $user['name'], $url, array(), NULL, NULL, FALSE, TRUE);
  }
  return $output;
}

/** 
 * Get the alias path to a user profile
 *
 * @param user ID
 * @return the relative URL of the user profile
 */
function _cmf_get_user_path($uid) {
  return db_result(db_query('SELECT dst FROM {url_alias} WHERE src = "%s";', 'user/' . $uid));
}

/** 
 * Get the term for a forum node
 *
 * @param node ID
 * @return the name and forum description
 */
function _cmf_get_forum($nid) {
  $path = array();
  $node = node_load($nid);
  $parents = taxonomy_get_parents_all($node->tid);
  foreach ($parents as $parent) {
    $path[] = $parent->name;
  }
  return implode(' > ', array_reverse($path));
}

Functions

Namesort descending Description
cmf_admin_content_page Called when user goes to example.com/admin/content/filter
cmf_build_filter_query Build the variable parts of the query to be performed regarding the filter status.
cmf_build_header Build the header of the result table.
cmf_filters List node administration filters that can be applied.
cmf_filter_form Defines the form for content administration filters.
cmf_filter_form_submit Handle post-validation form submission.
cmf_get_roles Builds a list of available roles
cmf_get_users Builds a list of available users
cmf_help Implementation of hook_help().
cmf_menu Implementation of hook_menu().
cmf_perform_query Perform adjusted query.
cmf_perm Implementation of hook_perm().
theme_cmf_filter_form Theme cmf administration filter form.
theme_cmf_type Theme (node) type cell on table result.
theme_cmf_user Theme user cell on table result.
_cmf_get_forum Get the term for a forum node
_cmf_get_img Get the html code of an image
_cmf_get_user_path Get the alias path to a user profile
_cmf_user_autocomplete Menu callback; Retrieve a JSON object containing autocomplete suggestions for existing users.