Commit 582713d9 authored by merlinofchaos's avatar merlinofchaos

Very early checking for Views 2 for Drupal 6. Currently query.inc looks good...

Very early checking for Views 2 for Drupal 6. Currently query.inc looks good and view.inc can at least load and save views, though the schema needs more tweaks.
parent e4127444
CHANGELOG for Views for Drupal 5
CHANGELOG for Views for Drupal 6
Views 1.0
o Initial release under drupal.org's new release system
Views 2.0-dev
o Complete rewrite begun
Views 5.x-1.1-beta-1
Bugs fixed:
o 97228: Fatal error on the views help page.
o View Import was completely not working.
o 93873: Exposed filters were completely not working.
o 92305: Removed broken and unworkable 'distinct' profile filter.
o 93540: Don't use block title if no page title.
o 93493: Allow field labels to be turned off if item not sortable.
o 91665: Order By pretty much borked in PGSQL.
o 85290: Views generated invalid CSS with -- this could have an impact on
your theming!
o 90482: Validate that nodes per page is not 0 if pager is on.
o 89893: Multiple filters not showing up properly in RSS links
o 97462: More robust view export code.
o 82634: theme_imagebutton renamed to theme_views_imagebutton
o 77859: update module weight to 10 in update.php -- RUN UPDATE.PHP!!
o 97589: Add some sorting on plugins so that Views' default plugins are
always on top.
New features:
o New comment fields to allow more Views use of comments. [Egon Bianchet]
o Recent comments block default view.
o Add simple 'word search' to text field operators [gordonh]
o Early views_search.inc -- needs testing! [gordonh]
o 90643: Access-checking 'edit', 'delete' and 'view' links as fields
o Added uninstall function (accessible from the module administration page)
o 88849: new views_pre_query hook
o 97290: new $offset argument to views_build_view to allow views to to
skip the first N nodes [doesn't work if $ pager = true].
o 97290: New options for granularity on date sorts
o Provide a proper 'action' for exposed filters so they always go to the
view, not just the current page.
o 76601: New 'all files' field to display all files on a node as a single
field
Views 5.x-1.2-beta-1
Bugs fixed:
o 100394: Fix to t() call in 'new comments'.
o 100164: alias prefixing fix.
o 100109: Incorrect caching of 'is new' filter.
o 99849: DISTINCT could break summary views.
o 99783: Comment count didn't take into account pages. Also moved handler
out of node where it didn't belong.
o Use drupal_add_feed() for RSS icons so they can be themed.
o 99323: fix link in argument handling help
o Temporary fix for cache not being loaded for menu item creation
o 100317: exported view gets improperly formed value fields on filters
o 98441: Fixed 'optional' setting on exposed filters.
o 100997: Clarified use of $arg in help text
o 100769: Getting book parents didn't require parents to be current
o 98492: Recent comments block needed to filter out moderated comments
New features:
o 99225: CSS generator for views theme wizard
o 88067: theme_view much more useful now.
o 98492: Comment moderation status filter
o 101025: Sort by node type
Views 5.x-1.3-beta-1
Bugs fixed:
o Reverted 99783 which doesn't work.
o 100769: link book table via vid instead of nid.
o 101306: views_new_table() used incorrect right_field
o 99225: theme wizard wasn't CSS safing classes in an ironic fashion.
o 101363: Made the DISTINCT more forceful by adding a GROUP BY.
o 101167: Proper use of drupal_add_feed
o 'node' arguments weren't properly using node in the title.
o 102142: Default table sorting broken if field with no label comes after
field to sort on.
o 88343: $arg in urls (foo/$arg/bar) had locale problems.
o 97497: rss feed did not call module_invoke_all('exit') as it should.
o 89332: Don't default tables to MyISAM type
o 83478: Properly encode block titles & block descriptions.
New features:
o 101324: New op for views_build_view: 'queries'
o 77526: Automatically enable views_ui if views is installed without it. But not
just when the module is enabled.
Views 5.x-1.4-rc1
Bugs fixed:
o All the date-based arguments were broken due to changes in $query->add_orderby
o 103475: updated rss feed to match fixes in Drupal core.
o 103773: Fixed some obnoxious t() % placeholder <em> stupidity.
o Replaced theme_views_nodate with theme('views_nodate') which is actually themable.
o 103115: Validation for individual views fields/etc was never called.
o 101275: Prevent node.nid from being added as a field twice (was happening when sorting)
o 102746: * was being used instead of actual wildcard in feed URLs.
o 102457: Spurious warnings when displayed node has no terms
New Features:
o 89421: New last changed sort / filter / field
o 103649: allow customizing date interval granularity
Views 5.x-1.4-rc1
Bugs fixed:
o 109456: Match API documentation on 'field' definition on fields.
o 104459: Correct theme wizard field names.
o 104854: Fixed $arg at the beginning of the URL *again*
o 107855: Removed double check_plain in RSS feed titles.
o 107723: Removed use of IDs on table fields -- this might require your CSS files to be adjusted!
o 107713: Popular recent and popular alltime are now disabled by default.
o 106460: Update of module weight was not run on install of 1.4, causing taxonomy/term view to not override Drupal default.
o 107974: Ensure file_revisions table is added to query when using 'node has files' filter.
o 107371: Correct spelling of 'weather' to 'whether'.
o 107218: 107217: Fixed some E_NOTICE errors.
o 106464: Taxonomy links showed up as Array | Array | Array rather than the taxonomy terms.
o 110212: Text patch to clarify date fields.
o 110299: Change nodes per block max size from 2 chars wide to 3, as it was meant to be.
o 110648: Block title not showing up in admin if view only provides block.
o 110462: set_distinct didn't properly check to see if the query was already distinct.
o Distinct filter could mess up summary queries by making them distinct on nid which isn't what is supposed to happen there.
New features:
o 107471: Spiffy new theme wizard features. Thanks Crell!!
o 105081: Save and edit button to save but not go change screens.
Views --dev
// $Id$
OVERVIEW
The views module provides a flexible method for Drupal administrators to control
how lists of content are presented. Traditionally, Drupal has hard-coded most of
this, particularly in how taxonomy and tracker lists are formatted.
This tool is essentially a sort-of smart query builder that, given enough
information, can build the proper query, execute it, and display the results. It
has four modes, plus a special mode, and provides an impressive amount of
functionality from these modes.
INSTALLING VIEWS
In 4.7, Views can be installed simply by activating the module, thanks to the
new module installation features.
Please note that this is now TWO modules -- views.module and views_ui.module
DOCUMENTATION
Documentation is now available at http://drupal.org/handbook/modules/views.
The documentation files in the views package have been removed since they
are even more out of date.
As of 3/16/2006, the user documentation is UP TO DATE. The API documentation
is somewhat out of date, and the theming documentation is very out of date.
I hope to correct this in the very near future.
DOCUMENTATION
The best documentation will be here:
http://drupal.org/handbook/modules/views
-------------- IMPORTANT --------------------------------------------------
-------------- IMPORTANT --------------------------------------------------
If you update Views or any module that uses Views, you MUST MUST MUST
go and resubmit the admin/modules page. Views caches information provided
by modules, and this information MUST be re-cached whenever an update
is performed.
DRUPAL CANNOT TELL AUTOMATICALLY IF YOU HAVE UPDATED CODE. Therefore you
must go and submit this page.
Hopefully in 4.8 this won't be an issue.
-------------- UPDATING VIEWS ---------------------------------------------
If you're updating from 4.6 to 4.7+, this is important:
Views Will Not Update Properly.
I'm sorry, but there is no upgrade path from 4.6 to 4.7. In order to
achieve this result, you need to first completely unstall Views. Before
you do this you may want to write down your view information.
Then uninstall views; there are instructions on the views module handbook
page on drupal.org -- http://drupal.org/handbook/modules/views.
Once you have it completely uninstalled, you may then install the new
Views for 4.7, via Drupal's automatic installer.
This is a rewrite of the Views module for Drupal 6. As of the above date,
it's still in the very early stages.
<?php
// $Id$
/**
* @file export.inc
* Provides an easy method to import and export a view as PHP code.
*/
This diff is collapsed.
<?php
// $Id$
/**
* @file view.inc
* Provides the view object type and associated methods.
*/
class view {
var $vid = 0;
var $name = '';
var $description = '';
var $display = array();
var $argument = array();
var $field = array();
var $sort = array();
var $filter = array();
var $base_table = 'node';
var $view_args_php = '';
// State variables
var $is_built = FALSE;
var $args = array();
var $query = NULL;
var $count_query = NULL;
function set_args($args) {
$this->args = $args;
}
function set_page_size($page_size) {
$this->page_size = $page_size;
}
function set_use_pager($use_pager) {
$this->use_pager = $use_pager;
}
function set_offset($offset) {
$this->offset = $offset;
}
function set_filter_input($filters) {
$this->filter_input = $filters;
}
function set_display($display_id) {
$this->display = $display_id;
}
function build($display_id = NULL) { }
function render() { }
function get_title($context) { }
function get_url() { }
function is_cacheable() { }
/**
* Load a view from the database based upon either vid or name.
*/
function load($arg) {
$where = (is_numeric($arg) ? "vid = %d" : "name = '%s'");
$data = db_fetch_object(db_query("SELECT * FROM {views_view} WHERE $where", $arg));
_views_unpack_schema($this, 'views_view', $data);
$this->_load_row('display');
$this->_load_row('argument');
$this->_load_row('field');
$this->_load_row('sort');
$this->_load_row('filter');
}
/**
* Load one of our sub tables.
*/
function _load_row($key) {
$object_name = "views_$key";
$table = $object_name . 's';
$result = db_query("SELECT * FROM {$table} WHERE vid = %d ORDER BY position", $this->vid);
while ($data = db_fetch_object($result)) {
$object = new $object_name;
_views_unpack_schema($object, $table, $data);
array_push($this->$key, $object);
}
}
/**
* Save the view to the database. If the view does not already exist,
* A vid will be assigned to the view and also returned from this function.
*/
function save() {
if (!empty($this->vid)) {
// remove existing table entries
db_query("DELETE from {views_displays} WHERE vid = %d", $this->vid);
db_query("DELETE from {views_arguments} WHERE vid = %d", $this->vid);
db_query("DELETE from {views_fields} WHERE vid = %d", $this->vid);
db_query("DELETE from {views_sorts} WHERE vid = %d", $this->vid);
db_query("DELETE from {views_filters} WHERE vid = %d", $this->vid);
}
_views_save_query('views_view', $this, !empty($this->vid) ? 'vid' : FALSE);
$this->_save_rows('display');
$this->_save_rows('argument');
$this->_save_rows('field');
$this->_save_rows('sort');
$this->_save_rows('filter');
cache_clear_all('views_urls', 'cache_views');
cache_clear_all(); // clear the page cache as well.
}
function _save_rows($key) {
foreach ($this->$key as $position => $object) {
$object->position = $position;
$object->vid = $this->vid;
_views_save_query("views_" . $key . "s", $object);
}
}
function delete() {
if (empty($view->vid)) {
return;
}
db_query("DELETE FROM {views_view} where vid = %d", $view->vid);
db_query("DELETE FROM {views_displays} where vid = %d", $view->vid);
db_query("DELETE FROM {views_arguments} where vid = %d", $view->vid);
db_query("DELETE FROM {views_fields} where vid = %d", $view->vid);
db_query("DELETE FROM {views_sorts} where vid = %d", $view->vid);
db_query("DELETE FROM {views_filters} where vid = %d", $view->vid);
cache_clear_all('views_query:' . $view->name, 'cache_views');
cache_clear_all(); // In Drupal 5.0 and later this clears the page cache only.
}
function export() {
require_once drupal_get_path('module', 'views') . '/includes/export.inc';
views_export_view($this);
}
}
class views_argument {
var $type = '';
var $default_action = '';
var $title = '';
var $wildcard = '';
var $wildcard_text = '';
var $summary_format;
var $options = array();
var $position = 0;
}
class views_field {
var $table = '';
var $field = '';
var $label = '';
var $handler = '';
var $position = 0;
// Options contains things like: Sortable, default sort, column, etc.
// Based upon the needs of the output type.
var $options = array();
}
class views_sort {
var $table = '';
var $field = '';
var $order = '';
var $options = array();
var $position = 0;
}
class views_filter {
var $table = '';
var $field = '';
var $group = '';
var $operator = '';
var $value = '';
var $options = '';
var $exposed = FALSE;
var $exposed_settings = array();
var $position = 0;
}
class views_display {
var $type = '';
var $output_type = '';
var $access = '';
var $title = '';
var $header = '';
var $header_format = '';
var $header_hide_if_empty = '';
var $footer = '';
var $footer_format = '';
var $footer_hide_if_empty = '';
var $empty = '';
var $empty_format = '';
var $use_pager = '';
var $page_size = '';
var $url = '';
var $display_options = array();
var $output_options = array();
var $position = 0;
var $filters_type = ''; // 'table', 'list'
var $filters_location = ''; // 'view', 'block'
}
// build an insert/update query based upon schema info.
function _views_save_query($table, &$object, $update = NULL) {
$schema = drupal_get_schema($table);
$fields = $defs = $values = $serials = array();
// Go through our schema and build correlations.
foreach ($schema['fields'] as $field => $info) {
if (!isset($object->$field)) {
if (isset($info['default'])) {
$object->$field = $info['default'];
}
else {
$object->$field = '';
}
}
// special case -- skip serial types if we are updating.
if ($info['type'] == 'serial' && $update) {
continue;
}
$fields[] = $field;
switch ($info['type']) {
case 'serial':
$defs[] = '%s';
$object->$field = 'NULL';
$serials[] = $field;
break;
case 'int':
$defs[] = '%d';
break;
case 'float':
case 'numeric':
$defs[] = '%f';
break;
default:
$defs[] = "'%s'";
}
if (empty($info['serialize'])) {
$values[] = $object->$field;
}
else {
$values[] = serialize($object->$field);
}
}
$query = '';
if (!$update) {
$query = "INSERT INTO {$table} (" . implode(', ', $fields) . ') VALUES (' . implode(', ', $defs) . ')';
}
else {
$query = '';
foreach ($fields as $id => $field) {
if ($query) {
$query .= ', ';
}
$query .= $field . ' = ' . $defs[$id];
}
$query = "UPDATE {$table} SET " . $query . " WHERE $update = " . $object->$update;
}
db_query($query, $values);
if ($serials) {
// get last insert ids and fill them in.
foreach ($serials as $field) {
$object->$field = db_last_insert_id($table, $field);
}
}
}
function _views_unpack_schema(&$object, $table, $data) {
$schema = drupal_get_schema($table);
// Go through our schema and build correlations.
foreach ($schema['fields'] as $field => $info) {
$object->$field = empty($info['serialize']) ? $data->$field : unserialize($data->$field);
}
}
; $Id$
name = Views
description = The views module creates customized views of node lists.
description = Create customized lists and queries from your database.
package = Views
core = 6.x
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
<?php
// $Id$
// Load all our module 'on behalfs'.
// Whenever we decide we need this, load our module 'on behalfs'.
$path = drupal_get_path('module', 'views') . '/modules';
$files = drupal_system_listing('views_.*\.inc$', $path, 'name', 0);
foreach($files as $file) {
// The filename format is very specific. It must be views_MODULENAME.inc
$module = substr_replace($file->name, '', 0, 6);
if (module_exists($module)) {
require_once("./$file->filename");
}
}
// ---------------------------------------------------------------------------
// Acquire Views Data
/**
* Return the arguments array; construct one if we haven't already. The
* array is cached in a global, safely named variable so that arguments
* are only constructed once per run.
*/
function _views_get_arguments($titles = false) {
static $views_arguments;
global $locale;
if (!$views_arguments) {
$data = cache_get("views_arguments:$locale", 'cache');
$cache = unserialize($data->data);
if (is_array($cache)) {
$views_arguments = $cache;
}
else {
$arguments = module_invoke_all('views_arguments');
uasort($arguments, '_views_sort_arrays');
foreach ($arguments as $name => $arg) {
if ($arg['option'] && !is_array($arg['option'])) {
if ($arg['option'] == 'string' || $arg['option'] == 'integer') {
$arg['option'] = array('#type' => 'textfield', '#size' => 10, '#maxlength' => 255);
}
else {
$arg['option'] = array('#type' => 'select', '#options' => $arg['option']);
}
}
$views_arguments['base'][$name] = $arg['name'];
$views_arguments['title'][$name] = $arg;
}
$cache = $views_arguments;
cache_set("views_arguments:$locale", 'cache', serialize($cache));
}
}
return ($titles ? $views_arguments['base'] : $views_arguments['title']);
}
/**
* Constructs the full table information array. Caches it into a global array
* so that it will only be called once per run.
*/
function _views_get_tables($full = false) {
static $views_tables;
global $locale;
if (!$views_tables) {
$data = cache_get("views_tables:$locale", 'cache');
$cache = unserialize($data->data);
if (is_array($cache)) {
$views_tables = $cache;
}
else {
$table_data = module_invoke_all('views_tables');
$views_tables['tables'] = $table_data;
foreach ($table_data as $name => $table) {
if (is_array($table['filters'])) {
foreach ($table['filters'] as $filter => $data) {
$data['table'] = $name;
// translate for deprecated APIs...
if ($data['option'] && !is_array($data['option'])) {
if ($data['option'] == 'string' || $data['option'] == 'integer') {
$data['option'] = array('#type' => 'textfield', '#size' => 10, '#maxlength' => 255);
}
else {
$data['option'] = array('#type' => 'select', '#options' => $data['option']);
}
}
if ($data['list']) {
$data['value'] = array('#type' => 'select', '#options' => $data['list']);
if ($data['list-type'] != 'select') {
$data['value']['#multiple'] = TRUE;
}
}
else if (!$data['value']) {
$data['value'] = array('#type' => 'textfield', '#size' => 10, '#maxlength' => 255);
}
$views_tables['filters']['titles']["$name.$filter"] = $data['name'];
$views_tables['filters']['base']["$name.$filter"] = $data;
}
}
if (is_array($table['fields'])) {
foreach ($table['fields'] as $field => $data) {
if ($data['option'] && !is_array($data['option'])) {
if ($data['option'] == 'string' || $data['option'] == 'integer') {
$data['option'] = array('#type' => 'textfield', '#size' => 10, '#maxlength' => 255);
}
else {
$data['option'] = array('#type' => 'select', '#options' => $data['option']);
}
}
$data['table'] = $name;
$views_tables['fields']['titles']["$name.$field"] = $data['name'];
$views_tables['fields']['base']["$name.$field"] = $data;
}
}
if (is_array($table['sorts'])) {
foreach ($table['sorts'] as $field => $data) {
$data['table'] = $name;
if ($data['option'] && !is_array($data['option'])) {
if ($data['option'] == 'string' || $data['option'] == 'integer') {
$data['option'] = array('#type' => 'textfield', '#size' => 10, '#maxlength' => 255);
}
else {
$data['option'] = array('#type' => 'select', '#options' => $data['option']);
}
}
$views_tables['sorts']['titles']["$name.$field"] = $data['name'];
$views_tables['sorts']['base']["$name.$field"] = $data;
}
}
}
cache_set("views_tables:$locale", 'cache', serialize($views_tables));
}
}
return ($full ? $views_tables : $views_tables['tables']);
}
/**
* Gets the filter information; if it doesn't exist, call the function
* that constructs all that.
*/
function _views_get_filters($titles = false) {
$table_data = _views_get_tables(true);
return ($titles ? $table_data['filters']['titles'] : $table_data['filters']['base']);
}
/**
* Gets the field information; if it doesn't exist, call the function
* that constructs all that.
*/
function _views_get_fields($titles = false) {
$table_data = _views_get_tables(true);
return ($titles ? $table_data['fields']['titles'] : $table_data['fields']['base']);
}
/**
* Gets the sort information; if it doesn't exist, call the function
* that constructs all that.
*/
function _views_get_sorts($titles = false) {
$table_data = _views_get_tables(true);
return ($titles ? $table_data['sorts']['titles'] : $table_data['sorts']['base']);
}
/**
* Ensures that views have legitimate information; a bit more is stored on
* the $view object than is in the database, and this isn't necessarily
* set when a view is constructed externally.
*/
function views_sanitize_view(&$view) {
_views_check_arrays($view); // so reference works.
foreach ($view->field as $i => $field) {
if (!isset($view->field[$i]['id'])) {
$view->field[$i]['id'] = $view->field[$i]['fullname'] = "$field[tablename].$field[field]";
$view->field[$i]['queryname'] = "$field[tablename]_$field[field]";
}
}
foreach ($view->filter as $i => $filter) {
if (!isset($view->filter[$i]['id'])) {
$view->filter[$i]['id'] = $view->filter[$i]['field'] = "$filter[tablename].$filter[field]";
}
}
foreach ($view->exposed_filter as $i => $exposed_filter) {
if (!isset($view->exposed_filter[$i]['id'])) {
$view->exposed_filter[$i]['id'] = $view->exposed_filter[$i]['field'] = "$exposed_filter[tablename].$exposed_filter[field]";
}
}
foreach ($view->sort as $i => $sort) {
if (!isset($view->sort[$i]['id'])) {
$view->sort[$i]['id'] = $view->sort[$i]['field'] = "$sort[tablename].$sort[field]";
}
}
foreach ($view->argument as $i => $argument) {
if (!isset($view->argument[$i]['id'])) {
$view->argument[$i]['id'] = $view->argument[$i]['type'];
}
}
}
/**
* Build default view information from all modules and cache it.
*/
function _views_get_default_views() {
static $views_default_views;
global $locale;
if (!$views_default_views) {