You are here

similarterms.module in Similar By Terms 5

Similar By Terms module displays a block with similar content based on taxonomy terms.

File

similarterms.module
View source
<?php

// by Jeff Robbins

/**
 * @file
 * Similar By Terms module displays a block with similar content
 * based on taxonomy terms.
 */

/**
 * Implementation of hook_block().
 */
function similarterms_block($op = 'list', $delta = 0, $edit = array()) {
  switch ($op) {
    case 'list':
      $blocks[]['info'] = t('Similar entries from ANY vocabulary.');
      if (variable_get('similarterms_vocabularies', 'multi_select_and_tags') == 'all') {
        foreach (taxonomy_get_vocabularies() as $v) {
          $blocks[$v->vid]['info'] = t('Similar entries from the @vocab vocabulary.', array(
            '@vocab' => $v->name,
          ));
        }
      }
      else {
        foreach (taxonomy_get_vocabularies() as $v) {

          // this only makes sense for multi-select vocabularies and free tagging
          if ($v->multiple || $v->tags) {
            $blocks[$v->vid]['info'] = t('Similar entries from the @vocab vocabulary.', array(
              '@vocab' => $v->name,
            ));
          }
        }
      }
      return $blocks;
    case 'configure':
      $form['count'] = array(
        '#type' => 'textfield',
        '#title' => t('Item count'),
        '#default_value' => variable_get('simterms_count_' . $delta, 5),
        '#size' => 3,
        '#description' => t('The maximum number of similar items to display'),
      );

      //petertj addition to configuration to permit display of current node in list
      $form['showcurrentnode'] = array(
        '#type' => 'checkbox',
        '#title' => t('Show current node as active in the list'),
        '#default_value' => variable_get('simterms_showcurrentnode_' . $delta, FALSE),
        '#required' => FALSE,
      );

      //mimo addition to configuration to limit to same page type
      $types = array(
        '0' => '<none>',
        '1' => t('same as current'),
      );
      $arr_types_obj = node_get_types();
      foreach ($arr_types_obj as $type => $obj) {
        $types[$type] = $obj->name;
      }
      $form['sametype'] = array(
        '#type' => 'select',
        '#title' => t('Content type limit'),
        '#default_value' => variable_get('simterms_sametype_' . $delta, FALSE),
        '#options' => $types,
        '#description' => t('Limit to pages of this or these content type(s)'),
        '#multiple' => TRUE,
      );
      if ($delta > 0) {
        $terms = array();
        $tree = taxonomy_get_tree($delta);
        foreach ($tree as $term) {
          $terms[$term->tid] = $term->name;
        }
        $form['ignoreterms'] = array(
          '#type' => 'select',
          '#title' => t('Terms to be ignored'),
          '#default_value' => variable_get('simterms_ignoreterms_' . $delta, array()),
          '#options' => $terms,
          '#description' => t('Ignore selected terms here from being used to search for similar entries'),
          '#multiple' => TRUE,
        );
      }
      return $form;
    case 'save':
      variable_set('simterms_count_' . $delta, $edit['count']);
      variable_set('simterms_sametype_' . $delta, $edit['sametype']);
      variable_set('simterms_ignoreterms_' . $delta, $edit['ignoreterms']);
      variable_set('similarterms_showcurrentnode_' . $delta, $edit['showcurrentnode']);
      return;
    case 'view':
      if ($delta == 0) {
        $block['subject'] = t('Similar');
        $block['content'] = theme('similarterms', variable_get('similarterms_display_options', 'title_only'), similarterms_list());
      }
      else {
        $block['subject'] = t('Similar');

        // $delta = $vocid - integer - vocabulary id, leave out to use ALL terms for this node
        $block['content'] = theme('similarterms', variable_get('similarterms_display_options', 'title_only'), similarterms_list($delta));
      }
      return $block;
  }
}

/**
 * Output the block
 *
 * @param $vocid
 *   integer - vocabulary id, leave out to use ALL terms for this node
 * @param $nid
 *   integer - nid, leave out to use the current node
 * @return
 *   an array of node objects
 */
function similarterms_list($vocid = 0, $nid = NULL) {
  $nodes = array();
  $sql = "";
  $args = array();
  $cache_lifetime = variable_get('similarterms_cache_options', 3600);
  if (arg(0) == 'node' && is_numeric(arg(1)) && !$nid) {
    $nid = arg(1);
  }
  if ($nid != NULL) {
    $cid = "{$vocid}:{$nid}";
    if ($cache_lifetime) {
      if ($cached = cache_get($cid, 'cache_similarterms')) {
        return unserialize($cached->data);
      }
    }
    $node_obj = node_load($nid);
    if ($vocid == 0) {
      $terms = array_keys(taxonomy_node_get_terms($node_obj->nid));
    }
    else {
      $terms = array_keys(taxonomy_node_get_terms_by_vocabulary($node_obj->nid, $vocid));
    }

    // Filter out some terms
    $terms_filter = variable_get('simterms_ignoreterms_' . $vocid, array());
    foreach ($terms_filter as $v) {
      $idx = array_search($v, $terms);
      if ($idx >= 0) {
        unset($terms[$idx]);
      }
    }
    $count = variable_get('simterms_count_' . $vocid, 5);
    if (!empty($terms)) {

      //past events
      $pasts = array();
      $sql = 'SELECT n.nid, n.title, COUNT(n.nid) AS ncount ';
      $sql .= 'FROM {node} n ';
      $sql .= 'INNER JOIN {term_node} tn ON n.nid = tn.nid ';
      $sql .= 'WHERE tn.tid IN (';
      $number_of_terms = count($terms);
      foreach ($terms as $terms_items) {
        $number_of_terms--;
        if ($number_of_terms) {
          $sql .= "'%s',";
        }
        else {
          $sql .= "'%s'";
        }
        $args[] = $terms_items;
      }
      $sql .= ') ';
      $types = variable_get('simterms_sametype_' . $vocid, FALSE);
      if ($types !== FALSE && is_array($types) && count($types) > 0 && $types['0'] == NULL) {
        if ($types[1]) {
          $node_obj = node_load($nid);
          $types[1] = $node_obj->type;
        }
        $sql .= 'AND n.type IN (';
        $number_of_types = count($types);
        foreach ($types as $types_items) {
          $number_of_types--;
          if ($number_of_types) {
            $sql .= "'%s',";
          }
          else {
            $sql .= "'%s'";
          }
          $args[] = $types_items;
        }
        $sql .= ') ';
      }

      //if showcurrentnode option is false (default state), create filter for query.
      if (!variable_get('similarterms_showcurrentnode_' . $vocid, FALSE)) {
        $sql .= 'AND n.nid != %d ';
        $args[] = $nid;
      }
      $sql .= 'AND n.status = 1 ';
      $sql .= 'AND n.moderate = 0 ';

      //      $sql .= "AND (n.language = '' OR n.language = '%s') ";
      //      $args[] = $node_obj->language;
      $sql .= 'GROUP BY n.nid, n.title, n.created ';
      if (variable_get('similarterms_ncount_options', 'default') == 'default') {
        $sql .= 'ORDER BY ncount DESC, ';
      }
      else {
        $sql .= 'ORDER BY ncount ASC, ';
      }
      $sql .= 'n.created DESC ';
      $sql .= 'LIMIT %d';
      $args[] = $count;
      $sql = db_rewrite_sql($sql);
      $result = db_query($sql, $args);

      //      watchdog('similarterms',  $sql, NULL, WATCHDOG_INFO);
      while ($r = db_fetch_object($result)) {
        $nodes[] = node_load($r->nid);
      }

      // Allow modules to alter the list of nodes by implementing a hook.
      // Design pattern from comment_invoke_comment().
      foreach (module_implements('similarterms') as $name) {
        $function = $name . '_similarterms';
        $function($nodes, $node_obj);
      }
      if ($cache_lifetime) {
        cache_set($cid, 'cache_similarterms', serialize($nodes), time() + $cache_lifetime);
      }
    }
  }
  return $nodes;
}

/**
 * Implementation of hook_menu().
 */
function similarterms_menu($may_cache) {
  $items = array();
  if ($may_cache) {
    $items[] = array(
      'path' => 'admin/settings/similarterms',
      'title' => t('Similar By Terms'),
      'description' => t('Basic Settings for similar term most settings are in the blocks config.'),
      'callback' => 'drupal_get_form',
      'callback arguments' => array(
        'similarterms_admin_settings',
      ),
      'access' => user_access('administer site configuration'),
      'type' => MENU_NORMAL_ITEM,
    );
  }
  return $items;
}

/**
 * Module settings page.
 */
function similarterms_admin_settings() {
  $vocabularies_options = array(
    'multi_select_and_tags' => 'Display multi-select and tags types only',
    'all' => 'Display all vocabularies types',
  );
  $form['similarterms_vocabularies'] = array(
    '#type' => 'radios',
    '#title' => t('Vocabularies types to list'),
    '#default_value' => variable_get("similarterms_vocabularies", 'multi_select_and_tags'),
    '#options' => $vocabularies_options,
    '#required' => FALSE,
  );
  $display_options = array(
    'title_only' => 'Display titles only',
    'teaser' => 'Display titles and teaser',
  );
  $form['similarterms_display_options'] = array(
    '#type' => 'radios',
    '#title' => t('Display Options'),
    '#default_value' => variable_get('similarterms_display_options', 'title_only'),
    '#options' => $display_options,
    '#required' => FALSE,
    '#prefix' => '<div>',
    '#suffix' => '</div>',
  );
  $ncount_options = array(
    'default' => t('Default sort order'),
    'unique' => t('Prefer more unique order'),
  );
  $form['similarterms_ncount_options'] = array(
    '#type' => 'radios',
    '#title' => t('Unique Order Options'),
    '#default_value' => variable_get('similarterms_ncount_options', 'default'),
    '#options' => $ncount_options,
    '#required' => FALSE,
    '#prefix' => '<div>',
    '#suffix' => '</div>',
  );
  $cache_options = drupal_map_assoc(array(
    0,
    300,
    600,
    900,
    1800,
    3600,
    7200,
    21600,
    43200,
    86400,
    604800,
    1209600,
    2419200,
    4838400,
    9676800,
    31536000,
  ), 'format_interval');
  $cache_options[0] = t('Never');
  $form['similarterms_cache_options'] = array(
    '#type' => 'select',
    '#title' => t('Cache Options'),
    '#default_value' => variable_get('similarterms_cache_options', 3600),
    '#options' => $cache_options,
    '#required' => FALSE,
  );
  $form['similarterms_clear_cache'] = array(
    '#type' => 'checkbox',
    '#title' => t('Clear Cache'),
    '#description' => t('Clear Similarterms Block Cache'),
  );

  // Get the weblinks categories to add to the blogroll
  //  $result = db_query('SELECT tid, name FROM {term_data} WHERE vid = %d ORDER BY weight, name', _weblinks_get_vocid());
  //  while ($row = db_fetch_object($result)) {
  // Set which link categories get displayed on the links page
  //    $form[$row->tid]['weblinks_page_'. $row->tid] = array(
  //      '#type' => 'checkbox',
  //      '#title' => t($row->name),
  //      '#default_value' => variable_get('weblinks_page_'. $row->tid, 1),
  //      '#required' => FALSE,
  //      '#description' => t('Check to enable this category'),
  //    );
  //  }
  $form['#submit']['similarterms_admin_settings_submit'] = array();
  return system_settings_form($form);
}
function similarterms_admin_settings_submit($form_id, $form_values) {
  if ($form_values['similarterms_clear_cache']) {
    cache_clear_all('*', 'cache_similarterms', TRUE);
    drupal_set_message(t('Similarterms Block Cache is now cleared'));
  }
}

/**
 * Theme function for similar block
 *
 * Available variables:
 * - $teaser: Display Yes = 0. No = 1
 * - $items: the list.
 *
 * @param array $nodes
 */
function theme_similarterms($display_options, $items) {
  $output = "";
  if (!empty($items)) {
    $output .= "<ul>\n";
    foreach ($items as $item) {
      $output .= '<li>' . l($item->title, 'node/' . $item->nid);
      if ($display_options == 'teaser') {
        $output .= ' - ' . $item->teaser;
      }
      $output .= "</li>\n";
    }
    $output .= "</ul>\n";
  }
  return $output;
}

Functions

Namesort descending Description
similarterms_admin_settings Module settings page.
similarterms_admin_settings_submit
similarterms_block Implementation of hook_block().
similarterms_list Output the block
similarterms_menu Implementation of hook_menu().
theme_similarterms Theme function for similar block