Index: modules/taxonomy.views.inc
===================================================================
RCS file: modules/taxonomy.views.inc
diff -N modules/taxonomy.views.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/taxonomy.views.inc	14 Mar 2008 06:19:21 -0000
@@ -0,0 +1,369 @@
+<?php
+/**
+ * @file
+ * Provide views data and handlers for user.module
+ *
+ * Status
+ * Vocab base view
+ *  - Fields
+ *    - Name
+ *  - Filters
+ *    - Name
+ *  - Sorts
+ *    - Name
+ *  - Arguments
+ *    - Name
+ *    - Name
+ *    - Name
+ *
+ * Node base view
+ *  WIP
+ *
+ * Term_data base view
+ *  - Fields
+ *    - Name
+ *  - Filters
+ *    - Vid
+ *  - Sorts
+ *    - Name(and weight)
+ *  - Arguments
+ *    - taxid
+ *    - taxletter
+ *    - vocid
+ */
+
+/**
+ * @defgroup views_taxonomy_module taxonomy.module handlers
+ *
+ * @{
+ */
+
+/**
+ * Implementation of hook_views_data()
+ */
+function taxonomy_views_data() {
+  $vocabularies = taxonomy_get_vocabularies();
+
+  $data = array();
+
+  // Define the base group of this table. Fields that don't
+  // have a group defined will go into this field by default.
+  $data['vocabulary']['table']['group']  = t('Vocabulary');
+
+  // @todo -- I don't see a point.
+/*
+  // Advertise this table as a possible base table
+  $data['vocabulary']['table']['base'] = array(
+    'field' => 'vid',
+    'title' => t('Vocabulary'),
+    'help' => t('The vocabulary type allows views of your site\'s vocabularies.'),
+    'weight' => 10,
+  );
+*/
+
+  // For other tables, explain how we join.
+  $data['vocabulary']['table']['join'] = array(
+    // TODO ??
+  );
+
+  // vocabulary name
+  $data['vocabulary']['name'] = array(
+    'title' => t('Name'), // The item it appears as on the UI,
+    'help' => t('Name of the vocabulary a term is a member of.'),
+    'field' => array(
+      'handler' => 'views_handler_field',
+      'click sortable' => TRUE,
+    ),
+  );
+
+
+  $data['term_data']['table']['group']  = t('Taxonomy');
+  $data['term_data']['table']['base'] = array(
+    'field' => 'tid',
+    'title' => t('Terms'),
+    'help' => t('The taxonomy type allows views of your site\'s taxonomy terms.'),
+    'weight' => 10,
+  );
+
+
+  // The term data table
+  $data['term_data']['table']['join'] = array(
+    'node' => array(
+      'handler' => 'views_join',
+      'arguments' => array('term_data', 'term_node', 'tid', 'tid'),
+    ),
+    'node_revision' => array(
+      'handler' => 'views_join',
+      'arguments' => array('term_data', 'term_node', 'tid', 'tid'),
+    ),
+  );
+
+  // All terms attached to the node.
+  $data['term_data']['name'] = array(
+    'title' => t('All Terms'),
+    'help' => 'Taxonomy'. (!empty($vocab->description) ? ': '. $vocab->description : ''),
+    'field' => array(
+      // TODO - does this actually do the extra queries still.
+      'help' => t('This will display all taxonomy terms associated with the node. Note that this causes one extra query per row displayed, and might have a minor performance impact.'),
+      'handler' => 'views_handler_field_term_data_name',
+      'click sortable' => false, // ??
+    ),
+    'sort' => array(
+      'title' => t('Term'),
+      'handler' => 'views_handler_sort',
+      'help' => t('This will sort nodes by taxonomy weight and name, as defined in the category administration.'),
+    ),
+    'filter' => array(
+      'handler' => 'views_handler_filter_taxonomy',
+    ),
+  );
+
+/* -- leaving these out for now. This will require pseudo tables so that they
+  filter the term_data table properly.
+
+  // Provide
+  foreach ($vocabularies as $vocab) {
+    $data['term_data']['name-'. $vocab->vid] = array(
+      'title' => t('Terms for @vocab_name', array('@vocab_name' => $vocab->name)),
+      'help' => t('This will display all taxonomy terms associated with the node that are members of @vocab_name. Note that this causes one extra query per row displayed, and might have a minor performance impact.', array('@vocab_name' => $vocab->name)),
+      'field' => array(
+        'field' => 'name', // the real field
+        'vid' => $vocab->vid,
+        'handler' => 'views_handler_field_term_data_name',
+//        'arguments' => array($vocab->vid),
+        'click sortable' => false, // ??
+      ),
+      'sort' => array(
+        'field' => 'name',
+        'vid' => $vocab->vid,
+        'handler' => 'views_handler_sort',
+        'help' => t('This will sort nodes by taxonomy weight and name, as defined in the category administration.'),
+      ),
+      'filter' => array(
+        'field' => 'name',
+        'vid' => $vocab->vid,
+        'handler' => 'views_handler_filter_taxonomy',
+      ),
+    );
+  }
+*/
+
+  $data['term_data']['description'] = array(
+    'title' => t('Description'), // The item it appears as on the UI,
+    'field' => array(
+      'field' => 'description', // the real field
+      'group' => t('Taxonomy'), // The group it appears in on the UI,
+      'help' => t('This will display the description associated with a taxonomy term.'),
+      'handler' => 'views_handler_field',
+      'click sortable' => false, // would you want to?
+    ),
+  );
+
+  $data['term_data']['vid'] = array(
+    'title' => t('Vocabulary Name'),
+    'help' => t('This will filter a view to only nodes that contain a term in the associated vocabulary.'),
+    'filter' => array(
+      'handler' => 'views_handler_filter_equality',
+    ),
+  );
+
+  // The term node table
+  $data['term_node']['table']['group']  = t('Term node');
+
+  $data['term_node']['table']['join'] = array(
+    'term_data' => array(
+      'handler' => 'views_join',
+      'arguments' => array('term_node', 'term_data', 'tid', 'tid'),
+    ),
+    'node' => array(
+      'handler' => 'views_join',
+      'arguments' => array('term_node', 'node', 'vid', 'vid'),
+    ),
+    'node_revision' => array(
+      'handler' => 'views_join',
+      'arguments' => array('term_node', 'node_revision', 'vid', 'vid'),
+    ),
+  );
+
+  // @todo: This doesn't work here, but we can alter it in later.
+/*
+  $data['node']['table']['join'] = array(
+    'term_node' => array(
+      'handler' => 'views_join',
+      'arguments' => array('node', 'term_node', 'nid', 'nid'),
+    ),
+  );
+*/
+
+
+  // Args
+  // *    - taxid
+  // *    - taxletter
+  // *    - vocid
+
+  return $data;
+}
+
+class views_handler_field_term_data_name extends views_handler_field {
+  /**
+   * Override init function to provide generic option to link to user.
+   */
+  function init(&$view, &$data) {
+    parent::init($view, $data);
+    $this->additional_fields['tax'] = array(
+      'table' => 'node',
+      'field' => 'vid'
+    );
+  }
+
+  function construct() {
+    parent::construct();
+    if (!empty($this->definition['vid'])) {
+      $this->vocabulary = $vid;
+    }
+  }
+
+  /**
+   * Provide meaningful defaults
+   */
+  function options(&$options) {
+    parent::options($options);
+    $options['link_to_taxonomy'] = TRUE;
+  }
+
+  /**
+   * Provide "link to term" option.
+   */
+  function options_form(&$form, &$form_state) {
+    $form['link_to_taxonomy'] = array(
+      '#title' => t('Link this field to its term page'),
+      '#type' => 'checkbox',
+      '#default_value' => !empty($this->options['link_to_taxonomy']),
+    );
+  }
+
+  /**
+   * Add this term to the query
+   */
+  function query() {
+    // Add any additional fields we are given.
+    if (!empty($this->additional_fields) && is_array($this->additional_fields)) {
+      foreach ($this->additional_fields as $identifier => $info) {
+        if (is_array($info)) {
+          if (isset($info['table'])) {
+            $table_alias = $this->query->ensure_table($info['table'], $this->relationship);
+          }
+          else {
+            $table_alias = $this->table_alias;
+          }
+          $this->field_keys[$identifier] = $this->query->add_field($table_alias, $info['field']);
+        }
+        else {
+          $this->aliases[$info] = $this->query->add_field($this->table_alias, $info);
+        }
+      }
+    }
+  }
+
+  function pre_render($result) {
+    vsm($result);
+  }
+
+  function render($values) {
+    // Start our local node object.
+    $node = drupal_clone($values);
+    // we need a vid for taxonomy functions now.
+    $node->vid = db_result(db_query('SELECT vid FROM {node} WHERE nid = %d', $values->nid));
+
+    if (isset($this->vocabulary)) {
+      $node->taxonomy = taxonomy_node_get_terms_by_vocabulary($node, $this->vocabulary);
+    }
+    else {
+      $node->taxonomy = taxonomy_node_get_terms($node);
+    }
+    if (!empty($this->options['link_to_taxonomy'])) {
+      // trigger the correct build mode. ie build_mode != NODE_BUILD_PREVIEW
+      $node->build_mode = NODE_BUILD_NORMAL;
+      $links = theme('links', taxonomy_link('taxonomy terms', $node));
+    }
+    else {
+      foreach ($node->taxonomy as $term) {
+        $links[] = check_plain($term->name);
+      }
+      $links = !empty($links) ? implode(' | ', $links) : '';
+    }
+    return $links;
+  }
+}
+
+class views_handler_sort_taxonomy extends views_handler_sort {
+  /**
+   * Called to add the sort to a query.
+   */
+  function query() {
+    $this->ensure_my_table();
+
+    // Add the field.
+    $this->query->add_orderby($this->table_alias, $this->real_field, $this->options['order']);
+    // TODO Missing sort by weight used previously.
+  }
+}
+
+class views_handler_argument_taxonomy extends views_handler_argument {
+
+  /**
+   * Override the behavior of title(). Get the title of the node.
+   */
+  function title() {
+    $term = taxonomy_get_term($this->argument);
+    if (!empty($term)) {
+      return check_plain($term->name);
+    }
+    // TODO review text
+    return t('No name');
+  }
+}
+
+/**
+ * Overide equality so we can steal some comparison code and just overide the choice form.
+ */
+class views_handler_filter_taxonomy extends views_handler_filter_in_operator  {
+
+  function value_form(&$form, &$form_state) {
+    $options = array();
+    $where = '';
+
+    if (isset($this->definition['vid'])) {
+      $where = "WHERE td.vid = {$this->definition['vid']}";
+    }
+    $result = db_query("SELECT DISTINCT(td.tid), td.name, td.weight, v.name as vocabname, v.weight FROM {term_data} td LEFT JOIN {vocabulary} v ON v.vid = td.vid $where ORDER BY v.weight, v.name, td.weight, td.name");
+    while ($obj = db_fetch_object($result)) {
+      if ($this->definition['vid']) {
+        $options[$obj->tid] = "$obj->name";
+      }
+      else {
+        $options[$obj->tid] = "$obj->vocabname: $obj->name";
+      }
+    }
+
+    $form['value'] = array(
+      '#title' => t('Term'),
+      '#type' => 'select',
+      '#multiple' => TRUE,
+      '#options' => $options,
+      '#default_value' => $options,
+    );
+    return $form;
+  }
+
+  function admin_summary() {
+    $output = '';
+
+    foreach ($this->value as $tid) {
+      $term = taxonomy_get_term($tid);
+      $terms[] = $term->name;
+    }
+    $output .= implode(', ', $terms);
+    return check_plain($this->operator) .' '. check_plain($output);
+  }
+}
\ No newline at end of file
