Commit 86ed07d8 authored by merlinofchaos's avatar merlinofchaos

Add basic support for summary styles; they don't quite work yet because view...

Add basic support for summary styles; they don't quite work yet because view URL knowledge isn't implemented.
parent 40b6f2f1
......@@ -14,8 +14,8 @@
*
* @code
* class views_join_complex extends views_join {
* // PHP 4 doesn't call constructors of the base class automatically from a
* // constructor of a derived class. It is your responsibility to propagate
* // PHP 4 doesn't call constructors of the base class automatically from a
* // constructor of a derived class. It is your responsibility to propagate
* // the call to constructors upstream where appropriate.
* function construct($left_table, $left_field, $field, $extra = array(), $type = 'LEFT') {
* parent::construct($left_table, $left_field, $field, $extra, $type);
......@@ -32,7 +32,7 @@
/**
* A function class to represent a join and create the SQL necessary
* to implement the join.
*
*
* This is the Delegation pattern. If we had PHP5 exclusively, we would
* declare this an interface.
*
......@@ -70,7 +70,7 @@ class views_join {
}
}
}
return $output;
return $output;
}
}
......@@ -79,7 +79,7 @@ class views_join {
*/
/**
* Base handler, from which all the other handlers are derived.
* Base handler, from which all the other handlers are derived.
* It creates a common interface to create consistency amongst
* handlers and data.
*
......@@ -87,18 +87,18 @@ class views_join {
* parent::views_handler() here.
*
* This class would be abstract in PHP5, but PHP4 doesn't understand that.
*
*
*/
class views_handler extends views_object {
/**
* Seed the handler with necessary data.
* init the handler with necessary data.
* @param $view
* The $view object this handler is attached to.
* @param $data
* The item from the database; the actual contents of this will vary
* based upon the type of handler.
*/
function seed(&$view, &$data) {
function init(&$view, &$data) {
$this->view = &$view;
$this->data = &$data;
......@@ -136,7 +136,7 @@ class views_handler extends views_object {
* Provide a form for setting options.
*/
function options_form(&$form) { }
/**
* Validate the options form.
*/
......@@ -377,7 +377,7 @@ class views_handler_filter extends views_handler {
* Provide a form for setting the operator.
*/
function operator_form(&$form) { }
/**
* Validate the operator form.
*/
......@@ -393,7 +393,7 @@ class views_handler_filter extends views_handler {
* Provide a form for setting options.
*/
function value_form(&$form) { }
/**
* Validate the options form.
*/
......@@ -423,7 +423,7 @@ class views_handler_filter extends views_handler {
* @{
*/
/**
* Base class for arguments.
* Base class for arguments.
*
* The basic argument works for very simple arguments such as nid and uid
*/
......@@ -444,14 +444,14 @@ class views_handler_argument extends views_handler {
* be a count on $view->primary_field
* - set_count_field: Reset the count field so we get the right paging.
*
* @return
* @return
* The alias used to get the number of records (count) for this entry.
*/
function summary_query() {
$this->ensure_my_table();
// Add the field.
$this->base_alias = $this->query->add_field($this->table_alias, $this->real_field);
$this->base_alias = $this->query->add_field($this->table_alias, $this->real_field);
// Add the 'name' field. For example, if this is a uid argument, the
// name field would be 'name' (i.e, the username).
if (isset($this->name_field)) {
......@@ -460,7 +460,7 @@ class views_handler_argument extends views_handler {
else {
$this->name_alias = $this->base_alias;
}
return $this->summary_basics();
}
......@@ -477,13 +477,13 @@ class views_handler_argument extends views_handler {
$this->query->set_count_field($this->table_alias, $this->real_field);
}
return $count_alias;
$this->count_alias = $count_alias;
}
/**
* Sorts the summary based upon the user's selection. The base variant of
* this is usually adequte.
*
*
* @param $order
* The order selected in the UI.
*/
......@@ -502,7 +502,7 @@ class views_handler_argument extends views_handler {
*/
function summary_link($data, $url) {
$value = $data->{$this->base_alias};
return l($data->{$this->name_alias}, "$url/$value");
return url("$url/$value");
}
/**
......@@ -551,11 +551,22 @@ class views_handler_argument extends views_handler {
$this->view->build_info['summary'] = TRUE;
$this->view->build_info['summary_level'] = $this->data->position;
// Change the display style to the summary style for this
// argument.
$this->view->style_plugin = isset($this->options['style_plugin']) ? $this->options['style_plugin'] : 'default_summary';
// Give it the style's options, too.
// @todo
// Clear out the normal primary field and whatever else may have
// been added and let the summary do the work.
$this->query->clear_fields();
$this->summary_query();
// Allow the new style to add additional fields if it wants.
// @todo
// Cut 'summary' out of our action to see how, if at all, we should
// sort.
$order = trim(str_replace($action, 'summary', ''));
......@@ -564,9 +575,10 @@ class views_handler_argument extends views_handler {
}
// DISTINCT can cause the summaries to fail.
// TODO: This may not be true anymore.
// @todo: This may not be true anymore.
// $this->query->no_distinct = TRUE;
// Summaries have their own sorting and fields, so tell the View not
// to build these.
$this->view->build_sort = $this->view->build_fields = FALSE;
......@@ -621,9 +633,9 @@ class views_handler_argument_formula extends views_handler_argument {
$this->ensure_my_table();
$field_alias = $alias . '_' . $this->field;
// Add the field.
$this->base_alias = $this->query->add_field(NULL, $this->formula, $field_alias);
$this->base_alias = $this->query->add_field(NULL, $this->formula, $field_alias);
$this->query->set_count_field(NULL, $this->formula, $field_alias);
return $this->summary_basics(FALSE);
}
......@@ -634,7 +646,7 @@ class views_handler_argument_formula extends views_handler_argument {
$this->ensure_my_table();
$field_alias = $alias . '_' . $this->field;
// Add the field.
$this->name_alias = $this->query->add_field(NULL, $this->formula, $field_alias);
$this->name_alias = $this->query->add_field(NULL, $this->formula, $field_alias);
$this->query->add_where(0, "$field = '%s'", $this->argument);
}
}
......
<?php
<?php
// $Id$
/**
* @file plugins.inc
......@@ -6,7 +6,7 @@
*
*/
/**
/**
* Implementation of hook_views_plugins
*/
function views_views_plugins() {
......@@ -36,7 +36,7 @@ function views_views_plugins() {
'title' => t('Default'),
'help' => t('Displays rows one after another.'),
'handler' => 'views_style_plugin_default',
'theme' => 'views_view_rows',
'theme' => 'views_view_summary',
),
'list' => array(
'title' => t('List'),
......@@ -50,6 +50,13 @@ function views_views_plugins() {
'handler' => 'views_style_plugin_table',
'theme' => 'views_view_table',
),
'default_summary' => array(
'summary' => TRUE, // only shows up as a summary style
'title' => t('Default'),
'help' => t('Displays the default summary view'),
'handler' => 'views_style_plugin_summary',
'theme' => 'views_view_summary',
),
),
'row' => array(
'fields' => array(
......@@ -58,11 +65,28 @@ function views_views_plugins() {
'handler' => 'views_row_plugin',
'theme' => 'views_view_row',
),
'fields_summary' => array(
'title' => t('Summary'),
'help' => t('Displays the link to the argument and the node count.'),
'handler' => 'views_row_plugin_summary',
'theme' => 'views_view_row_summary',
),
),
);
}
/**
* @defgroup views_display_plugins Views' display plugins
* @{
* Display plugins control how Views interact with the rest of Drupal.
*
* They can handle creating Views from a Drupal page hook; they can
* handle creating Views from a Drupal block hook. They can also
* handle creating Views from an external module source, such as
* a Panels pane, or an insert view, or a CCK field type.
*/
/**
* The default display plugin handler. Display plugins handle options and
* basic mechanisms for different output methods.
......@@ -77,10 +101,8 @@ class views_display_plugin extends views_object {
/**
* Fill this plugin in with the view, display, etc.
*
* @todo LG: This function needs to be renamed to something that sounds less like a randomizer.
*/
function seed(&$view, &$display) {
function init(&$view, &$display) {
$this->view = $view;
$this->display = $display;
}
......@@ -97,7 +119,7 @@ class views_display_plugin extends views_object {
return;
}
if (empty($this->display_options[$option . '_default'])) {
return;
return;
}
if (isset($this->default_display->display_options[$option])) {
return $this->default_display->display_options[$option];
......@@ -108,7 +130,7 @@ class views_display_plugin extends views_object {
* Provide the default form for setting options.
*/
function options_form(&$form) { }
/**
* Validate the options form.
*/
......@@ -132,12 +154,12 @@ class views_display_plugin extends views_object {
/**
* Not all display plugins will have a feed icon.
*/
*/
function render_feed_icon() { }
/**
* Render the view's title for display
* TODO: Necessary? Hm.
* @todo: Necessary? Hm.
*/
function render_title() { }
......@@ -174,8 +196,6 @@ class views_display_plugin extends views_object {
* Render this display.
*/
function render() {
// TODO: Remove this when the 'file' tag on theme registry is fixed.
// include_once drupal_get_path('module', 'views') . '/theme/theme.inc';
$themes = array(
'views_view__' . $this->display->id . '__' . $this->view->name,
'views_view__' . $this->display->id,
......@@ -193,7 +213,7 @@ class views_display_plugin extends views_object {
* @todo Implement this.
*/
function access($account) { return TRUE; }
/**
/**
* When used externally, this is how a view gets run and returns
* data in the format required.
*/
......@@ -216,7 +236,7 @@ class views_display_plugin_page extends views_display_plugin {
// tab version needs to come later. Maybe it should be its own plugin.
$items[$url] = array(
// default views page entry
'page callback' => 'views_page',
'page callback' => 'views_page',
'page arguments' => array($this->view->name, $this->display->id),
// Default access check (per display)
'access callback' => 'views_access',
......@@ -276,6 +296,22 @@ class views_display_plugin_block extends views_display_plugin {
}
}
/**
* @}
*/
/**
* @defgroup views_style_plugins Views' style plugins
* @{
* Style plugins control how a view is rendered. For example, they
* can choose to display a collection of fields, node_view() output,
* table output, or any kind of crazy output they want.
*
* Many style plugins can have an optional 'row' plugin, that displays
* a single record. Not all style plugins can utilize this, so it is
* up to the plugin to set this up and call through to the row plugin.
*/
/**
* Base class to define a style plugin handler.
*/
......@@ -283,7 +319,7 @@ class views_style_plugin extends views_object {
var $needs_fields = FALSE;
var $needs_headers = FALSE;
function seed(&$view, &$display) {
function init(&$view, &$display) {
$this->view = $view;
$this->display = $display;
$this->options = $display->style_options;
......@@ -293,7 +329,7 @@ class views_style_plugin extends views_object {
* Provide a form for setting options.
*/
function options_form(&$form) { }
/**
* Validate the options form.
*/
......@@ -308,6 +344,10 @@ class views_style_plugin extends views_object {
function render($rows) { }
}
/**
* Default style plugin to render rows one after another with no
* decorations.
*/
class views_style_plugin_default extends views_style_plugin {
// TEMP HACK
var $row_plugin = 'views_row_plugin';
......@@ -319,18 +359,59 @@ class views_style_plugin_default extends views_style_plugin {
* Render the given style.
*/
function render() {
// TODO: This needs to be able to support either a database resource OR
// @todo: This needs to be able to support either a database resource OR
// an array, because our input format doesn't actually have to be from
// a query.
$plugin = new views_row_plugin;
$plugin = new $this->row_plugin;
$rows = '';
while ($row = db_fetch_object($this->view->result)) {
// @todo: Include separator as an option.
$rows .= $plugin->render($this->view, $row);
}
return theme(array('views_view_rows__' . $this->view->name, 'views_view_rows'), $this->view, $rows);
}
}
/**
* The default style plugin for summaries.
*/
class views_style_plugin_summary extends views_style_plugin {
// TEMP HACK
var $row_plugin = 'views_row_plugin_summary';
function options_form(&$form) {
// provide an option form to select from our list of node renderers
}
/**
* Render the given style.
*/
function render() {
// @todo: This needs to be able to support either a database resource OR
// an array, because our input format doesn't actually have to be from
// a query.
$plugin = new $this->row_plugin;
$rows = array();
while ($row = db_fetch_object($this->view->result)) {
// @todo: Include separator as an option.
$rows[] = $plugin->render($this->view, $row);
}
return theme(array('views_view_summary__' . $this->view->name, 'views_view_summary'), $this->view, $rows);
}
}
/**
* @}
*/
/**
* @defgroup views_row_plugins Views' row plugins
* @{
*
* Row plugins control how Views outputs an individual record. They are
* tightly coupled to style plugins, in that a style plugin is what calls
* the row plugin.
*/
/**
* Default plugin to view a single row of a table. This is really just a wrapper around
* a theme function.
......@@ -340,3 +421,17 @@ class views_row_plugin extends views_object {
return theme(array('views_view_row__' . $view->name, 'views_view_row'), $view, $row);
}
}
/**
* Default plugin to view a single row of a table. This is really just a wrapper around
* a theme function.
*/
class views_row_plugin_summary extends views_object {
function render(&$view, $row) {
return theme(array('views_view_row_summary__' . $view->name, 'views_view_row_summary'), $view, $row);
}
}
/**
* @}
*/
......@@ -67,7 +67,7 @@ class views_query {
$this->primary_field = $primary_field;
$this->relationships[$primary_table] = array('link' => NULL, 'table' => $primary_table, 'alias' => $primary_table);
// Seed the table queue with our primary table.
// init the table queue with our primary table.
$this->table_queue[$primary_table] = array(
'alias' => $primary_table,
'table' => $primary_table,
......@@ -75,7 +75,7 @@ class views_query {
'join' => NULL,
);
// Seed the tables with our primary table
// init the tables with our primary table
$this->tables[$primary_table][$primary_table] = array(
'count' => 1,
'alias' => $primary_table,
......@@ -117,7 +117,7 @@ class views_query {
$alias = $table . '_' . $field;
}
$this->count_field = array(
'table' => $table,
'table' => $table,
'field' => $field,
'alias' => $alias,
'count' => TRUE,
......@@ -166,7 +166,7 @@ class views_query {
else if (!array_key_exists($link_point, $this->relationships)) {
return FALSE;
}
$join = $this->adjust_join($join, $link_point);
if ($alias = $this->add_table($join->table, $link_point, $join, $alias)) {
$this->relationships[$alias] = array('link' => $link_point, 'table' => $join->table);
......@@ -197,7 +197,7 @@ class views_query {
* will specify how this table joins if it is not the default.
* @param $alias
* A specific alias to use, rather than the default alias.
*
*
* @return $alias
* The alias of the table; this alias can be used to access information
* about the table and should always be used to refer to the table when
......@@ -232,7 +232,7 @@ class views_query {
* will specify how this table joins if it is not the default.
* @param $alias
* A specific alias to use, rather than the default alias.
*
*
* @return $alias
* The alias of the table; this alias can be used to access information
* about the table and should always be used to refer to the table when
......@@ -289,7 +289,7 @@ class views_query {
}
$this->table_queue[$alias] = array(
'table' => $table,
'table' => $table,
'num' => $this->tables[$relationship][$table]['count'],
'alias' => $alias,
'join' => $join,
......@@ -361,7 +361,7 @@ class views_query {
// Does a table along this path exist?
if (isset($this->tables[$relationship][$table]) ||
$join->left_table == $relationship ||
$join->left_table == $relationship ||
$join->left_table == $this->relationships[$relationship]['table']) {
// Make sure that we're linking to the correct table for our relationship.
foreach (array_reverse($add) as $table => $join) {
......@@ -396,12 +396,12 @@ class views_query {
if ($relationship != $this->primary_table) {
// If we're linking to the primary table, the relationship to use will
// be the prior relationship. Unless it's a direct link.
// Safety! Don't modify an original here.
$join = drupal_clone($join);
// First, if this is our link point/anchor table, just use the relationship
if ($join->left_table == $this->relationships[$relationship]['table']) {
if ($join->left_table == $this->relationships[$relationship]['table']) {
$join->left_table = $relationship;
}
// then, try the base alias.
......@@ -437,7 +437,7 @@ class views_query {
}
/**
* Get the information associated with a table.
* Get the information associated with a table.
*
* If you need the alias of a table with a particular relationship, use
* ensure_table().
......@@ -565,7 +565,7 @@ class views_query {
$args = current($args);
}
// Ensure all variants of 0 are actually 0. Thus '', 0 and NULL are all
// Ensure all variants of 0 are actually 0. Thus '', 0 and NULL are all
// the default group.
if (empty($group)) {
$group = 0;
......@@ -668,7 +668,7 @@ class views_query {
// If it's not a count query, add our fields
$fields_array = $get_count ? array($this->count_field) : $this->fields;
foreach ($fields_array as $field) {
if ($fields) { // TODO: LG: This would be cleaner as an array that gets imploded.
if ($fields) { // @todo: LG: This would be cleaner as an array that gets imploded.
$fields .= ",\n ";
}
$string = '';
......
This diff is collapsed.
......@@ -41,7 +41,7 @@ function node_views_data() {
'arguments' => array(TRUE),
);
// nid
// nid
$data['node']['nid'] = array(
'title' => t('Nid'),
'help' => t('The node ID of the node'), // The help that appears on the UI,
......@@ -90,10 +90,10 @@ function node_views_data() {
*/
class views_handler_field_node extends views_handler_field {
/**
* Override seed function to provide generic option to link to node.
* Override init function to provide generic option to link to node.
*/
function seed(&$view, &$data) {
parent::seed($view, $data);
function init(&$view, &$data) {
parent::init($view, $data);
if (isset($data->options['link_to_node']) && $view->base_table != 'node') {
$this->additional_fields[] = $nid;
$this->nid_field = 'node_nid';
......
......@@ -50,7 +50,6 @@ function template_preprocess_views_view_row(&$vars) {
// CSS classes should be.
$vars['fields'][$field->handler->field_alias] = views_css_safe($field->handler->field_alias);
}
// Collect all of the fields in the record, then display them in the template.
}
/**
......@@ -63,3 +62,17 @@ function template_preprocess_views_view_row(&$vars) {
function theme_views_view_field($view, $field, $row) {
return $field->handler->render($row);
}
/**
* Preprocess theme function to print a single record from a row, with fields
*/
function template_preprocess_views_view_row_summary(&$vars) {
$view = $vars['view'];
$row = $vars['row'];
$argument = $view->argument[$view->build_info['summary_level']]->handler;
$vars['link'] = check_plain($row->{$argument->name_alias});
$vars['url'] = $argument->summary_link($row, $view->get_url());
$vars['count'] = intval($row->{$argument->count_alias});
}
<?php
// $Id$
/**
* @file views-view-row.tpl.php
* Default simple view template to display a list of rows.
*/
?>
<a href="<?php print $url; ?>"><?php print $link; ?></a> (<?php print $count?>)
<?php
// $Id$
/**
* @file views-view-rows.tpl.php
* Default simple view template to display a list of summary lines
*/
?>
<div class="item-list">
<ul>
<?php foreach ($rows as $row): ?>
<li><?php print $row?></li>
<?php endforeach; ?>
</ul>
</div>
......@@ -83,7 +83,7 @@ function views_menu() {
}
/**
* Helper function for menu loading. This will automatically be
* Helper function for menu loading. This will automatically be
* called in order to 'load' a views argument; primarily it
* will be used to perform validation.
*
......@@ -93,11 +93,11 @@ function views_menu() {
* The name of the view. This needs to be specified in the 'load function'
* of the menu entry.
* @param $index
* The menu argument index. This counts from 1.
* The menu argument index. This counts from 1.
*/
function views_arg_load($value, $name, $index) {
if ($view = views_get_view($name)) {
$view->seed_handlers();
$view->init_handlers();
if (isset($view->argument[$index - 1])) {
return $view->argument[$index - 1]->handler->validate($value);
}
......@@ -239,9 +239,9 @@ function views_include_default_views() {
// Default views hooks may be in the normal handler file,
// or in a separate views_default file at the discretion of
// the module author.
// the module author.
views_include_handlers();
// Now include the views_default files specifically.
$views_path = drupal_get_path('module', 'views') . '/modules';
foreach (module_list() as $module) {
......@@ -265,7 +265,7 @@ function views_fetch_data($table = NULL) {
$start = microtime();
// NOTE: This happens whether we retrieve them from cache or otherwise.
views_include_handlers();
// @todo: We can probably cache the views_data longer than just the current page run.
$cache = module_invoke_all('views_data');
if (module_exists('devel')) {
......@@ -347,7 +347,7 @@ function views_get_handler($table, $field, $key) {
/**
* Builds and return a list of all plugins available in the system.
*
* @return Nested array of plugins, grouped by type and
* @return Nested array of plugins, grouped by type and
*/
function views_discover_plugins() {
$cache = array('display' => array(), 'style' => array(), 'row' => array());
......@@ -460,7 +460,7 @@ class views_object {
* Get a view from the database or from default views.
*
* This function is just a static wrapper around views::load().
*
*
* @todo LG: Shouldn't this be called views_load() to parallel node_load() et al?
* @param $name
* The name of the view.
......@@ -477,8 +477,8 @@ function &views_get_view($name, $reset = FALSE) {
/**
* Get a view from the default views defined by modules.
*
* Default views are cached per-language. This function will rescan the
*
* Default views are cached per-language. This function will rescan the
* default_views hook if necessary.
*
* @param $view_name
......@@ -488,27 +488,27 @@ function &views_get_view($name, $reset = FALSE) {
function &views_get_default_view($view_name) {
static $cache = array();
global $language;
// We need to ensure that the view class is defined before we de-serialize the
// We need to ensure that the view class is defined before we de-serialize the
// cached view(s), or else it gets cast to a stdClass object.
views_include('view');
if (empty($cache[$view_name])) {
// Try to get the view (for this language) from the cache.
// Try to get the view (for this language) from the cache.
$view = views_cache_get('views_default_views:'. $view_name, TRUE);
// If we found the view in the cache, just use that. If not, try to find it from
// module hooks.
if ($view) {
$cache[$view_name] = $view->data;
}
else {
// We may as well rebuild the cache while we're at it, since we need to pull all
// We may as well rebuild the cache while we're at it, since we need to pull all
// of the data anyway. We pick out the one we want along the way.
$cache = discover_default_views();
}
}
return $cache[$view_name];
}
......@@ -520,7 +520,7 @@ function &views_get_default_view($view_name) {
function views_discover_default_views() {
global $language;
static $cache = array();
if (empty($cache)) {
views_include_default_views();
$defaults = module_invoke_all('views_default_views');
......@@ -536,9 +536,9 @@ function views_discover_default_views() {