Commit 40b6f2f1 authored by merlinofchaos's avatar merlinofchaos

#188640 (by Crell): Add default views, and lots of comments, many of which...

#188640 (by Crell): Add default views, and lots of comments, many of which need to be dealt with one way or another.
parent c16f0e22
......@@ -77,8 +77,10 @@ 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 seed(&$view, &$display) {
$this->view = $view;
$this->display = $display;
}
......@@ -100,7 +102,7 @@ class views_display_plugin extends views_object {
if (isset($this->default_display->display_options[$option])) {
return $this->default_display->display_options[$option];
}
}
}
/**
* Provide the default form for setting options.
......@@ -188,7 +190,7 @@ class views_display_plugin extends views_object {
/**
* Determine if the user has access to this display of the view.
*
* TODO: Implement this.
* @todo Implement this.
*/
function access($account) { return TRUE; }
/**
......@@ -281,7 +283,7 @@ class views_style_plugin extends views_object {
var $needs_fields = FALSE;
var $needs_headers = FALSE;
function seed(&$view, $display) {
function seed(&$view, &$display) {
$this->view = $view;
$this->display = $display;
$this->options = $display->style_options;
......
......@@ -60,10 +60,10 @@ class views_query {
var $distinct = FALSE;
/**
* Create the basic query object and fill with default values.
* Constructor; Create the basic query object and fill with default values.
*/
function views_query($primary_table = 'node', $primary_field = 'nid') {
$this->primary_table = $primary_table;
$this->primary_table = $primary_table; // Predefine these above, for clarity.
$this->primary_field = $primary_field;
$this->relationships[$primary_table] = array('link' => NULL, 'table' => $primary_table, 'alias' => $primary_table);
......@@ -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) {
if ($fields) { // TODO: LG: This would be cleaner as an array that gets imploded.
$fields .= ",\n ";
}
$string = '';
......
......@@ -45,15 +45,18 @@ class view extends views_db_object {
}
/**
* Returns an array of objects in a view.
* Returns a list of the sub-object types used by this view.
*/
function objects() {
return array('argument', 'field', 'sort', 'filter', 'relationship');
}
/**
* Returns the complete list of objects in a view, including the display which
* is often special.
* 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.
*/
function objects_all() {
return array('display', 'argument', 'field', 'sort', 'filter', 'relationship');
......@@ -69,6 +72,8 @@ 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) {
$this->page_size = $page_size;
......@@ -118,6 +123,8 @@ class view extends views_db_object {
/**
* 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) {
// The default display is always the first one in the list.
......@@ -230,7 +237,7 @@ class view extends views_db_object {
$argument_title = '';
// build arguments.
foreach ($this->argument as $id => $arg) {
unset ($argument);
unset ($argument); // TODO: LG: Is this necessary, or is this because of the non-bug with reference reassignment?
$argument = &$this->argument[$id];
if (!is_object($argument->handler)) {
......@@ -366,7 +373,7 @@ class view extends views_db_object {
// TODO: Implement this
// Make sure the query has already executed.
if (empty($this->executed)) {
if (empty($this->executed)) { // TODO: Remove this, since ->execute() is already doing it for us.
$this->execute($display_id);
}
......@@ -399,7 +406,7 @@ class view extends views_db_object {
*/
function execute_hook_menu($display_id = NULL) {
// Prepare the view with the information we have.
$this->set_display($display_id);
$this->set_display($display_id); // Wasn't this just done already in the menu hook in views_get_page_views()?
// Execute the view
if (isset($this->display_handler)) {
......@@ -443,27 +450,55 @@ class view extends views_db_object {
/**
* Load a view from the database based upon either vid or name.
*/
function load($arg) {
// TODO: Move caching to here, make this a factory method.
$where = (is_numeric($arg) ? "vid = %d" : "name = '%s'");
$data = db_fetch_object(db_query("SELECT * FROM {views_view} WHERE $where", $arg));
if (empty($data)) {
return FALSE;
*
* This is a static factory method that implements internal caching for
* view objects.
*
* @param $arg
* The name of the view or its internal view id (vid)
* @param $reset
* If TRUE, reset this entry in the load cache.
* @return A view object or NULL if it was not available.
*/
function &load($arg, $reset = FALSE) {
static $cache = array();
// We want a NULL value to return TRUE here, so we can't use isset() or empty().
if (!array_key_exists($arg, $cache) || $reset) {
$where = (is_numeric($arg) ? "vid = %d" : "name = '%s'");
$data = db_fetch_object(db_query("SELECT * FROM {views_view} WHERE $where", $arg));
if (empty($data)) {
$cache[$arg] = NULL;
}
else {
$view =& new view();
$view->load_row($data);
// Load all of our subtables.
foreach ($view->objects_all() as $key) {
$view->_load_sub_row($key);
}
$view->loaded = TRUE;
$cache[$arg] = $view;
}
}
$this->load_row($data);
// Load all of our subtables.
foreach ($this->objects_all() as $key) {
$this->_load_row($key);
// If the view is not defined in the database, check the default_views hook.
if (is_null($cache[$arg]) && !is_numeric($arg)) {
$cache[$arg] = views_get_default_view($arg);
}
$this->loaded = TRUE;
return TRUE;
return $cache[$arg];
}
/**
* Static factory method to load a list of views based upon a $where clause.
*
* Although this method could be implemented to simply iterate over views::load(),
* that would be very slow. Buiding the views externally from unified queries is
* much faster.
*
* @todo FROM LG: We should document why this is passing in literal query fragments
* since it's bound to confuse someone else as much as it did/does me. :-)
*/
function load_views($where, $join = '') {
// TODO: Integrate this in with caching.
......@@ -487,7 +522,7 @@ class view extends views_db_object {
// Now load all the subtables:
foreach (view::objects_all() as $key) {
$object_name = "views_$key";
$result = db_query("SELECT * FROM {$object_name} WHERE vid IN ($vids) ORDER BY vid, position");
$result = db_query("SELECT * FROM {{$object_name}} WHERE vid IN ($vids) ORDER BY vid, position");
while ($data = db_fetch_object($result)) {
$object = new $object_name(FALSE);
......@@ -501,14 +536,14 @@ class view extends views_db_object {
/**
* Load one of our sub tables.
*/
function _load_row($key) {
function _load_sub_row($key) {
$object_name = "views_$key";
$result = db_query("SELECT * FROM {$object_name} WHERE vid = %d ORDER BY position", $this->vid);
while ($data = db_fetch_object($result)) {
$object = new $object_name(FALSE);
$object->load_row($data);
array_push($this->$key, $object);
array_push($this->$key, $object); // TODO: Why is this array_push instead of just []?
}
}
......@@ -521,7 +556,7 @@ class view extends views_db_object {
// remove existing table entries
foreach ($this->objects_all() as $key) {
db_query("DELETE from {views_" . $key . "} WHERE vid = %d", $this->vid);
$this->_load_row($key);
$this->_load_sub_row($key);
}
}
......@@ -560,7 +595,7 @@ class view extends views_db_object {
// Delete from all of our subtables as well.
foreach ($this->objects_all() as $key) {
db_query("DELETE from {views_" . $key . "} WHERE vid = %d", $this->vid);
$this->_load_row($key);
$this->_load_sub_row($key);
}
cache_clear_all('views_query:' . $this->name, 'cache_views');
......@@ -693,6 +728,10 @@ class views_db_object {
/**
* Load the object with a row from the database.
*
* This method is separate from the constructor in order to give us
* more flexibility in terms of how the view object is built in different
* contexts.
*
* @param $data
* An object from db_fetch_object. It should contain all of the fields
* that are in the schema.
......@@ -722,6 +761,7 @@ class views_db_object {
/**
* Export a loaded row to PHP code.
*
* @todo LG: I don't understand what a "row" is in this context.
* @param $identifier
* The variable to assign the PHP code for this object to.
* @param $indent
......@@ -765,6 +805,7 @@ class views_argument extends views_db_object {
var $db_table = 'views_argument';
function views_argument($init = TRUE) {
parent::init($init);
$this->default_argument = 'ignore';
}
}
......
......@@ -227,6 +227,35 @@ function views_include_handlers() {
$finished = TRUE;
}
/**
* Load default views files on behalf of modules.
*/
function views_include_default_views() {
static $finished = FALSE;
// Ensure this only gets run once.
if ($finished) {
return;
}
// Default views hooks may be in the normal handler file,
// or in a separate views_default file at the discretion of
// 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) {
$module_path = drupal_get_path('module', $module);
if (file_exists("$module_path/$module.views_default.inc")) {
include_once "$module_path/$module.views_default.inc";
}
else if (file_exists("$views_path/$module.views_default.inc")) {
include_once "$views_path/$module.views_default.inc";
}
}
$finished = TRUE;
}
/**
* Fetch Views' data from the cache
*/
......@@ -236,6 +265,8 @@ 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')) {
dsm('Views data build time: ' . (microtime() - $start) * 1000 . ' ms');
......@@ -313,6 +344,11 @@ function views_get_handler($table, $field, $key) {
dsm("$table $field $key");
}
/**
* Builds and return a list of all plugins available in the system.
*
* @return Nested array of plugins, grouped by type and
*/
function views_discover_plugins() {
$cache = array('display' => array(), 'style' => array(), 'row' => array());
// Get plugins from all mdoules.
......@@ -423,6 +459,9 @@ 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.
* @param $reset
......@@ -432,18 +471,125 @@ class views_object {
* a fresh one.
*/
function &views_get_view($name, $reset = FALSE) {
views_include('view');
return view::load($name, $reset);
}
/**
* Get a view from the default views defined by modules.
*
* Default views are cached per-language. This function will rescan the
* default_views hook if necessary.
*
* @param $view_name
* The name of the view to load.
* @return A view object or NULL if it is not available.
*/
function &views_get_default_view($view_name) {
static $cache = array();
if (!array_key_exists($name, $cache)) {
// Ensure we at least have a NULL.
$cache[$name] = NULL;
views_include('view');
$view = new view;
if ($view->load($name)) {
global $language;
// 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.
$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
// of the data anyway. We pick out the one we want along the way.
$cache = discover_default_views();
}
}
return $cache[$view_name];
}
/**
* Scan all modules for default views and rebuild the default views cache.
*
* @return An associative array of all known default views.
*/
function views_discover_default_views() {
global $language;
static $cache = array();
if (empty($cache)) {
views_include_default_views();
$defaults = module_invoke_all('views_default_views');
foreach ($defaults as $name => $view) {
if ($should_cache) {
views_cache_set('views_default_views:'. $name, $view, TRUE);
}
$cache[$name] = $view;
}
// TODO: check for default views in cache.
}
return $cache[$name];
return $cache;
}
/**
* Set a cached item in the views cache.
*
* This is just a convenience wrapper around cache_set().
*
* @param $cid
* The cache ID of the data to store.
* @param $data
* The data to store in the cache. Complex data types will be automatically serialized before insertion.
* Strings will be stored as plain text and not serialized.
* @param $use_language
* If TRUE, the data will be cached specific to the currently active language.
*/
function views_cache_set($cid, $data, $use_language = FALSE) {
global $language;
if (variable_get('views_skip_cache', FALSE)) {
return;
}
if ($use_language) {
$cid .= ':'. $language->language;
}
cache_set($cid, $data, 'cache_views');
}
/**
* Return data from the persistent views cache.
*
* This is just a convenience wrapper around cache_get().
*
* @param $cid
* The cache ID of the data to retrieve.
* @param $use_language
* If TRUE, the data will be requested specific to the currently active language.
*/
function views_cache_get($cid, $use_language = FALSE) {
global $language;
if (variable_get('views_skip_cache', FALSE)) {
return 0;
}
if ($use_language) {
$cid .= ':'. $language->language;
}
return cache_get($cid, 'cache_views');
}
/**
* Implementation of hook_devel_caches().
*
* When the devel cache is cleared, clear cached views, too. That
* makes development a bit easier.
*/
function views_devel_caches() {
return array('cache_views');
}
/**
......@@ -460,10 +606,20 @@ function &views_get_view($name, $reset = FALSE) {
* );
*/
function views_get_page_views() {
// First, get all applicable views.
// First, get all applicable views that are defined in the database.
views_include('view');
$views = view::load_views("d.url IS NOT NULL AND d.url <> ''", "INNER JOIN {views_display} d ON v.vid = d.vid");
// Now get all applicable views that are defined in a default_views hook.
foreach (views_discover_default_views() as $name => $view) {
foreach ($view->display as $display) {
if ($display->display_plugin == 'page') {
$views[$view->name] = &$view;
break;
}
}
}
$result = array();
foreach ($views as $view) {
foreach ($view->display as $display) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment