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 = '';
......
<?php
// $Id$
/**
/**
* @file view.inc
* Provides the view object type and associated methods.
*/
......@@ -23,7 +23,7 @@ class view extends views_db_object {
// State variables
var $built = FALSE;
var $executed = FALSE;
var $args = array();
var $build_info = array();
......@@ -52,9 +52,9 @@ class view extends views_db_object {
}
/**
* Returns the complete list of dependent objects in a view, including
* Returns the complete list of dependent objects in a view, including
* the display which is often special.
*
*
* @todo LG: special how? This needs to be doc'ed more.
* @todo Convert all references to this method to be static, not dynamic.
*/
......@@ -72,10 +72,10 @@ class view extends views_db_object {
/**
* Set the page size for ranged or pager queries
*
*
* @todo move all pager properties into a pager object
*/
function set_page_size($page_size) {
function set_page_size($page_size) {
$this->page_size = $page_size;
}
......@@ -97,7 +97,7 @@ class view extends views_db_object {
* How many records to skip. This does not function if use_pager is
* set.
*/
function set_offset($offset) {
function set_offset($offset) {
$this->offset = $offset;
}
......@@ -117,13 +117,13 @@ class view extends views_db_object {
$display_id = $this->current_display;
}
// TODO: Fix this:
// @todo: Fix this:
return $this->field;
}
/**
* Set the display for this view, and initialize the display handler.
*
*
* @todo Determine if this is meant to be called only once, and if so, document that.
*/
function set_display($display_id = NULL) {
......@@ -136,7 +136,7 @@ class view extends views_db_object {
if (!isset($display_id)) {
$this->current_display = 0;
}
foreach ($this->display as $id => $display) {
if ($display->id == $display_id) {
$this->current_display = $id;
......@@ -159,37 +159,43 @@ class view extends views_db_object {
return FALSE;
}
// Seed the new display handler with data.
$this->display_handler->seed($this, $display_data);
// init the new display handler with data.
$this->display_handler->init($this, $display_data);
// If this is NOT the default display handler, let it know which is
// since it may well utilize some data from the default.
if ($this->current_display != $this->default_display) {
$this->display_handler->default_display = $this->display[$this->default_display];
}
// Find and initialize the style plugin. Note that arguments may have changed
// which style plugin we use, so check the view object first, then ask
// the display handler.
return TRUE;
}
/**
* Find and initialize the style plugin.
*
* Note that arguments may have changed which style plugin we use, so
* check the view object first, then ask the display handler.
*/
function init_style() {
if (!isset($this->style_plugin)) {
$this->style_plugin = $display_data->style_plugin;
$this->style_plugin = $this->display[$this->current_display]->style_plugin;
}
dsm("Init_style: $this->style_plugin");
$this->style_handler = views_get_plugin('style', $this->style_plugin);
if (empty($this->style_handler)) {
return FALSE;
}
// Seed the new display handler with data.
$this->style_handler->seed($this, $display_data);
return TRUE;
// init the new display handler with data.
$this->style_handler->init($this, $this->display[$this->current_display]);
}
/**
* Build the query for the view.
*/
function build($display_id = NULL) {
function build($display_id = NULL) {
if (!empty($this->built)) {
return;
}
......@@ -207,9 +213,9 @@ class view extends views_db_object {
}
ob_end_clean();
}
// Attempt to load from cache.
// TODO: Load a build_info from cache.
// @todo: Load a build_info from cache.
......@@ -224,30 +230,32 @@ class view extends views_db_object {
// Call a module hook and see if it wants to present us with a
// pre-built query or instruct us not to build the query for
// some reason.
// TODO: Implement this.
// @todo: Implement this.
// Run through our handlers and ensure they have necessary information.
$this->seed_handlers();
$this->init_handlers();
// Build all the filters.
$this->_build('filter');
// Initially, we want to build sorts and fields. This can change, though,
// if we get a