summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--includes/admin.inc107
-rw-r--r--includes/handlers.inc87
-rw-r--r--includes/query.inc8
-rw-r--r--modules/node.views.inc40
-rw-r--r--modules/profile.views.inc22
-rw-r--r--modules/taxonomy.views.inc689
-rw-r--r--modules/user.views.inc9
-rw-r--r--views_ui.module4
8 files changed, 872 insertions, 94 deletions
diff --git a/includes/admin.inc b/includes/admin.inc
index d09af08..61da34e 100644
--- a/includes/admin.inc
+++ b/includes/admin.inc
@@ -857,6 +857,10 @@ function template_preprocess_views_ui_edit_item(&$vars) {
}
$fields[$id]['info'] = $handler->admin_summary();
+ if ($handler->has_extra_options()) {
+ $fields[$id]['links'] = l('<span>' . t('Settings') . '</span>', "admin/build/views/nojs/config-item-extra/$view->name/$display->id/$type/$id", array('attributes' => array('class' => 'views-button-configure views-ajax-link', 'title' => t('Settings')), 'html' => true));
+ }
+
if ($handler->needs_style_plugin()) {
$style_plugin = views_fetch_plugin_data('style', $handler->options['style_plugin']);
$style_title = empty($style_plugin['title']) ? t('Missing style plugin') : $style_plugin['title'];
@@ -1837,6 +1841,109 @@ function views_ui_config_item_form_expose($form, &$form_state) {
}
/**
+ * Page callback to configure an item
+ */
+function views_ui_config_item_extra($js, $view, $display_id, $type, $id) {
+ views_include('ajax');
+ $form_state = array(
+ 'view' => &$view,
+ 'ajax' => $js,
+ 'display_id' => $display_id,
+ 'id' => $id,
+ 'type' => $type,
+ );
+
+ $output = views_ajax_form_wrapper('views_ui_config_item_extra_form', $form_state);
+
+ if ($js) {
+ // If we don't have an output object, it was submitted. Set up the submission.
+ if (empty($output)) {
+ // Sometimes we need to re-generate the form for multi-step type operations.
+ return views_ui_regenerate_tabs($view, $display_id);
+ }
+ return views_ajax_render($output);
+ }
+
+ return $output;
+}
+
+/**
+ * Form to config_item items in the views UI.
+ */
+function views_ui_config_item_extra_form(&$form_state) {
+ $view = &$form_state['view'];
+ $display_id = $form_state['display_id'];
+ $type = $form_state['type'];
+ $id = $form_state['id'];
+
+ $form = array('options' => array('#tree' => TRUE));
+ if (!$view->set_display($display_id)) {
+ views_ajax_render(t('Invalid display id @display', array('@display' => $display_id)));
+ }
+ $item = $view->get_item($display_id, $type, $id);
+
+ if ($item) {
+ $handler = views_get_handler($item['table'], $item['field'], $type);
+ if (empty($handler)) {
+ $form['markup'] = array('#value' => t("Error: handler for @table > @field doesn't exist!", array('@table' => $item['table'], '@field' => $item['field'])));
+ break;
+ }
+ else {
+ $handler->init($view, $item);
+ $types = views_object_types();
+
+ $form['#title'] = check_plain($view->display[$display_id]->display_title) . ': ';
+ $form['#title'] .= t('Configure extra settings for @type "@item"', array('@type' => strtolower($types[$type]['stitle']), '@item' => $handler->ui_name()));
+
+ $form['#section'] = $display_id . '-' . $type . '-' . $id;
+
+ // Get form from the handler.
+ $handler->extra_options_form($form['options'], $form_state);
+ $form_state['handler'] = &$handler;
+
+ }
+
+ views_ui_standard_form_buttons($form, $form_state, 'views_ui_config_item_form', NULL, t('Remove'), 'remove');
+ }
+ return $form;
+}
+
+/**
+ * Submit handler for configing new item(s) to a view.
+ */
+function views_ui_config_item_extra_form_validate($form, &$form_state) {
+ $form_state['handler']->extra_options_validate($form['options'], $form_state);
+}
+
+/**
+ * Submit handler for configing new item(s) to a view.
+ */
+function views_ui_config_item_extra_form_submit($form, &$form_state) {
+ // Run it through the handler's submit function.
+ $form_state['handler']->extra_options_submit($form['options'], $form_state);
+ $item = $form_state['handler']->options;
+
+ // Store the data we're given.
+ foreach ($form_state['values']['options'] as $key => $value) {
+ $item[$key] = $value;
+ }
+
+ // Store the item back on the view
+ $form_state['view']->set_item($form_state['display_id'], $form_state['type'], $form_state['id'], $item);
+
+ views_ui_check_stack($form_state);
+
+ // Write to cache
+ views_ui_cache_set($form_state['view']);
+ if (isset($form_state['next'])) {
+ $form_state['redirect'] = 'admin/build/views/nojs/config-item/' . $form_state['view']->name . "/$form_state[display_id]/$form_state[type]/$form_state[next]";
+ }
+ else {
+ $form_state['redirect'] = 'admin/build/views/edit/' . $form_state['view']->name;
+ }
+}
+
+/**
* Page callback to change the summary style of an argument
*/
function views_ui_change_style($js, $view, $display_id, $type, $id) {
diff --git a/includes/handlers.inc b/includes/handlers.inc
index 7fdb4fa..b0b72e6 100644
--- a/includes/handlers.inc
+++ b/includes/handlers.inc
@@ -296,6 +296,33 @@ class views_handler extends views_object {
function options_submit($form, &$form_state) { }
/**
+ * If a handler has 'extra options' it will get a little settings widget and
+ * another form called extra_options.
+ */
+ function has_extra_options() { return FALSE; }
+
+ /**
+ * Provide defaults for the handler.
+ */
+ function extra_options(&$option) { }
+
+ /**
+ * Provide a form for setting options.
+ */
+ function extra_options_form(&$form, &$form_state) { }
+
+ /**
+ * Validate the options form.
+ */
+ function extra_options_validate($form, &$form_state) { }
+
+ /**
+ * Perform any necessary changes to the form values prior to storage.
+ * There is no need for this function to actually store the data.
+ */
+ function extra_options_submit($form, &$form_state) { }
+
+ /**
* Set new exposed option defaults when exposed setting is flipped
* on.
*/
@@ -1858,6 +1885,15 @@ class views_handler_filter_in_operator extends views_handler_filter {
function construct() {
parent::construct();
$this->value_title = t('Options');
+ $this->value_options = NULL;
+ }
+
+ /**
+ * Child classes should override this function to set the 'value options'.
+ * This can use a guard to be used to reduce database hits as much as
+ * possible.
+ */
+ function get_value_options() {
$this->value_options = array(t('Yes'), t('No'));
}
@@ -1878,6 +1914,7 @@ class views_handler_filter_in_operator extends views_handler_filter {
}
function value_form(&$form, &$form_state) {
+ $this->get_value_options();
$form['value'] = array(
'#type' => 'checkboxes',
'#title' => $this->value_title,
@@ -1895,6 +1932,7 @@ class views_handler_filter_in_operator extends views_handler_filter {
return t('exposed');
}
+ $this->get_value_options();
if (count($this->value) == 1) {
// If there is only one, show it as an =.
$keys = array_keys($this->value);
@@ -2239,21 +2277,16 @@ class views_handler_filter_date extends views_handler_filter_numeric {
* The construct method needs to be overridden to provide a list of options;
* alternately, the value_form and admin_summary methods need to be overriden
* to provide something that isn't just a select list.
+ *
+ * @todo Should this handler allow an option as to whether or not to avoid
+ * duplicates? That would have an effect on the join, but if you're not
+ * concerned about duplicates you'll get more efficient queries.
*/
-class views_handler_filter_many_to_one extends views_handler_filter {
- function construct() {
- parent::construct();
- // @todo Pull depth information from definition.
- $this->allow_depth = FALSE;
- $this->value_title = t('Options');
- $this->value_options = array();
- }
-
+class views_handler_filter_many_to_one extends views_handler_filter_in_operator {
function options(&$options) {
parent::options($options);
$options['operator'] = 'or';
$options['value'] = array();
- $options['depth'] = 0;
}
/**
@@ -2268,6 +2301,7 @@ class views_handler_filter_many_to_one extends views_handler_filter {
}
function value_form(&$form, &$form_state) {
+ $this->get_value_options();
$form['value'] = array(
'#type' => 'select',
'#title' => $this->value_title,
@@ -2278,39 +2312,6 @@ class views_handler_filter_many_to_one extends views_handler_filter {
);
}
- function admin_summary() {
- if (!empty($this->options['exposed'])) {
- return t('exposed');
- }
-
- if (count($this->value) == 1) {
- // If there is only one, show it as an =.
- $keys = array_keys($this->value);
- $key = array_shift($keys);
- if (!empty($this->value_options[$key])) {
- $value = check_plain($this->value_options[$key]);
- }
- else {
- $value = t('Unknown');
- }
-
- return ($this->operator == 'in' ? '=' : '<>') . ' ' . $value;
- }
- $output = '';
- foreach ($this->value as $value) {
- if ($output) {
- $output .= ', ';
- }
- if (strlen($output) > 8) {
- $output .= '...';
- break;
- }
- $output .= check_plain($this->value_options[$value]);
- }
-
- return check_plain($this->operator) . ' ' . $output;
- }
-
/**
* Override ensure_my_table so we can control how this joins in.
* The operator actually has influence over joining.
diff --git a/includes/query.inc b/includes/query.inc
index 98a446a..ff0ba6c 100644
--- a/includes/query.inc
+++ b/includes/query.inc
@@ -481,6 +481,14 @@ class views_query {
if (!empty($this->table_queue[$table])) {
return $this->table_queue[$table];
}
+
+ // In rare cases we might *only* have aliased versions of the table.
+ if (!empty($this->tables[$this->primary_table][$table])) {
+ $alias = $this->tables[$this->primary_table][$table]['alias'];
+ if (!empty($this->table_queue[$alias])) {
+ return $this->table_queue[$alias];
+ }
+ }
}
/**
diff --git a/modules/node.views.inc b/modules/node.views.inc
index 1eafa3a..27dfc4f 100644
--- a/modules/node.views.inc
+++ b/modules/node.views.inc
@@ -26,7 +26,7 @@ function node_views_data() {
$data['node']['table']['base'] = array(
'field' => 'nid',
'title' => t('Node'),
- 'help' => t('The node type allows views of your site\'s primary content.'),
+ 'help' => t('Nodes are a Drupal site\'s primary content.'),
'weight' => 10,
);
@@ -92,7 +92,7 @@ function node_views_data() {
// Information for accepting a nid as an argument
'argument' => array(
'handler' => 'views_handler_argument_node_nid',
- 'click sortable' => TRUE,
+ 'name field' => 'title', // the field to display in the summary.
),
// Information for accepting a nid as a filter
'filter' => array(
@@ -311,7 +311,7 @@ function node_views_data() {
$data['node_revisions']['table']['base'] = array(
'field' => 'vid',
'title' => t('Node revisions'),
- 'help' => t('Node revisions allow you to list revisions of nodes.'),
+ 'help' => t('Node revisions are a history of changes to nodes.'),
);
// For other base tables, explain how we join
@@ -840,8 +840,6 @@ class views_handler_argument_node_type extends views_handler_argument {
* @ingroup views_argument_handlers
*/
class views_handler_argument_node_nid extends views_handler_argument {
- // No constructor is necessary.
-
/**
* Override the behavior of title(). Get the title of the node.
*/
@@ -1008,22 +1006,15 @@ class views_handler_argument_node_created_week extends views_handler_argument_fo
* @ingroup views_filter_handlers
*/
class views_handler_filter_node_type extends views_handler_filter_in_operator {
- function construct() {
- parent::construct();
- $this->value_title = t('Node type');
- $types = node_get_types();
- foreach ($types as $type => $info) {
- $options[$type] = $info->name;
+ function get_value_options() {
+ if (!isset($this->value_options)) {
+ $this->value_title = t('Node type');
+ $types = node_get_types();
+ foreach ($types as $type => $info) {
+ $options[$type] = $info->name;
+ }
+ $this->value_options = $options;
}
- $this->value_options = $options;
- }
-
- function options(&$options) {
- parent::options($options);
- // Set the default value to the first node type, so that there is something
- // reasonable there.
- $types = array_keys(node_get_types());
- $options['value'] = array(array_shift($types));
}
}
@@ -1080,10 +1071,11 @@ class views_handler_filter_history_user_timestamp extends views_handler_filter {
* @ingroup views_filter_handlers
*/
class views_handler_filter_node_language extends views_handler_filter_in_operator {
- function construct() {
- parent::construct();
- $this->value_title = t('Node language');
- $this->value_options = locale_language_list();
+ function get_value_options() {
+ if (empty($this->value_options)) {
+ $this->value_title = t('Node language');
+ $this->value_options = locale_language_list();
+ }
}
function options(&$options) {
diff --git a/modules/profile.views.inc b/modules/profile.views.inc
index a61e1db..73c0392 100644
--- a/modules/profile.views.inc
+++ b/modules/profile.views.inc
@@ -330,11 +330,6 @@ class views_handler_field_profile_list extends views_handler_field_prerender_lis
* @ingroup views_filter_handlers
*/
class views_handler_filter_profile_selection extends views_handler_filter_in_operator {
- function construct() {
- parent::construct();
- $this->value_options = NULL;
- }
-
function get_value_options() {
if (isset($this->value_options)) {
return;
@@ -351,23 +346,6 @@ class views_handler_filter_profile_selection extends views_handler_filter_in_ope
}
}
}
-
- function options(&$options) {
- parent::options($options);
- $options['value'] = array();
- }
-
- function options_form(&$form, &$form_state) {
- // Do this only when really needed in order to reduce database hits.
- $this->get_value_options();
- parent::options_form($form, $form_state);
- }
-
- function admin_summary() {
- // Do this only when really needed in order to reduce database hits.
- $this->get_value_options();
- return parent::admin_summary();
- }
}
/**
diff --git a/modules/taxonomy.views.inc b/modules/taxonomy.views.inc
new file mode 100644
index 0000000..4f8265d
--- /dev/null
+++ b/modules/taxonomy.views.inc
@@ -0,0 +1,689 @@
+<?php
+/**
+ * @file
+ *
+ * Provide views data and handlers for taxonomy.module
+ */
+
+/**
+ * @defgroup views_taxonomy_module taxonomy.module handlers
+ *
+ * @{
+ */
+
+/**
+ * Implementation of hook_views_data()
+ */
+function taxonomy_views_data() {
+// $vocabularies = taxonomy_get_vocabularies();
+
+ $data = array();
+
+ // ----------------------------------------------------------------------
+ // vocabulary table
+
+ $data['vocabulary']['table']['group'] = t('Taxonomy');
+
+ $data['vocabulary']['table']['join'] = array(
+ // vocabulary links to term_data directly via vid.
+ 'term_data' => array(
+ 'left_field' => 'vid',
+ 'field' => 'vid',
+ ),
+ // vocabulary links to node through term_data via vid
+ 'node' => array(
+ 'left_table' => 'term_data',
+ 'left_field' => 'vid',
+ 'field' => 'vid',
+ ),
+ // vocabulary links to node_revision via term_data
+ 'node_revision' => array(
+ 'left_table' => 'term_data',
+ 'left_field' => 'vid',
+ 'field' => 'vid',
+ ),
+ // vocabulary links to users via term_data
+ 'users' => array(
+ 'left_table' => 'term_data',
+ 'left_field' => 'vid',
+ 'field' => 'vid',
+ ),
+ );
+
+ // vocabulary name
+ $data['vocabulary']['name'] = array(
+ 'title' => t('Vocabulary name'), // The item it appears as on the UI,
+ 'field' => array(
+ 'help' => t('Name of the vocabulary a term is a member of. This will be the vocabulary that whichever term the "Taxonomy: Term" field is; and can similarly cause duplicates.'),
+ 'handler' => 'views_handler_field',
+ 'click sortable' => TRUE,
+ ),
+ );
+ $data['vocabulary']['vid'] = array(
+ 'title' => t('Vocabulary ID'), // The item it appears as on the UI,
+ 'help' => t('The taxonomy vocabulary ID'),
+ 'argument' => array(
+ 'handler' => 'views_handler_argument_vocabulary_vid',
+ 'name field' => 'name',
+ ),
+ );
+
+ // ----------------------------------------------------------------------
+ // term_data table
+
+ $data['term_data']['table']['group'] = t('Taxonomy');
+ $data['term_data']['table']['base'] = array(
+ 'field' => 'tid',
+ 'title' => t('Terms'),
+ 'help' => t('Taxonomy terms are attached to nodes.'),
+ 'weight' => 10,
+ );
+
+
+ // The term data table
+ $data['term_data']['table']['join'] = array(
+ 'node' => array(
+ 'left_table' => 'term_node',
+ 'left_field' => 'tid',
+ 'field' => 'tid',
+ ),
+ 'node_revision' => array(
+ 'left_table' => 'term_node',
+ 'left_field' => 'tid',
+ 'field' => 'tid',
+ ),
+ 'users' => array(
+ 'left_table' => 'term_node',
+ 'left_field' => 'tid',
+ 'field' => 'tid',
+ ),
+ );
+
+ // Term name field
+ $data['term_data']['name'] = array(
+ 'title' => t('Term'),
+ 'help' => t('Taxonomy terms. Note that using this can cause duplicate nodes to appear in views; you must add filters to reduce the resultset.'),
+ 'field' => array(
+ 'handler' => 'views_handler_field_taxonomy',
+ 'click sortable' => TRUE,
+ ),
+ 'sort' => array(
+ 'handler' => 'views_handler_sort',
+ ),
+// 'argument' => array(
+// 'handler' => 'views_handler_argument_term_data_name', // @todo
+// 'help' => t('Taxonomy term name'),
+// ),
+ );
+
+ // taxonomy weight
+ $data['term_data']['weight'] = array(
+ 'title' => t('Weight'),
+ 'help' => t('The term weight field'),
+ 'field' => array(
+ 'handler' => 'views_hander_field',
+ 'click sortable' => TRUE,
+ ),
+ 'sort' => array(
+ 'handler' => 'views_hander_sort',
+ ),
+ );
+
+ // Term description
+ $data['term_data']['description'] = array(
+ 'title' => t('Term description'), // The item it appears as on the UI,
+ 'help' => t('The description associated with a taxonomy term.'),
+ 'field' => array(
+ 'field' => 'description', // the real field
+ 'group' => t('Taxonomy'), // The group it appears in on the UI,
+ 'handler' => 'views_handler_field_markup',
+ 'format' => FILTER_FORMAT_DEFAULT,
+ ),
+ );
+
+ // Term vocabulary
+ $data['term_data']['vid'] = array(
+ 'title' => t('Vocabulary'),
+ 'help' => t('Filter the results of "Taxonomy: Term" to a particular vocabulary.'),
+ 'filter' => array(
+ 'handler' => 'views_handler_filter_vocabulary_vid', // @todo
+ ),
+ );
+
+ // ----------------------------------------------------------------------
+ // term_node table
+
+ $data['term_node']['table']['group'] = t('Taxonomy');
+
+ $data['term_node']['table']['join'] = array(
+ 'term_data' => array(
+ // links directly to term_data via tid
+ 'left_field' => 'tid',
+ 'field' => 'tid',
+ ),
+ 'node' => array(
+ // links directly to node via nid
+ 'left_field' => 'nid',
+ 'field' => 'nid',
+ ),
+ 'node_revisions' => array(
+ // links directly to node_revisions via vid
+ 'left_field' => 'vid',
+ 'field' => 'vid',
+ ),
+ 'users' => array(
+ // Links to users via node.nid
+ 'left_table' => 'node',
+ 'left_field' => 'nid',
+ 'field' => 'nid',
+ ),
+ );
+
+ // tid field
+ $data['term_node']['tid'] = array(
+ 'title' => t('Term ID'),
+ 'help' => t('The taxonomy term ID'),
+ 'field' => array(
+ 'title' => t('All terms'),
+ 'help' => t('Display all taxonomy terms associated with a node.'),
+ 'handler' => 'views_handler_field_term_node_tid',
+ ),
+// 'argument' => array(
+// 'handler' => 'views_handler_argument_term_node_tid', // @todo
+// ),
+ 'filter' => array(
+ 'handler' => 'views_handler_filter_term_node_tid',
+ ),
+ );
+
+ // @todo: term_relation
+ // @todo: term_synonym
+
+ // ----------------------------------------------------------------------
+ // term_hierarchy table
+
+ $data['term_hierarchy']['table']['group'] = t('Taxonomy');
+
+ $data['term_hierarchy']['table']['join'] = array(
+ 'term_hierarchy' => array(
+ // links to self through left.tid = right.parent
+ 'left_field' => 'tid',
+ 'field' => 'right',
+ ),
+ 'term_data' => array(
+ // links directly to term_data via tid
+ 'left_field' => 'tid',
+ 'field' => 'tid',
+ ),
+ 'node' => array(
+ // links to node thorugh term_data
+ 'left_table' => 'term_data',
+ 'left_field' => 'tid',
+ 'field' => 'tid',
+ ),
+ 'node_revisions' => array(
+ // links to node_revisions thorugh term_data
+ 'left_table' => 'term_data',
+ 'left_field' => 'tid',
+ 'field' => 'tid',
+ ),
+ 'users' => array(
+ // links to users thorugh term_data
+ 'left_table' => 'term_data',
+ 'left_field' => 'tid',
+ 'field' => 'tid',
+ ),
+ );
+
+ // ----------------------------------------------------------------------
+ // term_synonym table
+
+ $data['term_synonym']['table']['group'] = t('Taxonomy');
+
+ $data['term_synonym']['table']['join'] = array(
+ 'term_data' => array(
+ // links directly to term_data via tid
+ 'left_field' => 'tid',
+ 'field' => 'tid',
+ ),
+ 'node' => array(
+ // links directly to node via nid
+ 'left_field' => 'nid',
+ 'field' => 'nid',
+ ),
+ 'node_revisions' => array(
+ // links directly to node_revisions via vid
+ 'left_field' => 'vid',
+ 'field' => 'vid',
+ ),
+ 'users' => array(
+ // Links to users via node.nid
+ 'left_table' => 'node',
+ 'left_field' => 'nid',
+ 'field' => 'nid',
+ ),
+ );
+
+ $data['term_synonym']['name'] = array(
+ 'title' => t('Term synonym'),
+ 'help' => t('Term synonyms may be used to find terms by alternate names'),
+// 'argument' => array(
+// 'handler' => 'views_handler_argument_string', // @todo this should be own argument probably
+// ),
+ );
+ return $data;
+}
+
+class views_handler_field_term_node_tid extends views_handler_field_prerender_list {
+ function init(&$view, $options) {
+ parent::init($view, $options);
+ if ($view->base_table == 'node_revisions') {
+ $this->additional_fields['nid'] = array('table' => 'node_revisions', 'field' => 'vid');
+ }
+ else {
+ $this->additional_fields['nid'] = array('table' => 'node', 'field' => 'nid');
+ }
+ }
+
+ /**
+ * Provide meaningful defaults
+ */
+ function options(&$options) {
+ parent::options($options);
+ $options['link_to_taxonomy'] = TRUE;
+ $options['limit'] = FALSE;
+ $options['vids'] = array();
+ }
+
+ /**
+ * Provide "link to term" option.
+ */
+ function options_form(&$form, &$form_state) {
+ parent::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']),
+ );
+
+ $form['limit'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Limit terms by vocabulary'),
+ '#default_value'=> $this->options['limit'],
+ );
+
+ $options = array();
+ $vocabularies = taxonomy_get_vocabularies();
+ foreach ($vocabularies as $voc) {
+ $options[$voc->vid] = $voc->name;
+ }
+
+ $form['vids'] = array(
+ '#prefix' => '<div><div id="edit-options-vids">',
+ '#suffix' => '</div></div>',
+ '#type' => 'checkboxes',
+ '#title' => t('Vocabularies'),
+ '#options' => $options,
+ '#default_value' => $this->options['vids'],
+ '#process' => array('expand_checkboxes', 'views_process_dependency'),
+ '#dependency' => array('edit-options-limit' => array(TRUE)),
+ );
+ }
+
+ /**
+ * Add this term to the query
+ */
+ function query() {
+ $this->add_additional_fields();
+ }
+
+ function pre_render($results) {
+ $this->field_alias = $this->aliases['nid'];
+ $nids = array();
+ foreach ($results as $result) {
+ $nids[] = $result->{$this->aliases['nid']};
+ }
+
+ if ($nids) {
+ $vids = '';
+ if (!empty($this->options['limit']) && !empty($this->options['vids'])) {
+ $vids = " AND td.vid IN (" . implode(', ', array_keys(array_filter($this->options['vids']))) . ")";
+ }
+
+ $result = db_query("SELECT tn.nid, td.* FROM {term_data} td INNER JOIN {term_node} tn ON td.tid = tn.tid WHERE tn.nid IN (" . implode(', ', $nids) . ")$vids ORDER BY td.weight, td.name");
+
+ while ($term = db_fetch_object($result)) {
+ if (empty($this->options['link_to_taxonomy'])) {
+ $this->items[$term->nid][$term->tid] = check_plain($term->name);
+ }
+ else {
+ $this->items[$term->nid][$term->tid] = l($term->name, taxonomy_term_path($term));
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Field handler to provide simple renderer that allows linking to a taxonomy
+ * term.
+ *
+ * @ingroup views_field_handlers
+ */
+class views_handler_field_taxonomy extends views_handler_field {
+ /**
+ * Constructor to provide additional field to add.
+ *
+ * This constructer assumes the term_data table. If using another
+ * table, we'll need to be more specific.
+ */
+ function construct() {
+ parent::construct();
+ $this->additional_fields['vid'] = 'vid';
+ $this->additional_fields['tid'] = 'tid';
+ }
+
+ /**
+ * Provide link to taxonomy option
+ */
+ function options_form(&$form, &$form_state) {
+ parent::options_form($form, $form_state);
+ $form['link_to_taxonomy'] = array(
+ '#title' => t('Link this field to its taxonomy term page'),
+ '#type' => 'checkbox',
+ '#default_value' => !empty($this->options['link_to_taxonomy']),
+ );
+ }
+
+ /**
+ * Render whatever the data is as a link to the taxonomy.
+ *
+ * Data should be made XSS safe prior to calling this function.
+ */
+ function render_link($data, $values) {
+ if (!empty($this->options['link_to_taxonomy']) && !empty($values->{$this->aliases['tid']})) {
+ $term = new stdClass();
+ $term->tid = $values->{$this->aliases['tid']};
+ $term->vid = $values->{$this->aliases['vid']};
+
+ return l($data, taxonomy_term_path($term), array('html' => TRUE));
+ }
+ else {
+ return $data;
+ }
+ }
+
+ function render($values) {
+ return $this->render_link(check_plain($values->{$this->field_alias}), $values);
+ }
+}
+
+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);
+ }
+}
+
+/**
+ * Filter by vocabulary id
+ *
+ * @ingroup views_filter_handlers
+ */
+class views_handler_filter_vocabulary_vid extends views_handler_filter_in_operator {
+ function get_value_options() {
+ if (isset($this->value_options)) {
+ return;
+ }
+
+ $this->value_options = array();
+ $vocabularies = taxonomy_get_vocabularies();
+ foreach ($vocabularies as $voc) {
+ $this->value_options[$voc->vid] = $voc->name;
+ }
+ }
+}
+
+/**
+ * Argument handler to accept a user id.
+ *
+ * @ingroup views_argument_handlers
+ */
+class views_handler_argument_vocabulary_vid extends views_handler_argument {
+ /**
+ * Override the behavior of title(). Get the name of the user.
+ */
+ function title() {
+ $title = db_result(db_query("SELECT v.name FROM {vocabulary} v WHERE v.vid = %d", $this->argument));
+
+ if (empty($title)) {
+ return t('No vocabulary');
+ }
+
+ return check_plain($title);
+ }
+}
+
+/**
+ * Filter by term id
+ *
+ * @ingroup views_filter_handlers
+ */
+class views_handler_filter_term_node_tid extends views_handler_filter_many_to_one {
+ function has_extra_options() { return TRUE; }
+
+ function get_value_options() { /* don't overwrite the value options */ }
+
+ function options(&$options) {
+ parent::options($options);
+ $options['type'] = 'textfield';
+ $options['vid'] = db_result(db_query('SELECT MIN(vid) FROM {vocabulary} v'));
+ }
+
+ function extra_options_form(&$form, &$form_state) {
+ $vocabularies = taxonomy_get_vocabularies();
+ foreach ($vocabularies as $voc) {
+ $options[$voc->vid] = $voc->name;
+ }
+
+ $form['vid'] = array(
+ '#prefix' => '<div class="views-left-40">',
+ '#suffix' => '</div>',
+ '#type' => 'radios',
+ '#title' => t('Vocabulary'),
+ '#options' => $options,
+ '#description' => t('Select which vocabulary to show terms for in the regular options'),
+ '#default_value' => $this->options['vid'],
+ );
+
+ $form['type'] = array(
+ '#prefix' => '<div class="views-left-40">',
+ '#suffix' => '</div>',
+ '#type' => 'radios',
+ '#title' => t('Selection type'),
+ '#options' => array('select' => t('Dropdown'), 'textfield' => t('Autocomplete')),
+ '#default_value' => $this->options['type'],
+ );
+
+ }
+
+ function value_form(&$form, &$form_state) {
+ $vocabulary = taxonomy_vocabulary_load($this->options['vid']);
+ if (!$vocabulary) {
+ $form['markup'] = array(
+ '#prefix' => '<div class="form-item">',
+ '#suffix' => '</div>',
+ '#value' => t('An invalid vocabulary is selected. Please change it in the options.'),
+ );
+ return;
+ }
+
+ if ($this->options['type'] == 'textfield') {
+ $default = '';
+ if ($this->value) {
+ $result = db_query("SELECT * FROM {term_data} td WHERE td.tid IN (" . implode(', ', $this->value));
+ while ($term = db_fetch_object($result)) {
+ if ($value) {
+ $value .= ', ';
+ }
+ $value .= $term->name;
+ }
+ }
+
+ $form['value'] = array(
+ '#title' => t('Select terms from vocabulary @voc', array('@voc' => $vocabulary->name)),
+ '#type' => 'textfield',
+ '#autocomplete_path' => 'taxonomy/autocomplete/' . $vocabulary->vid,
+ '#default_value' => $default,
+ );
+ }
+ else {
+ $form['value'] = _taxonomy_term_select(
+ t('Select terms from vocabulary @voc', array('@voc' => $vocabulary->name)),
+ 'value',
+ $this->value,
+ $vocabulary->vid,
+ '',
+ TRUE,
+ NULL
+ );
+ unset($form['value']['#weight']);
+ }
+ }
+
+ function value_validate($form, &$form_state) {
+ if ($this->options['type'] == 'textfield') {
+ $values = drupal_explode_tags($form_state['values']['options']['value']);
+ $tids = array();
+ $placeholders = array();
+ $args = array();
+ $results = array();
+ foreach ($values as $value) {
+ if (strtolower($value) == 'anonymous') {
+ $tids[] = 0;
+ }
+ else {
+ $missing[strtolower($value)] = TRUE;
+ $args[] = $value;
+ $placeholders[] = "'%s'";
+ }
+ }
+
+ $result = db_query("SELECT * FROM {term_data} WHERE name IN (" . implode(', ', $placeholders) . ")", $args);
+ while ($term = db_fetch_object($result)) {
+ unset($missing[strtolower($term->name)]);
+ $tids[] = $term->tid;
+ }
+
+ if ($missing) {
+ form_error($form['value'], t('Unable to find term(s): @terms', array('@terms', implode(', ', $missing))));
+ }
+
+ $form_state['values']['options']['value'] = $tids;
+ }
+ }
+
+ function value_submit($form, &$form_state) {
+ // prevent array_filter from messing up our arrays in parent submit.
+ }
+
+ function admin_summary() {
+ // set up $this->value_options for the parent summary
+ $this->value_options = array();
+
+ if ($this->value) {
+ $result = db_query("SELECT * FROM {term_data} td WHERE td.tid IN (" . implode(', ', $this->value) . ")");
+
+ while ($term = db_fetch_object($result)) {
+ $this->value_options[$term->tid] = $term->name;
+ }
+ }
+ return parent::admin_summary();
+ }
+
+ /**
+ * Override ensure_my_table so we can control how this joins in.
+ * The operator actually has influence over joining.
+ */
+ function ensure_my_table() {
+ if (!isset($this->table_alias)) {
+ $base_join = views_get_table_join($this->table, $this->query->primary_table);
+ if ($this->operator == 'or') {
+ // For this stuff, we just do a single join, simple join:
+ return views_handler_field::ensure_my_table();
+ }
+ else {
+ // base handling for everything else is ok:
+ return parent::ensure_my_table();
+ }
+ }
+ return $this->table_alias;
+ }
+
+ function query() {
+ if ($this->value && $this->operator == 'or') {
+ $this->ensure_my_table();
+ $this->operator = 'in';
+ views_handler_filter_in_operator::query();
+ }
+ else {
+ return parent::query();
+ }
+ }
+}
+
+/**
+ * @}
+ */
diff --git a/modules/user.views.inc b/modules/user.views.inc
index 024a7a3..f6fd78c 100644
--- a/modules/user.views.inc
+++ b/modules/user.views.inc
@@ -22,7 +22,7 @@ function user_views_data() {
$data['users']['table']['base'] = array(
'field' => 'uid',
'title' => t('User'),
- 'help' => t('Allows views of your site\'s users.'),
+ 'help' => t('Users who have created accounts on your site.'),
);
// @todo: restructure this back to normal.
@@ -88,6 +88,7 @@ function user_views_data() {
// Information for accepting a uid as an argument
'argument' => array(
'handler' => 'views_handler_argument_user_uid',
+ 'name field' => 'name', // display this field in the summary
),
// Information for accepting a uid as a filter
'filter' => array(
@@ -471,8 +472,7 @@ class views_handler_field_user_roles extends views_handler_field_prerender_list
function pre_render($results) {
$uids = array();
- $roles = array();
- $this->roles = array();
+ $this->items = array();
foreach ($results as $result) {
$uids[] = $result->{$this->aliases['uid']};
@@ -603,8 +603,7 @@ class views_handler_filter_user_name extends views_handler_filter_in_operator {
* @ingroup views_filter_handlers
*/
class views_handler_filter_user_roles extends views_handler_filter_many_to_one {
- function construct() {
- parent::construct();
+ function get_value_options() {
$this->value_options = user_roles(TRUE);
unset($this->value_options[DRUPAL_AUTHENTICATED_RID]);
}
diff --git a/views_ui.module b/views_ui.module
index 1b1f7ac..9a05ff1 100644
--- a/views_ui.module
+++ b/views_ui.module
@@ -137,6 +137,10 @@ function views_ui_menu() {
'page callback' => 'views_ui_config_item',
'page arguments' => array(3, 5),
);
+ $items['admin/build/views/%views_ui_js/config-item-extra/%views_ui_cache'] = $callback + array(
+ 'page callback' => 'views_ui_config_item_extra',
+ 'page arguments' => array(3, 5),
+ );
// display specific parameters
$items['admin/build/views/%views_ui_js/display/%views_ui_cache'] = $callback + array(
'page callback' => 'views_ui_edit_display',