diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 9db5a9fd0dc895f7c5fa72f3e0f91093f3e65052..a7b9f2e287cf92b81c38dbc98d5ca8acbcfaab19 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,125 +1,5 @@ -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 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 diff --git a/README.txt b/README.txt index 8e848f8450bf1ced391371462166fc598b53a7b0..c40b2e28c4fc10d34f4305807787ac1119d54666 100644 --- a/README.txt +++ b/README.txt @@ -1,61 +1,4 @@ // $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. diff --git a/go-bottom.png b/go-bottom.png deleted file mode 100644 index 741b6191fe7aa90d935d44be384913602734659a..0000000000000000000000000000000000000000 Binary files a/go-bottom.png and /dev/null differ diff --git a/go-down.png b/go-down.png deleted file mode 100644 index 30acf6863f2ed514ad7aefe7d923ad9c74342e8c..0000000000000000000000000000000000000000 Binary files a/go-down.png and /dev/null differ diff --git a/go-top.png b/go-top.png deleted file mode 100644 index e6f9532e120166efa448eaa722895ffa459f194b..0000000000000000000000000000000000000000 Binary files a/go-top.png and /dev/null differ diff --git a/go-up.png b/go-up.png deleted file mode 100644 index 17b374f91b2ab67d1549972674885beed2d9d8f9..0000000000000000000000000000000000000000 Binary files a/go-up.png and /dev/null differ diff --git a/includes/cache.inc b/includes/cache.inc new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/includes/export.inc b/includes/export.inc new file mode 100644 index 0000000000000000000000000000000000000000..deb3dca32c6822d6a8c0861af8fa30d23720bf67 --- /dev/null +++ b/includes/export.inc @@ -0,0 +1,6 @@ +primary_table = $primary_table; + $this->primary_field = $primary_field; + $this->relationships[$primary_table] = array('link' => NULL, 'table' => $primary_table); + + // Seed the table queue with our primary table. + $this->table_queue[$primary_table] = array( + 'alias' => $primary_table, + 'table' => $primary_table, + 'relationship' => $primary_table, + 'join' => NULL, + ); + + if ($primary_field) { + $this->fields[$primary_field] = array( + 'table' => $primary_table, + 'field' => $primary_field, + 'alias' => $primary_field, + ); + } + + $this->count_field = array( + 'table' => $primary_table, + 'field' => $primary_field, + 'alias' => $primary_field, + 'count' => TRUE, + ); + } + + // ---------------------------------------------------------------- + // Utility sets + + /* + * Set the base field to be distinct. + */ + function set_distinct($value = TRUE) { + if (!(isset($this->no_distinct) && $value)) { + $this->distinct = $value; + } + } + + /* + * Set what field the query will count() on for paging. + */ + function set_count_field($field) { + $this->count_field = $field; + } + + /* + * Set the table header; used for click-sorting because it's needed + * info to modify the ORDER BY clause. + */ + function set_header($header) { + $this->header = $header; + } + + // ---------------------------------------------------------------- + // Table/join adding + + /** + * A relationship is an alternative endpoint to a series of table + * joins. Relationships must be aliases of the primary table and + * they must join either to the primary table or to a pre-existing + * relationship. + * + * An example of a relationship would be a nodereference table. + * If you have a nodereference named 'book_parent' which links to a + * parent node, you could set up a relationship 'node_book_parent' + * to 'node'. Then, anything that links to 'node' can link to + * 'node_book_parent' instead, thus allowing all properties of + * both nodes to be available in the query. + * + * @param $alias + * What this relationship will be called, and is also the alias + * for the table. + * @param $table + * The real table in the relationship. This will be ensured to be in + * the path. + * @param $join + * A views_join object (or derived object) to join the alias in. + * @param $link_point + * If this relationship links to something other than the primary + * table, specify that table here. For example, a 'track' node + * might have a relationship to an 'album' node, which might + * have a relationship to an 'artist' node. + */ + function add_relationship($alias, $join, $link_point = NULL) { + if (empty($link_point)) { + $link_point = $this->primary_table; + } + 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); + return $alias; + } + } + + /* + * This function will add a table to the query. + * + * This function will test to ensure that the path back to the primary + * table is valid and exists; if you do not wish for this testing to + * occur, use $query->queue_table() instead. + * + * @param $table + * The name of the table to add. It needs to exist in the global table + * array. + * @param $relationship + * An alias of a table; if this is set, the path back to this table will + * be tested prior to adding the table, making sure that all intermediary + * tables exist and are properly aliased. If set to NULL the path to + * the primary table will be ensured. If the path cannot be made, the + * table will NOT be added. + * @param $join + * In some join configurations this table may actually join back through + * a different method; this is most likely to be used when tracing + * a hierarchy path. (node->parent->parent2->parent3). This parameter + * 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 + * adding parts to the query. Or FALSE if the table was not able to be + * added. + */ + function add_table($table, $relationship = NULL, $join = NULL, $alias = NULL) { + if (!$this->ensure_path($table, $relationship, $join)) { + return FALSE; + } + + return $this->queue_table($table, $relationship, $join, $alias); + } + + /* + * This function will add a table to the query. + * + * This function will test to ensure that the path back to the primary + * table is valid and exists; if you do not wish for this testing to + * occur, use $query->queue_table() instead. + * + * @param $table + * The name of the table to add. It needs to exist in the global table + * array. + * @param $relationship + * The primary table alias this table is related to. If not set, the + * primary table will be used. + * @param $join + * In some join configurations this table may actually join back through + * a different method; this is most likely to be used when tracing + * a hierarchy path. (node->parent->parent2->parent3). This parameter + * 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 + * adding parts to the query. Or FALSE if the table was not able to be + * added. + */ + function queue_table($table, $relationship = NULL, $join = NULL, $alias = NULL) { + // If the alias is set, make sure it doesn't already exist. + if (isset($this->table_queue[$alias])) { + return FALSE; + } + + if (empty($relationship)) { + $relationship = $this->primary_table; + } + + if (!array_key_exists($relationship, $this->relationships)) { + return FALSE; + } + + // Mark that this table has been added. + if (empty($this->tables[$relationship][$table])) { + if (!isset($alias)) { + $alias = ''; + if ($relationship != $this->primary_table) { + // double underscore will help prevent accidental name + // space collisions. + $alias = $relationship . '__'; + } + $alias .= $table; + } + $this->tables[$relationship][$table] = array( + 'count' => 1, + 'alias' => $alias, + ); + } + else { + $this->tables[$relationship][$table]['count']++; + } + + // If no alias is specified, give it the default. + if (!isset($alias)) { + $alias = $this->tables[$relationship][$table]['alias'] . $this->tables[$relationship][$table]['count']; + } + + // If no join is specified, pull it from the table data. + if (!isset($join)) { + $join = $this->get_join_data($table); + if (empty($join)) { + return FALSE; + } + + $join = $this->adjust_join($join, $relationship); + } + + $this->table_queue[$alias] = array( + 'table' => $table, + 'num' => $this->tables[$relationship][$table]['count'], + 'alias' => $alias, + 'join' => $join, + 'relationship' => $relationship, + ); + + return $alias; + } + + /* + * Ensure a table exists in the queue; if it already exists it won't + * do anything, but if it doesn't it will add the table queue. It will ensure + * a path leads back to the relationship table. + * + * @param $table + * The unaliased name of the table to ensure. + * @param $relationship + * The relationship to ensure the table links to. Each relationship will + * get a unique instance of the table being added. If not specified, + * will be the primary table. + * @param $join + * A views_join object (or derived object) to join the alias in. + * + * @return + * The alias used to refer to this specific table, or NULL if the table + * cannot be ensured. + */ + function ensure_table($table, $relationship = NULL, $join = NULL) { + if (empty($relationship)) { + $relationship = $this->primary_table; + } + + if (!array_key_exists($relationship, $this->relationships)) { + return FALSE; + } + + if (isset($this->tables[$relationship][$table]['alias'])) { + return $this->tables[$relationship][$table]['alias']; + } + + if (!empty($join)) { + $join = $this->adjust_join($join, $relationship); + } + + if ($this->ensure_path($table, $relationship, $join)) { + return $this->queue_table($table, $relationship, $join); + } + } + + /* + * Make sure that the specified table can be properly linked to the primary + * table in the JOINs. This function uses recursion. If the tables + * needed to complete the path back to the primary table are not in the + * query they will be added, but additional copies will NOT be added + * if the table is already there. + */ + function ensure_path($table, $relationship = NULL, $join = NULL, $traced = array(), $add = array()) { + if (!isset($relationship)) { + $relationship = $this->primary_table; + } + + if (!array_key_exists($relationship, $this->relationships)) { + return FALSE; + } + + if (!isset($join)) { + $join = $this->get_join_data($table); + } + + // Does it end at our link table? + if ($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) { + $this->queue_table($table, $relationship, $this->adjust_join($join, $relationship)); + } + return true; + } + + // Have we been this way? + if (isset($traced[$join->left_table])) { + // we looped. Broked. + return false; + } + + // Do we have to add this table? + $left_join = $this->get_join_data($join->left_table); + if (!isset($this->tables[$relationship][$join->left_table])) { + $add[$join->left_table] = $left_join; + } + + // Keep looking. + $traced[$join->left_table] = TRUE; + return $this->ensure_path($join->left_table, $relationship, $left_join, $traced, $add); + } + + /** + * Fix a join to adhere to the proper relationship; the left table can vary + * based upon what relationship items are joined in on. + */ + function adjust_join($join, $relationship) { + // Adjusts the left table for our relationship. + 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']) { + $join->left_table = $relationship; + } + // then, try the base alias. + else if (isset($this->tables[$relationship][$join->left_table]['alias'])) { + $join->left_table = $this->tables[$relationship][$join->left_table]['alias']; + } + // But if we're already looking at an alias, use that instead. + else if (isset($this->table_queue[$relationship]['alias'])) { + $join->left_table = $this->table_queue[$relationship]['alias']; + } + } + return $join; + } + + /** + * Retrieve join data from the larger join data cache. + * + * @return + * A keyed array containing the following information: + * - 'alias': The alias used to refer to the table in the query. + * - 'table': The real table in the query. + * - 'relationship': What relationship this join is part of. + * - 'join': The join object used to create the join. + */ + function get_join_data($table) { + // Check to see if we're linking to a known alias. If so, get the real + // table's data instead. + if (!empty($this->table_queue[$table])) { + $table = $this->table_queue[$table]['table']; + } + return views_get_table_join($table, $this->primary_table); + + } + + /** + * Get the information associated with a table. + * + * If you need the alias of a table with a particular relationship, use + * ensure_table(). + */ + function get_table_info($table) { + if (!empty($this->table_queue[$table])) { + return $this->table_queue[$table]; + } + } + + /* + * Add a field to the query table, possibly with an alias. This will + * automatically call ensure_table to make sure the required table + * exists, *unless* $table is unset. + * + * @param $table + * The table this field is attached to. If NULL, it is assumed this will + * be a formula; otherwise, ensure_table is used to make sure the + * table exists. + * @param $field + * The name of the field to add. This may be a real field or a formula. + * @param $alias + * The alias to create. If not specified, the alias will be $table_$field + * unless $table is NULL. When adding formulae, it is recommended that an + * alias be used. + * + * @return $name + * The name that this field can be referred to as. Usually this is the alias. + */ + function add_field($table, $field, $alias = '') { + + // We check for this specifically because we don't want to add it aliased. + if ($table == $this->primary_table && $field == $this->primary_field) { + return $this->primary_field; + } + + if ($table) { + $this->ensure_table($table); + } + + if (!$alias && $table) { + $alias = $table . '_' . $field; + } + + $name = $alias ? $alias : $field; + + if (empty($this->fields[$alias])) { + $this->fields[$name] = array( + 'field' => $field, + 'table' => $table, + 'alias' => $alias, + ); + } + return $name; + } + + /* + * Remove all fields that may've been added; primarily used for summary + * mode where we're changing the query because we didn't get data we needed. + */ + function clear_fields() { + $this->fields = array(); + } + + /** + * Create a new grouping for the WHERE clause. + * + * @param $type + * Either 'AND' or 'OR'. All items within this group will be added + * to the WHERE c + * @param $group + * An ID to use for this group. If unspecified, an ID will be generated. + * + * @return $group + * The group ID generated. + */ + function set_where_group($type = 'AND', $group = NULL) { + if (!isset($group)) { + $group = max(array_keys($this->where)) + 1; + } + + // Create an empty group + if (empty($this->where[$group])) { + $this->where[$group] = array('clauses' => array(), 'args' => array()); + } + + $this->where[$group]['type'] = strtoupper($type); + return $group; + } + + /** + * Control how all WHERE groups are put together. + * + * @param $type + * Either 'AND' or 'OR' + */ + function set_group_operator($type = 'AND') { + $this->group_operator = strtoupper($type); + } + + /* + * Add a simple WHERE clause to the query. The caller is responsible for + * ensuring that all fields are fully qualified (TABLE.FIELD) and that + * the table already exists in the query. + * + * @param $group + * The WHERE group to add these to; groups are used to create AND/OR + * sections. Groups cannot be nested. Use 0 as the default group. + * If the group does not yet exist it will be created as an AND group. + * @param $clause + * The actual clause to add. When adding a where clause it is important + * that all tables are addressed by the alias provided by add_table or + * ensure_table and that all fields are addressed by their alias wehn + * possible. Please use %d and %s for arguments. + * @param ... + * A number of arguments as used in db_query(). May be many args or one + * array full of args. + */ + function add_where($group, $clause) { + $args = func_get_args(); + array_shift($args); // ditch $group + array_shift($args); // ditch $clause + + // Expand an array of args if it came in. + if (count($args) == 1 && is_array(reset($args))) { + $args = current($args); + } + + // Check for a group. + if (!isset($this->where[$group])) { + $this->set_where_group('AND', $group); + } + + // Add the clause and the args. + if (is_array($args)) { + $this->where[$group]['clauses'][] = $clause; + $this->where[$group]['args'] = array_merge($this->where[$group]['args'], $args); + } + } + + /* + * Add multiple an orderby's. Right now I'm not sure why this function + * is separate from add_orderby above; I don't think it needs to + * be. + * + * @param $table + * The table this field is part of. If a formula, enter NULL. + * @param $field + * The field or formula to sort on. + * @param $order + * Either ASC or DESC. + * @param $alias + * The alias to add the field as. In SQL, all fields in the order by + * must also be in the SELECT portion. If an $alias isn't specified + * one will be generated for from the $field; however, if the + * $field is a formula, this alias will likely fail. + * + * @return $alias + * The alias created. + */ + function add_orderby($table, $field, $order, $alias = '') { + if ($table) { + $this->ensure_table($table); + } + + // Only fill out this aliasing if there is a table; + // otherwise we assume it is a formula. + if (!$alias && $table) { + $as = $table . '_' . $f; + } + else { + $as = $alias; + } + + $this->add_field($table, $field, $as); + $this->orderby[] = "$as $order"; + + // If grouping, all items in the order by must also be in the + // group by clause. + if ($this->groupby) { + $this->add_groupby($as); + } + } + + /* + * Add a simple GROUP BY clause to the query. The caller is responsible + * for ensuring that the fields are fully qualified and the table is properly + * added. + */ + function add_groupby($clause) { + $this->groupby[] = $clause; + } + + /* + * Generate a query and a countquery from all of the information supplied + * to the object. + * + * @param $get_count + * Provide a countquery if this is true, otherwise provide a normal query. + */ + function query($get_count = false) { + // Check query distinct value. + if (empty($this->no_distinct) && $this->distinct && !empty($this->fields)) { + $this->fields[$this->primary_field]['distinct'] = TRUE; + $this->count_field['distinct'] = TRUE; + } + + $joins = $fields = $where = $orderby = $groupby = ''; + // Add all the tables to the query via joins. We assume all LEFT joins. + foreach ($this->table_queue as $table) { + if (is_object($table['join'])) { + $joins .= $table['join']->join($table, $this) . "\n"; + } + } + + // If it's not a count query, add our fields + $fields_array = $get_count ? $this->count_field : $this->fields; + foreach ($fields_array as $field) { + if ($fields) { + $fields .= ', '; + } + $string = ''; + if ($field['table']) { + $string .= $field['table'] . '.'; + } + $string .= $field['field']; + if (isset($field['distinct'])) { + $string = "DISTINCT($string)"; + } + if (isset($field['count'])) { + $string = "COUNT($string)"; + } + if ($field['alias']) { + $string .= " AS $field[alias]"; + } + $fields .= $string; + } + + if (!$get_count) { + // we only add the groupby if we're not counting. + if ($this->groupby) { + $groupby = "GROUP BY " . implode(', ', $this->groupby) . "\n"; + } + + // ok, tablesort_sql is really, really (really) annoying. + // 1) it insists on adding the ORDER BY clause. + // 2) You're supposed to give it your stuff as $before, but + // 3) You have to add the comma and + // 4) if it doesn't have anything to add, it returns NOTHING. + // 5) So I'm just going to get what it sends back and chop off + // the orderby, cause otherwise my code is too ugly with + // various checks. + if ($this->header) { + $result = tablesort_sql($this->header); + if ($result) { + $this->orderby[] = str_replace('ORDER BY ', '', $result); + } + } + + if ($this->orderby) { + $orderby = "ORDER BY " . implode(', ', $this->orderby) . "\n"; + } + } + else { + $fields = "COUNT($this->count_field)"; + } + + $clauses = array(); + foreach ($this->where as $group => $info) { + $clauses[] = '(' . implode(") " . $info['type'] . " (", $info['clauses']) . ')'; + } + + if ($clauses) { + $where = 'WHERE (' . implode(")\n " . $this->group_operator . ' (', $clauses) . ')'; + } + + $query = "SELECT $fields\n FROM {" . $this->primary_table . "} $this->primary_table \n$joins $where $groupby $orderby"; + + $replace = array('>' => '>', '<' => '<'); + $query = strtr($query, $replace); + + return $query; + } + + /** + * Get the arguments attached to the WHERE clauses of this query. + */ + function get_where_args() { + $args = array(); + foreach ($this->where as $group => $where) { + $args = array_merge($args, $where['args']); + } + return $args; + } +} + +/** + * 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. + * + * Extensions of this class can be used to create more interesting joins. + */ +class views_join { + /** + * Construct the views_join object. + */ + function views_join($table, $left_table, $left_field, $field, $extra = array(), $type = 'LEFT') { + $this->table = $table; + $this->left_table = $left_table; + $this->left_field = $left_field; + $this->field = $field; + $this->extra = $extra; + $this->type = strtoupper($type); + } + + /** + * Build the SQL for the join this object represents. + */ + function join($table, &$query) { + $left = $query->get_table_info($this->left_table); + $output = " $this->type JOIN {" . $this->table . "} $table[alias] ON $left[alias].$this->left_field = $table[alias].$this->field"; + + // Tack on the extra. + if (isset($extra)) { + foreach ($extra as $field => $value) { + $output .= " AND $table[alias].$this->field"; + if (is_array($value) && !empty($value)) { + $output .= " IN ('". implode("','", $value) ."')"; + } + else if ($value !== NULL) { + $output .= " = '$value'"; + } + } + } + return $output; + } +} + +// Here is how you do complex joins: + +/* +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 + // the call to constructors upstream where appropriate. + function views_complex_join($left_table, $left_field, $field, $extra = array(), $type = 'LEFT') { + parent::views_join($left_table, $left_field, $field, $extra, $type); + } + + function join($table, &$query) { + $output = parent::join($table, $query); + } + $output .= "AND foo.bar = baz.boing"; + return $output; +} +*/ \ No newline at end of file diff --git a/includes/render.inc b/includes/render.inc new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/includes/view.inc b/includes/view.inc new file mode 100644 index 0000000000000000000000000000000000000000..d65e28a1215482ffec915fe7a479b59f83af5277 --- /dev/null +++ b/includes/view.inc @@ -0,0 +1,287 @@ +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); + } +} diff --git a/user-trash.png b/user-trash.png deleted file mode 100644 index 71e4c46265aaf28ac59b0aaaa8d90d450d1af25d..0000000000000000000000000000000000000000 Binary files a/user-trash.png and /dev/null differ diff --git a/views.info b/views.info index 57562d732255e2ffee36707d3b948b0ea41b103a..430c895bdced57dd7a0a261e53e201815b53d9e4 100644 --- a/views.info +++ b/views.info @@ -1,5 +1,5 @@ ; $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 diff --git a/views.install b/views.install index 34f13795fe42d424ffdc22a5f39cec90ed6eb470..7240aab7e6c0c22704130fd39b83cb0b7cd49d51 100644 --- a/views.install +++ b/views.install @@ -1,363 +1,16 @@ TRUE)); -// db_add_column($ret, 'view_view', 'block_use_page_empty', 'int(1)'); -// db_add_column($ret, 'view_view', 'block_empty', 'longtext'); -// db_add_column($ret, 'view_view', 'block_empty_format', 'int(4)', array('not null' => TRUE)); - switch($GLOBALS['db_type']) { - case 'mysql': - case 'mysqli': - $ret[] = update_sql("CREATE TABLE if not exists {view_exposed_filter} ( - vid int(10) unsigned NOT NULL default '0', - field varchar(255), - label varchar(255), - optional int(1), - is_default int(1), - operator int(1), - single int(1), - position int(2), - KEY (vid) - ) TYPE=MyISAM /*!40100 DEFAULT CHARACTER SET utf8 */;"); - break; - case 'pgsql': - $ret[] = update_sql("CREATE TABLE {view_exposed_filter} ( - vid numeric(10) unsigned NOT NULL default '0', - field varchar(255), - label varchar(255), - optional numeric(1), - is_default numeric(1), - operator numeric(1), - single numeric(1), - position numeric(2), - )"); - $ret[] = update_sql("CREATE INDEX {view_exposed_filter}_vid_idx ON {view_exposed_filter} (vid)"); - break; - } - return $ret; -} - -function views_update_4() { - $ret = array(); - db_add_column($ret, 'view_view', 'page_footer', 'longtext'); - db_add_column($ret, 'view_view', 'page_footer_format', 'int(4)', array('default' => 0)); - db_add_column($ret, 'view_view', 'block_use_page_footer', 'int(1)'); - db_add_column($ret, 'view_view', 'block_footer', 'longtext'); - db_add_column($ret, 'view_view', 'block_footer_format', 'int(4)', array('default' => 0)); - db_add_column($ret, 'view_view', 'page_empty', 'longtext'); - db_add_column($ret, 'view_view', 'page_empty_format', 'int(4)', array('default' => 0)); - db_add_column($ret, 'view_view', 'block_use_page_empty', 'int(1)'); - db_add_column($ret, 'view_view', 'block_empty', 'longtext'); - db_add_column($ret, 'view_view', 'block_empty_format', 'int(4)', array('default' => 0)); - return $ret; -} - -function views_update_5() { - $ret = array(); - db_add_column($ret, 'view_view', 'view_args_php', 'longtext'); - return $ret; -} - -function views_update_6() { - $ret = array(); - db_add_column($ret, 'view_tablefield', 'options', 'varchar(255)'); - return $ret; -} - -function views_update_7() { - $ret = array(); - $ret[] = update_sql("ALTER TABLE {view_argument} MODIFY type varchar(255)"); - return $ret; -} - -function views_update_8() { - $ret = array(); - $ret[] = update_sql("ALTER TABLE {view_view} MODIFY nodes_per_page int(5)"); - return $ret; -} - -function views_update_9() { - $ret = array(); - db_add_column($ret, 'view_argument', 'wildcard', 'varchar(32)'); - db_add_column($ret, 'view_argument', 'wildcard_substitution', 'varchar(32)'); - return $ret; -} - -function views_update_10() { - $ret = array(); - $ret[] = update_sql("UPDATE {system} SET weight = 10 WHERE name = 'views'"); - return $ret; + +function views_install() { + drupal_set_message('Installing views'); + drupal_install_schema('views'); + db_query("UPDATE {system} SET weight = 10 WHERE name = 'views'"); } -function views_update_11() { - // running this again because fresh installs of 1.4 didn't get it. - $ret = array(); - $ret[] = update_sql("UPDATE {system} SET weight = 10 WHERE name = 'views'"); - return $ret; +function views_uninstall() { + drupal_uninstall_schema('views'); } diff --git a/views.module b/views.module index f354a0a11d94348c40743a52e45db9b058bc6265..c9b22fede86fc3e6106375acffd36d0dcf1a3385 100644 --- a/views.module +++ b/views.module @@ -1,1873 +1,124 @@ url, '$arg') !== FALSE) { - continue; - } - - // unpack the array - $view->access = ($view->access ? explode(', ', $view->access) : array()); - - // This happens before the next check; even if it's put off for later - // it is still used. - $used[$view->name] = true; - - _views_create_menu_item($items, $view, $view->url); - } - $default_views = _views_get_default_views(); - $views_status = variable_get('views_defaults', array()); - - foreach ($default_views as $name => $view) { - if ($view->page && !$used[$name] && - ($views_status[$name] == 'enabled' || (!$view->disabled && $views_status[$name] != 'disabled'))) { - - if (strrpos($view->url, '$arg') !== FALSE) { - continue; - } - - _views_create_menu_item($items, $view, $view->url); - } - } - } - else { - $data = cache_get("views_with_inline_args:$locale", 'cache'); - if ($data == 0) { - // There's no cache for our language, regenerate it. - views_reset_inline_args_cache($locale); - $data = cache_get("views_with_inline_args:$locale"); - } - - $views = unserialize($data->data); - if (is_array($views)) { - foreach ($views as $view) { - // Do substitution on args. - $view_args = array(); - $menu_path = array(); - foreach (explode('/', $view->url) as $num => $element) { - if ($element == '$arg') { - $menu_path[] = arg($num); - $view_args[] = arg($num); - $view->args[] = arg($num); - } - else { - $menu_path[] = $element; - } - } - $path = implode('/', $menu_path); - _views_create_menu_item($items, $view, $path, MENU_CALLBACK, $view_args); - } - } - } - return $items; -} - -/** - * Reset the views with inline arguments cache for a locale. - */ -function views_reset_inline_args_cache($locale = 'en') { - $result = db_query("SELECT * FROM {view_view} WHERE page = 1"); - $views_with_inline_args = array(); - - while ($view = db_fetch_object($result)) { - // Skip over any non-argument views - if (strrpos($view->url, '$arg') === FALSE) { - continue; - } - // unpack the array - $view->access = ($view->access ? explode(', ', $view->access) : array()); - - // This happens before the next check; even if it's put off for later - // it is still used. - $used[$view->name] = true; - - - $arg_result = db_query("SELECT * FROM {view_argument} WHERE vid = %d", $view->vid); - while ($arg = db_fetch_array($arg_result)) { - $view->argument[] = $arg; - } - - $views_with_inline_args[$view->name] = $view; - } - - views_load_cache(); - $default_views = _views_get_default_views(); - $views_status = variable_get('views_defaults', array()); - - foreach ($default_views as $name => $view) { - if ($view->page && !$used[$name] && ($views_status[$name] == 'enabled' || (!$view->disabled && $views_status[$name] != 'disabled'))) { - if (strrpos($view->url, '$arg') !== FALSE) { - $views_with_inline_args[$view->name] = $view; - } - } - } - cache_set("views_with_inline_args:$locale", 'cache', serialize($views_with_inline_args)); -} - -/** - * Helper function to add a menu item for a view. - */ -function _views_create_menu_item(&$items, $view, $path, $local_task_type = MENU_NORMAL_ITEM, $args = array()) { - static $roles = NULL; - if ($roles == NULL) { - global $user; - $roles = array_keys($user->roles); - } - $title = views_get_title($view, 'menu'); - $type = _views_menu_type($view); - if ($type == MENU_LOCAL_TASK || $type == MENU_DEFAULT_LOCAL_TASK) { - $weight = $view->menu_tab_weight; - } - $access = !$view->access || array_intersect($view->access, $roles); - $items[] = _views_menu_item($path, $title, $view, $args, $access, $type, $weight); - - if ($type == MENU_DEFAULT_LOCAL_TASK) { - $items[] = _views_menu_item(dirname($path), $title, $view, $args, $access, $local_task_type, $weight); - } -} - -/** - * Helper function to create a menu item for a view. - */ -function _views_menu_item($path, $title, $view, $args, $access, $type, $weight = NULL) { - array_unshift($args, $view->name); - $retval = array('path' => $path, - 'title' => $title, - 'callback' => 'views_view_page', - 'callback arguments' => $args, - 'access' => user_access('access content') && $access, - 'type' => $type, - ); - if ($weight !== NULL) { - $retval['weight'] = $weight; - } - return $retval; -} - -/** - * Determine what menu type a view needs to use. - */ -function _views_menu_type($view) { - if ($view->menu) { - if ($view->menu_tab_default) { - $type = MENU_DEFAULT_LOCAL_TASK; - } - else if ($view->menu_tab) { - $type = MENU_LOCAL_TASK; - } - else { - $type = MENU_NORMAL_ITEM; - } - } - else { - $type = MENU_CALLBACK; - } - return $type; -} - -/** - * Implementation of hook_block() - */ -function views_block($op = 'list', $delta = 0) { - $block = array(); - if ($op == 'list') { - views_load_cache(); - // Grab views from the database and provide them as blocks. - $result = db_query("SELECT vid, block_title, page_title, name FROM {view_view} WHERE block = 1"); - while ($view = db_fetch_object($result)) { - $block[$view->name]['info'] = filter_xss_admin(views_get_title($view, 'block-info')); - } - - $default_views = _views_get_default_views(); - $views_status = variable_get('views_defaults', array()); - - foreach ($default_views as $name => $view) { - if (!isset($block[$name]) && $view->block && - ($views_status[$name] == 'enabled' || (!$view->disabled && $views_status[$name] != 'disabled'))) { - $block[$name]['info'] = filter_xss_admin(views_get_title($view, 'block')); - } - } - return $block; - } - else if ($op == 'view') { - return views_view_block($delta); - } -} - -// --------------------------------------------------------------------------- -// View Construction - -/** - * Ensure that all the arrays in a view exist so we don't run into array - * operations on a non-array error. - */ -function _views_check_arrays(&$view) { - $fields = array('field', 'sort', 'argument', 'filter', 'exposed_filter', 'access'); - - foreach($fields as $field) { - if (!is_array($view->$field)) { - $view->$field = array(); - } - } - return $view; -} - -/** - * This function loads a view by name or vid; if not found in db, it looks - * for a default view by that name. - */ -function views_get_view($view_name) { - views_load_cache(); - $view = _views_load_view($view_name); - if ($view) { - return $view; - } - - if (is_int($view_name)) { - return; // don't bother looking if view_name is an int! - } - - $default_views = _views_get_default_views(); - - if (isset($default_views[$view_name])) { - return $default_views[$view_name]; - } -} - -/** - * This views a view by page, and should only be used as a callback. - * - * @param $view_name - * The name or id of the view to load - * @param $args - * The arguments from the end of the url. Usually passed from the menu system. - * - * @return - * The view page. - */ -function views_view_page() { - $args = func_get_args(); - $view_name = array_shift($args); - $view = views_get_view($view_name); - - if (!$view) { - drupal_not_found(); - exit; - } - - $output = views_build_view('page', $view, $args, $view->use_pager, $view->nodes_per_page); - if ($output === FALSE) { - drupal_not_found(); - exit; - } - - return $output; -} - -/** - * This views a view by block. Can be used as a callback or programmatically. - */ -function views_view_block($vid) { - views_load_cache(); - $view = views_get_view($vid); - - if (!$view || !$view->block) { - return NULL; - } - - global $user; - if (!$user->roles) { - return NULL; - } - - $roles = array_keys($user->roles); - if ($view->access && !array_intersect($roles, $view->access)) { - return NULL; - } - - $content = views_build_view('block', $view, array(), false, $view->nodes_per_block); - if ($content) { - $block['content'] = $content; - $block['subject'] = filter_xss_admin(views_get_title($view, 'block')); - return $block; - } - else { - return NULL; - } -} - -function &views_set_current_view(&$view) { - static $current_view = NULL; - if ($view !== NULL) { - unset($current_view); - $current_view = &$view; - unset($GLOBALS['current_view']); - $GLOBALS['current_view'] = &$view; - } - return $current_view; -} - -function &views_get_current_view() { - $dummy = NULL; - return views_set_current_view($dummy); -} - -/** - * This builds the basic view. - * @param $type - * 'page' -- Produce output as a page, sent through theme. - * The only real difference between this and block is that - * a page uses drupal_set_title to change the page title. - * 'block' -- Produce output as a block, sent through theme. - * 'embed' -- Use this if you want to embed a view onto another page, - * and don't want any block or page specific things to happen to it. - * 'result' -- return an $info array. The array contains: - * query: The actual query ran. - * countquery: The count query that would be run if limiting was required. - * summary: True if an argument was missing and a summary was generated. - * level: What level the missing argument was at. - * result: Database object you can use db_fetch_object on. - * 'items' -- return info array as above, except instead of result, - * items: An array of objects containing the results of the query. - * 'queries' -- returns an array, summarizing the queries, but does not - * run them. - * @param $view - * The actual view object. Use views_get_view() if you only have the name or - * vid. - * @param $args - * args taken from the URL. Not relevant for many views. Can be null. - * @param $use_pager - * If set, use a pager. Set this to the pager id you want it - * to use if you plan on using multiple pagers on a page. To go with the - * default setting, set to $view->use_pager. Note that the pager element - * id will be decremented in order to have the IDs start at 0. - * @param $limit - * Required if $use_pager is set; if $limit is set and $use_pager is - * not, this will be the maximum number of records returned. This is ignored - * if using a view set to return a random result. To go with the default - * setting set to $view->nodes_per_page or $view->nodes_per_block. If - * $use_pager is set and this field is not, you'll get a SQL error. Don't - * do that! - * @param $page - * $use_pager is false, and $limit is !0, $page tells it what page to start - * on, in case for some reason a particular section of view is needed, - * @param $offset - * If $use_pager == false, skip the first $offset results. Does not work - * with pager. - * without paging on. -*/ -function views_build_view($type, &$view, $args = array(), $use_pager = false, $limit = 0, $page = 0, $offset = 0) { - views_load_cache(); - - // Fix a number of annoying whines when NULL is passed in.. - if ($args == NULL) { - $args = array(); - } - - views_set_current_view($view); - - $view->build_type = $type; - $view->type = ($type == 'block' ? $view->block_type : $view->page_type); - - if ($view->view_args_php) { - ob_start(); - $result = eval($view->view_args_php); - if (is_array($result)) { - $args = $result; - } - ob_end_clean(); - } - - // Call a hook that'll let modules modify the view query before it is created - foreach (module_implements('views_pre_query') as $module) { - $function = $module .'_views_pre_query'; - $output .= $function($view); - } - - $plugins = _views_get_style_plugins(); - if ($view->query) { - $info['query'] = $view->query; - $info['countquery'] = $view->countquery; - - if ($plugins[$view->type]['needs_table_header']) { - $view->table_header = _views_construct_header($view, _views_get_fields()); - } - } - else { - views_load_query(); - - $info = _views_build_query($view, $args); - if ($info['fail']) { - return FALSE; - } - } - - // Run-time replacement so we can do cacheing - $replacements = module_invoke_all('views_query_substitutions', $view); - foreach ($replacements as $src => $dest) { - $info['query'] = str_replace($src, $dest, $info['query']); - $info['countquery'] = str_replace($src, $dest, $info['countquery']); - - if (is_array($info['args'])) { - foreach ($info['args'] as $id => $arg) { - $info['args'][$id] = str_replace($src, $dest, $arg); - } - } - } - - $query = db_rewrite_sql($info['query'], 'node'); - - if ($type == 'queries') { - return $info; - } - - if ($use_pager) { - $cquery = db_rewrite_sql($info['countquery'], 'node', 'nid', $info['rewrite_args']); - $result = pager_query($query, $limit, $use_pager - 1, $cquery, $info['args']); - $view->total_rows = $GLOBALS['pager_total_items'][$use_pager - 1]; - } - else { - $result = ($limit ? db_query_range($query, $info['args'], $page * $limit + $offset, $limit) : db_query($query, $info['args'])); - } - $view->num_rows = db_num_rows($result); - if ($type == 'result') { - $info['result'] = $result; - return $info; - } - - $items = array(); - while ($item = db_fetch_object($result)) { - $items[] = $item; - } - - if ($type == 'items') { - $info['items'] = $items; - return $info; - } - - // Call a hook that'll let modules modify the view just before it is displayed. - foreach (module_implements('views_pre_view') as $module) { - $function = $module .'_views_pre_view'; - $output .= $function($view, $items); - } - - $view->real_url = views_get_url($view, $args); - - $view->use_pager = $use_pager; - $view->pager_limit = $limit; - $output .= views_theme('views_view', $view, $type, $items, $info['level'], $args); - - // Call a hook that'll let modules modify the view just after it is displayed. - foreach (module_implements('views_post_view') as $module) { - $function = $module .'_views_post_view'; - $output .= $function($view, $items, $output); - } - - return $output; -} - -// --------------------------------------------------------------------------- -// Utility - -/** - * Load the cache sub-module - */ -function views_load_cache() { - $path = drupal_get_path('module', 'views'); - require_once("./$path/views_cache.inc"); -} - -/** - * Load the query sub-module - */ -function views_load_query() { - $path = drupal_get_path('module', 'views'); - require_once("./$path/views_query.inc"); -} - -/** - * Easily theme any item to a view. - * @param $function - * The name of the function to call. - * @param $view - * The view being themed. - */ -function views_theme() { - $args = func_get_args(); - $function = array_shift($args); - $view = $args[0]; - - if (!($func = theme_get_function($function . "_" . $view->name))) { - $func = theme_get_function($function); - } - - if ($func) { - return call_user_func_array($func, $args); - } -} - -/** - * Easily theme any item to a field name. - * field name will be in the format of TABLENAME_FIELDNAME - * You have to understand a bit about the views data to utilize this. - * - * @param $function - * The name of the function to call. - * @param $field_name - * The field being themed. - */ -function views_theme_field() { - $args = func_get_args(); - $function = array_shift($args); - $field_name = array_shift($args); - $view = array_pop($args); - - if (!($func = theme_get_function($function . '_' . $view->name . '_' . $field_name))) { - if (!($func = theme_get_function($function . '_' . $field_name))) { - $func = theme_get_function($function); - } - } - - if ($func) { - return call_user_func_array($func, $args); - } -} - -/** - * Figure out what timezone we're in; needed for some date manipulations. - */ -function _views_get_timezone() { - global $user; - if (variable_get('configurable_timezones', 1) && $user->uid && strlen($user->timezone)) { - $timezone = $user->timezone; - } - else { - $timezone = variable_get('date_default_timezone', 0); - } - - // set up the database timezone - if (in_array($GLOBALS['db_type'], array('mysql', 'mysqli'))) { - static $already_set = false; - if (!$already_set) { - if ($GLOBALS['db_type'] == 'mysqli' || version_compare(mysql_get_server_info(), '4.1.3', '>=')) { - db_query("SET @@session.time_zone = '+00:00'"); - } - $already_set = true; - } - } - - return $timezone; -} - -/** - * Figure out what the URL of the view we're currently looking at is. - */ -function views_get_url($view, $args) { - $url = $view->url; - - if (!empty($url)) { - $where = 1; - foreach ($args as $arg) { - // This odd construct prevents us from strposing once there is no - // longer an $arg to replace. - if ($where && $where = strpos($url, '$arg')) { - $url = substr_replace($url, $arg, $where, 4); - } - else { - $url .= "/$arg"; - } - } - } - - return $url; -} - -/** - * Figure out what the title of a view should be. - */ -function views_get_title($view, $context = 'menu', $args = NULL) { - if (($context == 'menu' || $context == 'admin' )&& $view->menu_title) - return $view->menu_title; - - if ($context == 'block-info') { - return $view->description ? $view->description : $view->name; - } - - if ($args === NULL) { - $args = $view->args; - } - // Grab the title from the highest argument we got. If there is no such - // title, track back until we find a title. - - if (is_array($args)) { - $rargs = array_reverse(array_keys($args)); - foreach ($rargs as $arg_id) { - if ($title = $view->argument[$arg_id]['title']) { - break; - } - } - } - - if (!$title && ($context == 'menu' || $context == 'page' || $context == 'admin')) { - $title = $view->page_title; - } - - if (!$title && $context == 'block' || $context == 'admin') { - $title = $view->block_title; - } - - if (!$view->argument) { - return $title; - } - - views_load_cache(); - $arginfo = _views_get_arguments(); - foreach ($view->argument as $i => $arg) { - if (!isset($args[$i])) { - break; - } - $argtype = $arg['type']; - if ($arg['wildcard'] == $args[$i] && $arg['wildcard_substitution'] != '') { - $title = str_replace("%" . ($i + 1), $arg['wildcard_substitution'], $title); - } - else if (function_exists($arginfo[$argtype]['handler'])) { - // call the handler - $rep = $arginfo[$argtype]['handler']('title', $args[$i], $argtype); - $title = str_replace("%" . ($i + 1), $rep, $title); - } - } - return $title; -} - -/** - * Determine whether or not a view is cacheable. A view is not cacheable if - * there is some kind of user input or data required. For example, views - * that need to restrict to the 'current' user, or any views that require - * arguments or allow click-sorting are not cacheable. - */ -function _views_is_cacheable(&$view) { - // views with arguments are immediately not cacheable. - if (!empty($view->argument) || !empty($view->exposed_filter) || !empty($view->no_cache)) { - return false; - } - - $filters = _views_get_filters(); - - foreach ($view->filter as $i => $filter) { - if ($filters[$filter['field']]['cacheable'] == 'no') { - return false; - } - } - - foreach ($view->field as $i => $field) { - if ($field['sortable']) { - return false; - } - } - return true; -} - -/** - * Invalidate the views cache, forcing a rebuild on the next grab of table data. - */ -function views_invalidate_cache() { - cache_clear_all('views_', 'cache', true); -} - -// --------------------------------------------------------------------------- -// Database functions - -/** - * Provide all the fields in a view. - */ -function _views_view_fields() { - return array('vid', 'name', 'description', 'access', 'page', 'page_title', 'page_header', 'page_header_format', 'page_footer', 'page_footer_format', 'page_empty', 'page_empty_format', 'page_type', 'use_pager', 'nodes_per_page', 'url', 'menu', 'menu_tab', 'menu_tab_default', 'menu_tab_weight', 'menu_title', 'block', 'block_title', 'block_use_page_header', 'block_header', 'block_header_format', 'block_use_page_footer', 'block_footer', 'block_footer_format', 'block_use_page_empty', 'block_empty', 'block_empty_format', 'block_type', 'nodes_per_block', 'block_more', 'url', 'breadcrumb_no_home', 'changed', 'query', 'countquery', 'view_args_php'); -} - -/** - * Delete a view from the database. - */ -function _views_delete_view($view) { - $view->vid = intval($view->vid); - if (!$view->vid) { - return; - } - - db_query("DELETE FROM {view_view} where vid=%d", $view->vid); - db_query("DELETE FROM {view_sort} where vid=%d", $view->vid); - db_query("DELETE FROM {view_argument} where vid=%d", $view->vid); - db_query("DELETE FROM {view_tablefield} where vid=%d", $view->vid); -} - -/** - * Load a view from the database -- public version of the function. - */ -function views_load_view($arg) { - return _views_load_view($arg); -} - -/** - * Load a view from the database. - * (deprecated; use views_load_view in favor of this function). - */ -function _views_load_view($arg) { - static $cache = array(); - $which = is_numeric($arg) ? 'vid' : 'name'; - if (isset($cache[$which][$arg])) { - return $cache[$which][$arg]; - } - - $where = (is_numeric($arg) ? "v.vid = %d" : "v.name = '%s'"); - $view = db_fetch_object(db_query("SELECT v.* FROM {view_view} v WHERE $where", $arg)); - - if (!$view->name) { - return NULL; - } - - $view->access = ($view->access ? explode(', ', $view->access) : array()); - - // load the sorting criteria too. - $result = db_query("SELECT * FROM {view_sort} vs WHERE vid = $view->vid ORDER BY position ASC"); - - $view->sort = array(); - while ($sort = db_fetch_array($result)) { - if (substr($sort['field'], 0, 2) == 'n.') { - $sort['field'] = 'node' . substr($sort['field'], 1); - } - $sort['id'] = $sort['field']; - $view->sort[] = $sort; - } - - $result = db_query("SELECT * FROM {view_argument} WHERE vid = $view->vid ORDER BY position ASC"); - - $view->argument = array(); - while ($arg = db_fetch_array($result)) { - $arg['id'] = $arg['type']; - $view->argument[] = $arg; - } - - $result = db_query("SELECT * FROM {view_tablefield} WHERE vid = $view->vid ORDER BY position ASC"); - - $view->field = array(); - while ($arg = db_fetch_array($result)) { - if ($arg['tablename'] == 'n') { - $arg['tablename'] = 'node'; - } - $arg['id'] = $arg['fullname'] = "$arg[tablename].$arg[field]"; - $arg['queryname'] = "$arg[tablename]_$arg[field]"; - $view->field[] = $arg; - } - - $result = db_query("SELECT * FROM {view_filter} WHERE vid = $view->vid ORDER BY position ASC"); - - views_load_cache(); - $filters = _views_get_filters(); - $view->filter = array(); - while ($filter = db_fetch_array($result)) { - if (substr($filter['field'], 0, 2) == 'n.') { - $filter['field'] = 'node' . substr($filter['field'], 1); - } - - if ($filter['operator'] == 'AND' || - $filter['operator'] == 'OR' || - $filter['operator'] == 'NOR' || - $filters[$filter['field']]['value-type'] == 'array' ) { - if ($filter['value'] !== NULL && $filter['value'] !== '') { - $filter['value'] = explode(',', $filter['value']); - } - else { - $filter['value'] = array(); - } - } - $filter['id'] = $filter['field']; - $view->filter[] = $filter; - } - - $result = db_query("SELECT * FROM {view_exposed_filter} WHERE vid = $view->vid ORDER BY position ASC"); - - $view->exposed_filter = array(); - while ($arg = db_fetch_array($result)) { - $arg['id'] = $arg['field']; - $view->exposed_filter[] = $arg; - } - - $cache['vid'][$view->vid] = $view; - $cache['name'][$view->name] = $view; - - return $view; -} - -/** - * Save a view to the database. - */ -function _views_save_view($view) { - _views_check_arrays($view); - - // cache the query - if (_views_is_cacheable($view)) { - views_load_query(); - - $info = _views_build_query($view); - $view->query = _views_replace_args($info['query'], $info['args']); - $view->countquery = _views_replace_args($info['countquery'], $info['args']); - } - else { - $view->query = NULL; - $view->countquery = NULL; - } - - $view->access = implode(', ', $view->access); - - $view->changed = time(); - $fields = _views_view_fields(); - if ($view->vid) { - // update - // Prepare the query: - foreach ($view as $key => $value) { - if (in_array($key, $fields)) { - $q[] = db_escape_string($key) ." = '%s'"; - $v[] = $value; - } - } - - // Update the view in the database: - db_query("UPDATE {view_view} SET " . implode(', ', $q) . " WHERE vid = '$view->vid'", $v); - db_query("DELETE from {view_sort} WHERE vid='$view->vid'"); - db_query("DELETE from {view_argument} WHERE vid='$view->vid'"); - db_query("DELETE from {view_tablefield} WHERE vid='$view->vid'"); - db_query("DELETE from {view_filter} WHERE vid='$view->vid'"); - db_query("DELETE from {view_exposed_filter} WHERE vid='$view->vid'"); - } - else { - // insert - - // This method really saves on typos, and makes it a lot easier to add fields - // later on. - $view->vid = db_next_id('{view_view}_vid'); - - // Prepare the query: - foreach ($view as $key => $value) { - if (in_array((string) $key, $fields)) { - $k[] = db_escape_string($key); - $v[] = $value; - $s[] = is_numeric($value) ? '%d' : "'%s'"; - } - } - - db_query("INSERT INTO {view_view} (" . implode(", ", $k) . ") VALUES (" . implode(", ", $s) . ")", $v); - } - - foreach ($view->sort as $i => $sort) { - db_query("INSERT INTO {view_sort} (vid, position, field, sortorder, options) VALUES (%d, %d, '%s', '%s', '%s')", $view->vid, $i, $sort['field'], $sort['sortorder'], $sort['options']); - } - - foreach ($view->argument as $i => $arg) { - db_query("INSERT INTO {view_argument} (vid, type, argdefault, title, options, position, wildcard, wildcard_substitution) VALUES (%d, '%s', %d, '%s', '%s', %d, '%s', '%s')", $view->vid, $arg['type'], $arg['argdefault'], $arg['title'], $arg['options'], $i, $arg['wildcard'], $arg['wildcard_substitution']); - } - - foreach ($view->field as $i => $arg) { - db_query("INSERT INTO {view_tablefield} (vid, tablename, field, label, handler, sortable, defaultsort, options, position) VALUES (%d, '%s', '%s', '%s', '%s', %d, '%s', '%s', %d)", $view->vid, $arg['tablename'], $arg['field'], $arg['label'], $arg['handler'], $arg['sortable'], $arg['defaultsort'], $arg['options'], $i); - } - - foreach ($view->filter as $i => $arg) { - if (is_array($arg['value'])) { - $arg['value'] = implode(',', $arg['value']); - } - db_query("INSERT INTO {view_filter} (vid, tablename, field, value, operator, options, position) VALUES (%d, '%s', '%s', '%s', '%s', '%s', %d)", $view->vid, $arg['tablename'], $arg['field'], $arg['value'], $arg['operator'], $arg['options'], $i); - } - - foreach ($view->exposed_filter as $i => $arg) { - db_query("INSERT INTO {view_exposed_filter} (vid, field, label, optional, is_default, single, operator, position) VALUES (%d, '%s', '%s', %d, %d, %d, %d, %d)", $view->vid, $arg['field'], $arg['label'], $arg['optional'], $arg['is_default'], $arg['single'], $arg['operator'], $i); - } -} - -// --------------------------------------------------------------------------- -// Helper functions to build views and view data - -/** - * Helper function to make table creation a little easier. It adds the necessary - * data to a $table array and returns it. - */ -function views_new_table($table_name, $provider, $left_table, $left_field, $right_field, $extra = NULL) { - $table['name'] = $table_name; - $table['provider'] = $provider; - $table['join']['left']['table'] = $left_table; - $table['join']['left']['field'] = $left_field; - $table['join']['right']['field'] = $right_field; - if ($extra) { - $table['join']['extra'] = $extra; - } - return $table; -} - -/** - * Helper function to make table creation a little easier. It adds the necessary - * data to the $table array. - */ -function views_table_add_field(&$table, $name, $label, $help, $others = array()) { - views_table_add_data($table, 'fields', $name, $label, $help, $others); -} - -/** - * Helper function to make table creation a little easier. It adds the necessary - * data to the $table array. - */ -function views_table_add_filter(&$table, $name, $label, $help, $others = array()) { - views_table_add_data($table, 'filters', $name, $label, $help, $others); -} - -/** - * Helper function to make table creation a little easier. It adds the necessary - * data to the $table array. - */ -function views_table_add_sort(&$table, $name, $label, $help, $others = array()) { - views_table_add_data($table, 'sorts', $name, $label, $help, $others); -} - -/** - * Helper function to make table creation a little easier. It adds the necessary - * data to the $table array. - */ -function views_table_add_data(&$table, $type, $name, $label, $help, $others = array()) { - $table[$type][$name]['name'] = $label; - $table[$type][$name]['help'] = $help; - foreach ($others as $key => $value) { - $table[$type][$name][$key] = $value; - } -} - -/** - * Create a blank view. - */ -function views_create_view($name, $description, $access = array()) { - $view = new stdClass(); - _views_check_arrays($view); - - $view->name = $name; - $view->description = $description; - $view->access = $access; - - // ensure some things are numerically 0. - $view->nodes_per_page = 0; - $view->nodes_per_block = 0; - return $view; -} - -/** - * Add page info to a view. - */ -function views_view_add_page(&$view, $title, $url, $type, $pager, $nodes_per_page, $header, $header_format, $breadcrumb_no_home = FALSE) { - $view->page = TRUE; - $view->page_title = $title; - $view->url = $url; - $view->page_type = $type; - $view->use_pager = $pager; - $view->nodes_per_page = $nodes_per_page; - $view->page_header = $header; - $view->page_header_format = $header_format; - $view->breadcrumb_no_home = $breadcrumb_no_home; -} - -/** - * Add menu info to a view. - */ -function views_view_add_menu(&$view, $title, $tab, $tab_weight, $default_tab) { - $view->menu = TRUE; - $view->menu_title = $title; - $view->menu_tab = $tab; - $view->menu_tab_weight = $tab_weight; - $view->menu_tab_default = $default_tab; -} - -/** - * Add block info to a view. - */ -function views_view_add_block(&$view, $title, $type, $nodes_per_block, $more, $use_page_header, $header = '', $header_format = 0) { - $view->block = TRUE; - $view->block_title = $title; - $view->block_type = $type; - $view->nodes_per_block = $nodes_per_block; - $view->block_more = $more; - $view->block_use_page_header = $use_page_header; - $view->block_header = $header; - $view->block_header_format = $header_format; -} - -/** - * Add field info to a view. - */ -function views_view_add_field(&$view, $table, $field, $label, $sortable = FALSE, $default_sort = 0, $handler = '') { - $view->field[] = array( - 'tablename' => $table, - 'field' => $field, - 'label' => $label, - 'sortable' => $sortable, - 'defaultsort' => $default_sort, - 'handler' => $handler - ); -} - -/** - * Add argument info to a view. - */ -function views_view_add_argument(&$view, $type, $default, $title, $option = '') { - $view->argument[] = array( - 'type' => $type, - 'argdefault' => $default, - 'title' => $title, - 'options' => $option, - ); -} - -/** - * Add filter info to a view. - */ -function views_view_add_filter(&$view, $table, $field, $operator, $value, $option) { - $view->filter[] = array( - 'tablename' => $table, - 'field' => $field, - 'operator' => $operator, - 'value' => $value, - 'options' => $option, - ); -} - -/** - * Add exposed_filter info to a view. - */ -function views_view_add_exposed_filter(&$view, $table, $field, $optional, $is_default, $lock_operator, $single) { - $view->exposed_filter[] = array( - 'tablename' => $table, - 'field' => $field, - 'optional' => $optional, - 'is_default' => $is_default, - 'operator' => $lock_operator, - 'single' => $single - ); -} /** - * Add sort info to a view. + * Implementation of hook_menu */ -function views_view_add_sort(&$view, $table, $field, $order, $option) { - $view->sort[] = array( - 'tablename' => $table, - 'field' => $field, - 'sortorder' => $order, - 'options' => $option +function views_menu() { + $items['views/test'] = array( + 'page callback' => 'views_test', + 'access callback' => TRUE, + 'title' => 'Views test', + 'type' => MENU_NORMAL_ITEM, ); -} - -// --------------------------------------------------------------------------- -// Themeable and support for themeables. - -/** - * Themeable function to handle displaying a specific field. - */ -function theme_views_handle_field($fields, $field, $data) { - $info = $fields[$field['fullname']]; - - if ($field['handler'] && function_exists($field['handler'])) { - return $field['handler']($info, $field, $data->$field['queryname'], $data); - } - - if ($info['handler'] && is_string($info['handler']) && function_exists($info['handler'])) { - return $info['handler']($info, $field, $data->$field['queryname'], $data); - } - - return check_plain($data->$field['queryname']); -} - -/** - * Construct a header for a table view. - */ -function _views_construct_header($view, $fields) { - foreach ($view->field as $field) { - $header = array(); - $info = $fields[$field['fullname']]; - - if ($field['sortable']) { - $header['data'] = ($field['label'] ? $field['label'] : $info['name']); - if (function_exists($info['sort_handler'])) { - $header['field'] = $info['sort_handler']($field, $info); - } - else { - $header['field'] = $field['fullname']; - } - } - else if ($field['label']) { - $header['data'] = $field['label']; - } - - if ($field['defaultsort']) { - $header['sort'] = strtolower($field['defaultsort']); - } - - // Add CSS id to table cell header cell. - $header['class'] = "view-cell-header" . views_css_safe(' view-field-'. $field['queryname']); - $headers[] = $header; - } - return $headers; -} - -function theme_views_display_filters($view) { - return drupal_get_form("views_filters", $view); -} - -function views_filters($view) { - $filters = _views_get_filters(); - foreach ($view->exposed_filter as $count => $expose) { - $id = $expose['id']; - $filterinfo = $filters[$id]; - foreach ($view->filter as $filter) { - if ($filter['id'] == $id) { - break; - } - } - - // set up the operator widget. - if (!$expose['operator']) { - // 'operator' is either an array or a handler - $operator = $filterinfo['operator']; - if (!is_array($operator) && function_exists($filterinfo['operator'])) { - $operator = $filterinfo['operator']('operator', $filterinfo); - } - - $form["op$count"] = array( - '#name' => "op$count", // get rid of edit[] array. - '#type' => 'select', - '#default_value' => $filter['operator'], - '#options' => $operator, - ); - if (array_key_exists("op$count", $_GET)) { - $form["op$count"]["#default_value"] = $_GET["op$count"]; - } - } - - - // set up the filter widget. - $item = $filterinfo['value']; - $item['#name'] = "filter$count"; - - if (!is_array($item['#options']) && function_exists($item['#options'])) { - $item['#options'] = $item['#options']('value', $filterinfo); - } - if (!$expose['optional'] || $expose['is_default']) { - $item['#default_value'] = $filter['value']; - } - - if ($expose['single']) { - unset($item['#multiple']); - } - if ($expose['optional'] && is_array($item['#options'])) { - $item['#options'] = array('**ALL**' => t('')) + $item['#options']; - } - - if ($item['#multiple'] && is_array($item['#options'])) { - $item['#size'] = min(count($item['#options']), 8); - } - - if (array_key_exists("filter$count", $_GET)) { - $item["#default_value"] = $_GET["filter$count"]; - } - $form["filter$count"] = $item; - } - $form['#method'] = 'get'; - $form['#process'] = array('views_filters_process' => array()); - $form['#action'] = url($view->real_url ? $view->real_url : $view->url, NULL, NULL, true); - $form['view'] = array('#type' => 'value', '#value' => $view); - $form['submit'] = array('#type' => 'button', '#name' => '', '#value' => t('Submit')); - // clean URL get forms breaks if we don't give it a 'q'. - if (!(bool)variable_get('clean_url', '0')) { - $form['q'] = array( - '#type' => 'hidden', - '#value' => $view->real_url ? $view->real_url : $view->url, - '#name' => 'q', - ); - } - - - return $form; -} - -function views_filters_process($form) { - unset($form['form_id']); - unset($form['form_token']); - return $form; -} -function theme_views_filters($form) { - $view = $form['view']['#value']; - - foreach ($view->exposed_filter as $count => $expose) { - $row[] = drupal_render($form["op$count"]) . drupal_render($form["filter$count"]); - $label[] = $expose['label']; - } - $row[] = drupal_render($form['submit']); - $label[] = ''; // so the column count is the same. - - // make the 'q' come first - return drupal_render($form['q']) . theme('table', $label, array($row)) . drupal_render($form); -} - -/** - * Display the nodes of a view as a list. - */ -function theme_views_view_list($view, $nodes, $type) { - $fields = _views_get_fields(); - - foreach ($nodes as $node) { - $item = ''; - foreach ($view->field as $field) { - if ($fields[$field['id']]['visible'] !== FALSE) { - if ($field['label']) { - $item .= "
" . $field['label'] . "
"; - } - $item .= "
" . views_theme_field('views_handle_field', $field['queryname'], $fields, $field, $node, $view) . "
"; - } - } - $items[] = "
name) ."'>$item
\n"; // l($node->title, "node/$node->nid"); - } - if ($items) { - return theme('item_list', $items); - } -} - -/** - * Display the nodes of a view as a table. - */ -function theme_views_view_table($view, $nodes, $type) { - $fields = _views_get_fields(); - - foreach ($nodes as $node) { - $row = array(); - foreach ($view->field as $field) { - if ($fields[$field['id']]['visible'] !== FALSE) { - $cell['data'] = views_theme_field('views_handle_field', $field['queryname'], $fields, $field, $node, $view); - $cell['class'] = "view-field ". views_css_safe('view-field-'. $field['queryname']); - $row[] = $cell; - } - } - $rows[] = $row; - } - return theme('table', $view->table_header, $rows); -} - -/** - * Display the nodes of a view as teasers. - */ -function theme_views_view_teasers($view, $nodes, $type) { - return views_theme('views_view_nodes', $view, $nodes, $type, true); -} - -/** - * Display the nodes of a view as plain nodes. - */ -function theme_views_view_nodes($view, $nodes, $type, $teasers = false, $links = true) { - foreach ($nodes as $n) { - $node = node_load($n->nid); - $output .= node_view($node, $teasers, false, $links); - } - return $output; -} - -function views_set_breadcrumb($view) { - $breadcrumb = drupal_get_breadcrumb(); - if ($view->breadcrumb_no_home) { - array_shift($breadcrumb); - } - - if ($view->args) { - // Add a breadcrumb trail for each level of argument we're at. - $url = $view->url; - $args = array(); - $where = 1; - foreach ($view->args as $level => $arg) { - if ($view->argument[$level]['argdefault'] != 1) { - $breadcrumb[] = l(views_get_title($view, 'page', $args), $url); - // For next round. - } - $args[] = $arg; - if ($where && $where = strpos('$arg', $url)) { - $url = substr_replace($url, $arg, $where, 4); - } - else { - $url .= "/$arg"; - } - } - } - - drupal_set_breadcrumb($breadcrumb); -} - -function views_get_textarea($view, $type, $textarea) { - $use_page = "block_use_page_$textarea"; - $var = ($type != 'block' || $view->$use_page ? 'page_' : 'block_') . $textarea; - $format = $var . '_format'; - - if ($view->$var) { - return "
name) ."'>" - . check_markup($view->$var, $view->$format, false) . "
\n"; - } -} - -/** - * Prepare the specified string for use as a CSS identifier. - */ -function views_css_safe($string) { - return str_replace('_', '-', $string); -} - -/** - * Display a view. - */ -function theme_views_view($view, $type, $nodes, $level = NULL, $args = NULL) { - $num_nodes = count($nodes); - - if ($type == 'page') { - drupal_set_title(views_get_title($view, 'page')); - views_set_breadcrumb($view); - } - - if ($num_nodes) { - $output .= views_get_textarea($view, $type, 'header'); - } - - if ($type != 'block' && $view->exposed_filter) { - $output .= views_theme('views_display_filters', $view); - } - - $plugins = _views_get_style_plugins(); - $view_type = ($type == 'block') ? $view->block_type : $view->page_type; - if ($num_nodes || $plugins[$view_type]['even_empty']) { - if ($level !== NULL) { - $output .= "
name) ."'>". views_theme($plugins[$view_type]['summary_theme'], $view, $type, $level, $nodes, $args) . '
'; - } - else { - $output .= "
name) ."'>". views_theme($plugins[$view_type]['theme'], $view, $nodes, $type) . '
'; - } - $output .= views_get_textarea($view, $type, 'footer'); - - if ($type == 'block' && $view->block_more && $num_nodes >= $view->nodes_per_block) { - $output .= theme('views_more', $view->real_url); - } - } - else { - $output .= views_get_textarea($view, $type, 'empty'); - } - - if ($view->use_pager) { - $output .= theme('pager', '', $view->pager_limit, $view->use_pager - 1); - } - if ($output) { - $output = "
name) ."'>$output
\n"; - } - return $output; -} - -/** - * Format the 'more' link for a view. Personally I prefer [More] but I've - * been convinced to go with simply 'more'. - */ -function theme_views_more($url) { - return ""; -} - -/** - * Get the summary link for a view. - */ -function views_get_summary_link($argtype, $item, $base) { - $arginfo = _views_get_arguments(); - return $arginfo[$argtype]['handler']('link', $item, $argtype, $base); + return $items; } -/** - * In a summary view, each entry links to a more specific entry - * in that view. Construct the base of that link. - */ +function views_test() { /* -function views_get_summary_link_base($argtype, $url, $level, $args) { - $arginfo = _views_get_arguments(); - if (!function_exists($arginfo[$argtype]['handler'])) { - return NULL; - } - - $arg = $url; - for ($i = 0; $i < $level; $i++) { - $arg .= "/$args[$i]"; - } - - return $arg; -} + views_include_view(); + $view = new view; + $view->name = 'foo'; + $view->description = 'foobar'; + $view->set_page_size(3); + + $argument = new views_argument; + $argument->type = 'node_nid'; + $argument->default_action = 'not_found'; + $argument->title = '%1'; + + $view->argument[] = drupal_clone($argument); + $argument->default_action = 'summary, ascended'; + $view->argument[] = $argument; + + $view->save(); + + $view2 = new view; + $view2->load($view->vid); + + $output = '
';
+  $array = array();
+  $output .= "Array test: " . (array_push($array, 'foo'));
+  $output .= "\n";
+  $output .= var_export($view, 1);
+  $output .= var_export($view2, 1);
+  $output .= '
'; */ -/** - * Display a summary version of a view. - */ -function theme_views_summary($view, $type, $level, $nodes, $args) { - foreach ($nodes as $node) { - $items[] = views_get_summary_link($view->argument[$level]['type'], $node, $view->real_url) . " (" . $node->num_nodes . ")"; - } - if ($items) { - $output .= theme('item_list', $items); - } - - return $output; -} - -// --------------------------------------------------------------------------- -// Generic handlers. These make sense to be used in a lot of different places. - -/** - * Field handlers accept the following arguments: - * @param $fieldinfo - * The array of info for that field from the global tables array. - * @param $fielddata - * All of the info about that field in the database. - * @param $value - * The value of the field fetched from the database. - * @param $data - * The rest of the data about the node fetched from the database, in case - * the handler needs more than just the field. - */ - -/** - * Format a date. - */ -function views_handler_field_date($fieldinfo, $fielddata, $value, $data) { - return $value ? format_date($value) : theme('views_nodate'); -} - -/** - * Format a date using small representation. - */ -function views_handler_field_date_small($fieldinfo, $fielddata, $value, $data) { - return $value ? format_date($value, 'small') : theme('views_nodate'); -} - -/** - * Format a date using large representation. - */ -function views_handler_field_date_large($fieldinfo, $fielddata, $value, $data) { - return $value ? format_date($value, 'large') : theme('views_nodate'); -} - -/** - * Format a date using custom representation. - */ -function views_handler_field_date_custom($fieldinfo, $fielddata, $value, $data) { - return $value ? format_date($value, 'custom', $fielddata['options']) : theme('views_nodate'); -} - -/** - * Format a date as "X time ago". - */ -function views_handler_field_since($fieldinfo, $fielddata, $value, $data) { - return $value ? t('%time ago', array('%time' => format_interval(time() - $value, is_numeric($fielddata['options']) ? $fielddata['options'] : 2))) : theme('views_nodate'); -} - -function theme_views_nodate() { - return '' . t('never') . ''; -} - -/** - * Provide a list of all standard supproted date output handlers. - */ -function views_handler_field_dates() { - return array( - 'views_handler_field_date_small' => t('As Short Date'), - 'views_handler_field_date' => t('As Medium Date'), - 'views_handler_field_date_large' => t('As Long Date'), - 'views_handler_field_date_custom' => t('As Custom Date'), - 'views_handler_field_since' => t('As Time Ago') - ); -} -function views_handler_sort_date_options() { - return array( - '#type' => 'select', - '#options' => array( - 'normal' => t('Normal'), - 'minute' => t('Granularity: minute'), - 'hour' => t('Granularity: hour'), - 'day' => t('Granularity: day'), - 'month' => t('Granularity: month'), - 'year' => t('Granularity: year'), - ), - ); -} - -function views_handler_sort_date($op, &$query, $sortinfo, $sort) { - switch($sort['options']) { - case 'normal': - default: - $table = $sortinfo['table']; - $field = $sortinfo['field']; - break; - case 'minute': - $field = "DATE_FORMAT(FROM_UNIXTIME($sortinfo[table].$sortinfo[field]), '%Y%m%%d%H%m')"; - break; - case 'hour': - $field = "DATE_FORMAT(FROM_UNIXTIME($sortinfo[table].$sortinfo[field]), '%Y%m%%d%H')"; - break; - case 'day': - $field = "DATE_FORMAT(FROM_UNIXTIME($sortinfo[table].$sortinfo[field]), '%Y%m%%d')"; - break; - case 'month': - $field = "DATE_FORMAT(FROM_UNIXTIME($sortinfo[table].$sortinfo[field]), '%Y%m%)"; - break; - case 'year': - $field = "DATE_FORMAT(FROM_UNIXTIME($sortinfo[table].$sortinfo[field]), '%Y%')"; - break; - } - $alias = $as = $sortinfo['table'] . '_' . $sortinfo['field']; - if (!$table) { - $as .= '_orderby'; - $alias = $field; - } - -// $query->add_field($field, $table, $as); -// $query->orderby[] = "$alias $sort[sortorder]"; - $query->add_orderby($table, $field, $sort['sortorder'], $as); -} + views_include_query(); + $query = new views_query; -function views_handler_sort_date_minute($op, &$query, $sortinfo, $sort) { - $field = "DATE_FORMAT(FROM_UNIXTIME($table.$sortinfo[field]), '%Y%m%%d%H%m')"; - $query->add_orderby(NULL, $field, $sort['sortorder']); -} -/** - * Format a field as an integer. - */ -function views_handler_field_int($fieldinfo, $fielddata, $value, $data) { - return intval($value); -} -/** - * Argument handlers take up to 4 fields, which vary based upon the operation. - * @param $op - * The operation to perform: - * 'summary': A summary view is being constructed. In this case the handler - * is to add the necessary components to the query to display - * the summary. It must return a $fieldinfo array with 'field' - * set to the field the summary is ordered by; if this is aliased - * for some reason (such as being an aggregate field) set 'fieldname' - * to the alias. - * 'sort': Set up the view to sort based upon the setting in $a2. - * 'filter': Filter the view based upon the argument sent; essentially just - * add the where clause here. - * 'link': Provide a link from a summary view based upon the argument sent. - * 'title': Provide the title of a view for substitution. - * @param &$query - * For summary, filter and link, this is the actual query object; for title this is - * simply the value of the argument. - * @param $a2 - * For summary, this is the type of the argument. For the others, this is the info - * for the argument from the global table. (Why is this not consistent? I dunno). - * @param $a3 - * For summary, this is the 'options' field from the db. For 'filter' this is - * the argument received. For 'link' this is the base URL of the link. Not used - * for 'title'. - * - */ + $book_parent = $query->add_relationship('book_parent', new views_join('node', 'book', 'pid', 'nid')); + $book_parent_users = $query->ensure_table('users', 'book_parent'); -// --------------------------------------------------------------------------- -// Filter handlers + $book_parent_parent = $query->add_relationship('book_parent_parent', new views_join('node', 'book', 'pid', 'nid'), 'book_parent'); + $book_parent_parent_users = $query->ensure_table('users', 'book_parent_parent'); -/** - * There are two kinds of filter handlers here; the easy kind simply creates an - * array of options. For example, for taxonomy we provide a list of all taxonomy - * terms which is placed in the select box. - * - * The other type is the 'custom' handler which is used to create a customized - * WHERE clause for specialized filters. - * - * It takes 4 parameters. - * @param $op - * At this time it will always be 'handler'. - * @param $filter - * Information on the filter from the database, including 'options', 'value' and 'operator'. - * @param $filterinfo - * Information on the filter from the global table array. - * @param &$query - * The query object being worked on. - */ -/** - * A list of and/or/nor. - */ -function views_handler_operator_andor() { - return array('AND' => t('Is All Of'), 'OR' => t('Is One Of'), 'NOR' => t('Is None Of')); -} -/** - * A list of or/nor. - */ -function views_handler_operator_or() { - return array('OR' => t('Is One Of'), 'NOR' => t('Is None Of')); -} + $query->add_relationship('term_hierarchy_1', new views_join('term_hierarchy', 'term_hierarchy', 'parent', 'tid')); + $query->add_relationship('term_hierarchy_2', new views_join('term_hierarchy', 'term_hierarchy', 'parent', 'tid'), 'term_hierarchy_1'); + $book_parent_users = $query->ensure_table('term_data'); + $book_parent_users = $query->ensure_table('term_data', 'term_hierarchy_1', new views_join('term_data', 'term_hierarchy', 'tid', 'tid')); + $book_parent_users = $query->ensure_table('term_data_x', 'term_hierarchy_2'); -/** - * A list of equal or not equal to. - */ -function views_handler_operator_eqneq() { - return array('=' => t('Is Equal To'), '!=' => t('Is Not Equal To')); -} + $query->add_field('bar', 'baz'); + $query->add_field('node', 'title'); + $query->add_field(NULL, 'unix_timestamp(some_value)'); - /** - * A list of greater / equal / less than - */ -function views_handler_operator_gtlt() { - return array('>' => t("Is Greater Than"), '>=' => t("Is Greater Than Or Equals"), '=' => t("Is Equal To"), '!=' => t("Is Not Equal To"), '<=' => t("Is Less Than Or Equals"), '<' => t("Is Less Than")); -} + $query->set_where_group('or', 'or'); + $query->add_where(0, 'froot_loops = 1', 'froot', 'loops'); + $query->add_where(0, 'gay = yes', 'gay', 'yes'); + $query->add_where('or', 'foo = bar'); + $query->add_where('or', 'bar = baz', 'bar', 'baz'); -/** - * A list of yes/no. - */ -function views_handler_operator_yesno() { - return array('1' => t('Yes'), '0' => t('No')); -} + $output = ''; + $output .= '
';
+  $output .= $query->query() . "\n";
+  $output .= var_export($query->get_where_args(), true) . "\n";
 /*
- * Break x,y,z and x+y+z into an array. Numeric only.
- */
-function _views_break_phrase($str) {
-  if (preg_match('/^([0-9]+[+ ])+[0-9]+$/', $str)) {
-    // The '+' character in a query string may be parsed as ' '.
-    return array('or', preg_split('/[+ ]/', $str));
-  }
-  else if (preg_match('/^([0-9]+,)*[0-9]+$/', $str)) {
-    return array('and', explode(',', $str));
-  }
-  else {
-    return NULL;
-  }
-}
-
-/**
- * Default Views style plugins. Implementation of hook_views_style_plugins()
- */
-function views_views_style_plugins() {
-  return array(
-    'list' => array(
-      'name' => t('List View'),
-      'theme' => 'views_view_list',
-      'validate' => 'views_ui_plugin_validate_list',
-      'needs_fields' => true,
-      'weight' => -10,
-    ),
-    'table' => array(
-      'name' => t('Table View'),
-      'theme' => 'views_view_table',
-      'validate' => 'views_ui_plugin_validate_table',
-      'needs_fields' => true,
-      'needs_table_header' => true,
-      'weight' => -9,
-    ),
-    'teaser' => array(
-      'name' => t('Teaser List'),
-      'theme' => 'views_view_teasers',
-      'weight' => -8,
-    ),
-    'node' => array(
-      'name' => t('Full Nodes'),
-      'theme' => 'views_view_nodes',
-      'weight' => -7,
-    ),
-  );
-}
-
-/**
- * A list of options to be used in LIKE queries
- */
-function views_handler_operator_like() {
-  return array('=' => t('Is Equal To'), 'contains' => t('Contains'), 'word' => t('Contains Any Word'), 'allwords' => t('Contains All Words'), 'starts' => t('Starts With'), 'ends' => t('Ends With'), 'not' => t('Does Not Contain'));
-}
-
-/**
- * Custom filter for LIKE operations
- */
-function views_handler_filter_like($op, $filter, $filterinfo, &$query) {
-  switch (trim($filter['value'])) {
-    case (''):
-      return;
-      break;
-  }
-  switch ($op) {
-    case 'handler':
-      $table = $filterinfo['table'];
-      $column = $filterinfo['field'];
-      $field = "$table.$column";
-      $query->ensure_table($table);
-
-      switch ($filter['operator']) {
-        case 'contains':
-          $query->add_where("UPPER(%s) LIKE UPPER('%%%s%%')",
-            $field, $filter['value']);
-          break;
-        case 'word':
-        case 'allwords':
-          preg_match_all('/ (-?)("[^"]+"|[^" ]+)/i', ' '. $filter['value'], $matches, PREG_SET_ORDER);
-          foreach ($matches as $match) {
-            $phrase = false;
-            // Strip off phrase quotes
-            if ($match[2]{0} == '"') {
-              $match[2] = substr($match[2], 1, -1);
-              $phrase = true;
-            }
-            $words = trim($match[2], ',?!();:-');
-            $words = $phrase ? array($words) : preg_split('/ /', $words, -1, PREG_SPLIT_NO_EMPTY);
-            foreach ($words as $word) {
-              $where[] = "UPPER(%s) LIKE UPPER('%%%s%%')";
-              $values[] = $field;
-              $values[] = trim($word, " ,!?");
-            }
-          }
-          if ($filter['operator'] == 'word') {
-            $where = '('. implode(' OR ', $where) .')';
-          }
-          else {
-            $where = implode(' AND ', $where);
-          }
-          // previously this was a call_user_func_array but that's unnecessary
-          // as views will unpack an array that is a single arg.
-          $query->add_where($where, $values);
-          break;
-        case 'starts':
-          $query->add_where("UPPER(%s) LIKE UPPER('%s%%')",
-            $field, $filter['value']);
-          break;
-        case 'ends':
-          $query->add_where("UPPER(%s) LIKE UPPER('%%%s')",
-            $field, $filter['value']);
-          break;
-        case 'not':
-          $query->add_where("UPPER(%s) NOT LIKE UPPER('%%%s%%')",
-            $field, $filter['value']);
-          break;
-        case '=':
-          $query->add_where("UPPER(%s) = UPPER('%s')",
-            $field, $filter['value']);
-          break;
-      }
-    break;
-  }
-}
-
-/**
- * Format a field as file size.
- */
-function views_handler_field_filesize($fieldinfo, $fielddata, $value, $data) {
-  return format_size($value);
-}
-
-/**
- * Handle a timestamp filter.
- */
-function views_handler_filter_timestamp($op, $filter, $filterinfo, &$query) {
-  $value = $filter['value'] == 'now' ? "***CURRENT_TIME***" : strtotime($filter['value']);
-
-  $table = $filterinfo['table'];
-  $column = $filterinfo['field'];
-  $field = "$table.$column";
-  if ($filterinfo['from_unixtime']) {
-    $field = "from_UNIXTIME($field)";
-  }
-  $query->ensure_table($table);
-  $query->add_where("%s %s %s + %d", $field, $filter['operator'], $value, $filter['options']);
+  $output .= "book_parent: $book_parent\n";
+  $output .= "book_parent_users: $book_parent_users\n";
+  $output .= "book_parent_parent: $book_parent_parent\n";
+  $output .= "book_parent_parent_users: $book_parent_parent_users\n";
+*/
+  $output .= var_export($query, 1);
+  $output .= '
'; + return $output; } /** - * Provide a form gadget for dates. - */ -function views_handler_filter_date_value_form() { - return array( - '#type' => 'textfield', - '#attributes' => array('class' => 'jscalendar'), - ); -} -/** - * Substitute current time; this works with cached queries. + * Include view.inc */ -function views_views_query_substitutions($view) { - global $user; - return array('***CURRENT_TIME***' => time()); +function views_include_view() { + require_once drupal_get_path('module', 'views') . '/includes/view.inc'; } /** - * Returns a themed view. - * @param $view_name - * The name of the view. - * @param $limit - * Maximum number of nodes displayed on one page. if $limit is set and $use_pager is - * not, this will be the maximum number of records returned. This is ignored - * if using a view set to return a random result. - * If NULL, the setting defined for the $view will be used. - * @param $use_pager - * If set, use a pager. Set this to the pager id you want it to use if you - * plan on using multiple pagers on a page. Note that the pager element id - * will be decremented in order to have the IDs start at 0. - * If NULL, the setting defined for the $view will be used. - * @param $type - * 'page' -- Produce output as a page, sent through theme. - * The only real difference between this and block is that - * a page uses drupal_set_title to change the page title. - * 'block' -- Produce output as a block, sent through theme. - * 'embed' -- Use this if you want to embed a view onto another page, - * and don't want any block or page specific things to happen to it. - * @param $view_args - * An array containing the arguments for the view + * Include query.inc */ -function theme_view($view_name, $limit = NULL, $use_pager = NULL, $type = 'embed', $view_args = array()) { - if ($view = views_get_view($view_name)) { - $use_pager = isset($use_pager) ? $use_pager : $view->use_pager; - $limit_default = ($type == 'block') ? $view->nodes_per_block : $view->nodes_per_page; - $limit = isset($limit) ? $limit : $limit_default; - return views_build_view($type, $view, $view_args, $use_pager, $limit); - } +function views_include_query() { + require_once drupal_get_path('module', 'views') . '/includes/query.inc'; } - -/** - * This function is used as a central place to manage some translatable text strings - * that are used in different places. - * @param $text - * which string to return. - */ -function views_t_strings($text) { - switch ($text) { - case 'filter date': - return t('The "Value" can either be a date in the format: CCYY-MM-DD HH:MM:SS or the word "now" to use the current time. You may enter a positive or negative number in the "Option" field that will represent the amount of seconds that will be added or substracted to the time; this is most useful when combined with "now". If you have the jscalendar module from jstools installed, you can use a popup date picker here.'); - } -} +function views_get_table_join($table, $primary_table) { + // temp hack + static $cache = array(); + if (empty($cache)) { + $cache['users'] = new views_join('users', 'node', 'uid', 'uid'); + $cache['term_node'] = new views_join('term_node', 'node', 'nid', 'nid'); + $cache['term_data'] = new views_join('term_data', 'term_node', 'tid', 'tid'); + $cache['term_data_x'] = new views_join('term_data', 'term_hierarchy', 'tid', 'tid'); + $cache['term_hierarchy'] = new views_join('term_hierachy', 'term_node', 'tid', 'tid'); + $cache['book'] = new views_join('book', 'node', 'nid', 'nid'); + $cache['foo'] = new views_join('foo', 'node', 'nid', 'nid'); + $cache['bar'] = new views_join('bar', 'foo', 'baz', 'baz'); + } + +// if ($table == 'node') { drupal_set_message('
'.var_export(debug_backtrace(), 1)); }
+  return $cache[$table];
+}
\ No newline at end of file
diff --git a/views.schema b/views.schema
new file mode 100644
index 0000000000000000000000000000000000000000..98368f3da7b08c0e11dc3098c934e0644ba4c340
--- /dev/null
+++ b/views.schema
@@ -0,0 +1,388 @@
+ t('Stores the general data for a view.'),
+    'fields' => array(
+      'vid' => array(
+        'type' => 'serial', 
+        'unsigned' => TRUE, 
+        'not null' => TRUE, 
+        'description' => t('The view ID of the field, defined by the database.'),
+      ),
+      'name' => array(
+        'type' => 'varchar', 
+        'length' => '32', 
+        'default' => '',
+        'not null' => TRUE, 
+        'description' => t('The unique name of the view. This is the primary field views are loaded from, and is used so that views may be internal and not necessarily in the database. May only be alphanumeric characters plus underscores.'),
+      ),
+      'description' => array(
+        'type' => 'varchar', 
+        'length' => '255', 
+        'default' => '',
+        'description' => t('A description of the view for the admin interface.'),
+      ),
+      'view_php' => array(
+        'type' => 'blob', 
+        'default' => '',
+        'description' => t('A chunk of PHP code that can be used to provide modifications to the view prior to building.'),
+      ),
+      'base_table' => array(
+        'type' => 'varchar', 
+        'length' => '32', 
+        'default' => '',
+        'not null' => TRUE, 
+        'description' => t('What table this view is based on, such as node, user, comment, or term.'),
+      ),
+      'is_cacheable' => array(
+        'type' => 'int', 
+        'default' => 0,
+        'size' => 'tiny',
+        'description' => t('A boolean to indicate whether or not this view may have its query cached.'),
+      ),
+    ),
+    'primary key' => array('vid'),
+    'unique key' => array('name' => array('name')),
+  );
+
+  $schema['views_displays'] = array(
+    'description' => t('Stores information about each display attached to a view.'),
+    'fields' => array(
+      'vid' => array(
+        'type' => 'int', 
+        'unsigned' => TRUE, 
+        'not null' => TRUE, 
+        'default' => 0,
+        'description' => t('The view this display is attached to.'),
+      ),
+      'type' => array(
+        'type' => 'varchar', 
+        'length' => '64', 
+        'default' => '',
+        'not null' => TRUE, 
+        'description' => t('The type of the display. Usually page, block or embed, but is pluggable so may be other things.'),
+      ),
+      'access' => array(
+        'type' => 'varchar',
+        'length' => 255,
+        'description' => t('A serialized array describing who can access this display of the view.'),
+        'serialize' => TRUE,
+      ),
+      'output_type' => array(
+        'type' => 'varchar', 
+        'length' => '64', 
+        'default' => '',
+        'not null' => TRUE, 
+        'description' => t('The output type of the display. Usually list, table, teasers or nodes, but is pluggable so may be other things.'),
+      ),
+      'title' => array(
+        'type' => 'varchar', 
+        'length' => '255', 
+        'default' => '',
+        'not null' => TRUE, 
+        'description' => t('The title to use for this display.'),
+      ),
+      'header' => array(
+        'type' => 'blob', 
+        'description' => t('Text to display for the header.'),
+      ),
+      'header_format' => array(
+        'type' => 'int',
+        'description' => t('The output format for the header.'),
+      ),
+      'header_hide_empty' => array(
+        'type' => 'int', 
+        'default' => 1,
+        'size' => 'tiny',
+        'description' => t('If true, hide the header when the view has no records to display.'),
+      ),
+      'footer' => array(
+        'type' => 'blob', 
+        'description' => t('Text to display for the footer.'),
+      ),
+      'footer_format' => array(
+        'type' => 'int',
+        'description' => t('The output format for the footer.'),
+      ),
+      'footer_hide_empty' => array(
+        'type' => 'int', 
+        'default' => 1,
+        'size' => 'tiny',
+        'description' => t('If true, hide the footer when the view has no records to display.'),
+      ),
+      'empty' => array(
+        'type' => 'blob', 
+        'description' => t('Text to display if the view produces no records.'),
+      ),
+      'empty_format' => array(
+        'type' => 'int',
+        'description' => t('The output format for the empty text.'),
+      ),
+      'use_pager' => array(
+        'type' => 'int', 
+        'default' => 1,
+        'size' => 'tiny',
+        'description' => t('If true, this display will utilize the pager.'),
+      ),
+      'url' => array(
+        'type' => 'varchar', 
+        'length' => '255', 
+        'description' => t('The URL of the display, if applicable.'),
+      ),
+      'position' => array(
+        'type' => 'int', 
+        'default' => 0,
+        'description' => t('The order in which this display is loaded.'),
+      ),
+      'display_options' => array(
+        'type' => 'blob', 
+        'description' => t('A serialized array of options for this display; it contains options that are generally only pertinent to that display type.'),
+        'serialize' => TRUE,
+      ),
+      'output_options' => array(
+        'type' => 'blob', 
+        'description' => t('A serialized array of options for this display\'s output type; it contains options that are generally only pertinent to that type.'),
+        'serialize' => TRUE,
+      ),
+      'filter_options' => array(
+        'type' => 'blob', 
+        'description' => t('A serialized array of options for this display\'s exposed filters.'),
+        'serialize' => TRUE,
+      ),      
+    ),
+    'indexes' => array('vid' => array('vid', 'position')),
+  );
+
+  $schema['views_arguments'] = array(
+    'description' => t('Stores information about each argument attached to a view.'),
+    'fields' => array(
+      'vid' => array(
+        'type' => 'int', 
+        'unsigned' => TRUE, 
+        'not null' => TRUE, 
+        'default' => 0,
+        'description' => t('The view this display is attached to.'),
+      ),
+      'position' => array(
+        'type' => 'int', 
+        'default' => 0,
+        'description' => t('The order in which this information is loaded.'),
+      ),
+      'type' => array(
+        'type' => 'varchar', 
+        'length' => '64', 
+        'default' => '',
+        'not null' => TRUE, 
+        'description' => t('The type of the display. Usually page, block or embed, but is pluggable so may be other things.'),
+      ),
+      'default_action' => array(
+        'type' => 'varchar', 
+        'length' => '32', 
+        'default' => '',
+        'not null' => TRUE, 
+        'description' => t('What to do if this argument is not present.'),
+      ),
+      'title' => array(
+        'type' => 'varchar', 
+        'length' => '255', 
+        'default' => '',
+        'not null' => TRUE, 
+        'description' => t('The title to use if this argument is present.'),
+      ),
+      'wildcard' => array(
+        'type' => 'varchar', 
+        'length' => '32', 
+        'default' => '*',
+        'description' => t('What to use for a wildcard in the URL for this argument.'),
+      ),
+      'wildcard_text' => array(
+        'type' => 'varchar', 
+        'length' => '64',
+        'default' => t('All'),
+        'description' => t('The textual representation of the argument, for use in titles. For example, if the argument is *, the text represnation might be "all".'),
+      ),
+      'options' => array(
+        'type' => 'blob', 
+        'description' => t('A serialized array of options for this field.'),
+        'serialize' => TRUE,
+      ),      
+    ),
+    'indexes' => array('vid' => array('vid', 'position')),
+  );
+
+  $schema['views_fields'] = array(
+    'description' => t('Stores information about each field attached to a view.'),
+    'fields' => array(
+      'vid' => array(
+        'type' => 'int', 
+        'unsigned' => TRUE, 
+        'not null' => TRUE, 
+        'default' => 0,
+        'description' => t('The view this display is attached to.'),
+      ),
+      'position' => array(
+        'type' => 'int', 
+        'default' => 0,
+        'description' => t('The order in which this information is loaded.'),
+      ),
+      'table' => array(
+        'type' => 'varchar', 
+        'length' => '255', 
+        'description' => t('The name of the table this field is attached to.'),
+      ),
+      'field' => array(
+        'type' => 'varchar', 
+        'length' => '255', 
+        'description' => t('The name of the field.'),
+      ),
+      'handler' => array(
+        'type' => 'varchar', 
+        'length' => '255', 
+        'description' => t('Which handler to use.'),
+      ),
+      'options' => array(
+        'type' => 'blob', 
+        'description' => t('A serialized array of options for this field.'),
+        'serialize' => TRUE,
+      ),      
+    ),
+    'indexes' => array('vid' => array('vid', 'position')),
+  );
+
+  $schema['views_sorts'] = array(
+    'description' => t('Stores information about each sort criterion attached to a view.'),
+    'fields' => array(
+      'vid' => array(
+        'type' => 'int', 
+        'unsigned' => TRUE, 
+        'not null' => TRUE, 
+        'default' => 0,
+        'description' => t('The view this display is attached to.'),
+      ),
+      'position' => array(
+        'type' => 'int', 
+        'default' => 0,
+        'description' => t('The order in which this information is loaded.'),
+      ),
+      'table' => array(
+        'type' => 'varchar', 
+        'length' => '255', 
+        'description' => t('The name of the table this field is attached to.'),
+      ),
+      'field' => array(
+        'type' => 'varchar', 
+        'length' => '255', 
+        'description' => t('The name of the field.'),
+      ),
+      'order' => array(
+        'type' => 'varchar', 
+        'length' => '4', 
+        'description' => t('Either ASC or DESC.'),
+      ),
+      'options' => array(
+        'type' => 'blob', 
+        'description' => t('A serialized array of options for this field.'),
+        'serialize' => TRUE,
+      ),      
+      'exposed' => array(
+        'type' => 'int', 
+        'default' => 0,
+        'size' => 'tiny',
+        'description' => t('True if this sort is exposed in the UI.'),
+      ),
+      'exposed_options' => array(
+        'type' => 'blob', 
+        'description' => t('A serialized array of options for exposed sorts.'),
+        'serialize' => TRUE,
+      ),      
+    ),
+    'indexes' => array('vid' => array('vid', 'position')),
+  );
+
+  $schema['views_filters'] = array(
+    'description' => t('Stores information about each filter attached to a view.'),
+    'fields' => array(
+      'vid' => array(
+        'type' => 'int', 
+        'unsigned' => TRUE, 
+        'not null' => TRUE, 
+        'default' => 0,
+        'description' => t('The view this display is attached to.'),
+      ),
+      'position' => array(
+        'type' => 'int', 
+        'default' => 0,
+        'description' => t('The order in which this information is loaded.'),
+      ),
+      'group' => array(
+        'type' => 'int', 
+        'default' => 0,
+        'description' => t('Which filter group this filter belongs to, so that AND and OR can be separated properly.'),
+      ),
+      'table' => array(
+        'type' => 'varchar', 
+        'length' => '255', 
+        'description' => t('The name of the table this field is attached to.'),
+      ),
+      'field' => array(
+        'type' => 'varchar', 
+        'length' => '255', 
+        'description' => t('The name of the field.'),
+      ),
+      'operator' => array(
+        'type' => 'varchar', 
+        'length' => '255', 
+        'description' => t('The operator for this filter. For example, == or > or <.'),
+      ),
+      'value' => array(
+        'type' => 'varchar', 
+        'length' => '255', 
+        'description' => t('The value being tested for this filter.'),
+        'serialize' => TRUE,
+      ),
+      'options' => array(
+        'type' => 'blob', 
+        'description' => t('A serialized array of options for this field.'),
+        'serialize' => TRUE,
+      ),      
+      'exposed' => array(
+        'type' => 'int', 
+        'default' => 0,
+        'size' => 'tiny',
+        'description' => t('True if this filter is exposed in the UI.'),
+      ),
+      'exposed_options' => array(
+        'type' => 'blob', 
+        'description' => t('A serialized array of options for exposed filters.'),
+        'serialize' => TRUE,
+      ),      
+    ),
+    'indexes' => array('vid' => array('vid', 'position')),
+  );
+
+  // This is unfortunately cut & pasted from system.module since cache has no way of
+  // telling us what the proper schema is.
+  $schema['cache_views'] = array(
+    'fields' => array(
+      'cid'        => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''),
+      'data'       => array('type' => 'blob', 'not null' => FALSE, 'size' => 'big'),
+      'expire'     => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
+      'created'    => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
+      'headers'    => array('type' => 'text', 'not null' => FALSE),
+      'serialized' => array('type' => 'int', 'size' => 'small', 'not null' => TRUE, 'default' => 0)
+    ),
+    'indexes' => array('expire' => array('expire')),
+    'primary key' => array('cid'),
+  );
+
+  return $schema;
+}
diff --git a/views_cache.inc b/views_cache.inc
deleted file mode 100644
index b1ec38bc0411e168ef075e016615cc2597805306..0000000000000000000000000000000000000000
--- a/views_cache.inc
+++ /dev/null
@@ -1,284 +0,0 @@
-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) {
-    $data = cache_get("views_default_views:$locale", 'cache');
-    $cache = unserialize($data->data);
-
-    if (is_array($cache)) {
-      $views_default_views = $cache;
-    }
-    else {
-      // We have to make sure table data is built in order to be sure about providers.
-      $tables = array_keys(_views_get_tables());
-
-      $views = module_invoke_all('views_default_views');
-      uasort($views, '_views_sort_arrays');
-      $views_default_views = array();
-      foreach ($views as $i => $view) {
-        if (!is_array($view->requires) || !array_diff($view->requires, $tables)) {
-          views_sanitize_view($view);
-          $views_default_views[$i] = $view;
-        }
-      }
-      cache_set("views_default_views:$locale", 'cache', serialize($views_default_views));
-    }
-  }
-  return $views_default_views;
-}
-
-/**
- * sort callback
- */
-function _views_sort_arrays($a, $b) {
-  $a = (array) $a; // safety -- something send objects.
-  $b = (array) $b;
-  if ($a['weight'] == $b['weight']) {
-    if ($a['name'] == $b['name']) {
-      return 0;
-    }
-    return ($a['name'] < $b['name']) ? -1 : 1;
-  }
-  return ($a['weight'] > $b['weight']) ? -1 : 1;
-}
-
-/**
- * Return the style plugins; construct one if we haven't already. The
- * array is cached in a static variable so that arguments
- * are only constructed once per run.
- */
-function _views_get_style_plugins($titles = false) {
-  static $views_style_plugins;
-  global $locale;
-
-  if (!$views_style_plugins) {
-    $data = cache_get("views_style_plugins:$locale", 'cache');
-    $cache = unserialize($data->data);
-    if (is_array($cache)) {
-      $views_style_plugins = $cache;
-    }
-    else {
-      $arguments = module_invoke_all('views_style_plugins');
-      uasort($arguments, '_views_sort_arrays');
-      foreach ($arguments as $name => $arg) {
-        if (!isset($arg['summary_theme'])) {
-          $arg['summary_theme'] = 'views_summary';
-        }
-        $views_style_plugins['title'][$name] = $arg['name'];
-        $views_style_plugins['base'][$name] = $arg;
-      }
-      $cache = $views_style_plugins;
-      cache_set("views_style_plugins:$locale", 'cache', serialize($cache));
-    }
-  }
-  return ($titles ? $views_style_plugins['title'] : $views_style_plugins['base']);
-}
-
diff --git a/views_query.inc b/views_query.inc
deleted file mode 100644
index c6a0e19f45f3d6bf83fdfced5466b81383cd6132..0000000000000000000000000000000000000000
--- a/views_query.inc
+++ /dev/null
@@ -1,655 +0,0 @@
-use_alias_prefix) ? $view->use_alias_prefix : '');
-
-  // Process static filters
-  _views_view_build_filters($query, $view);
-
-  // Process arguments.
-  $view->args = $args; // we'll need these later.
-
-  foreach ($view->argument as $i => $argument) {
-    if ($args[$i] != NULL && $args[$i] != '' && $args[$i] != '$arg') {
-      _views_view_build_arg($query, $args[$i], $argument);
-    }
-    else {
-      // This is what we do if we expected an arg but we didn't get it.
-      switch ($argument['argdefault']) {
-        case 1:
-          $info['fail'] = TRUE;
-          return $info;
-        case 3:
-        case 4:
-          $self_sort = "ASC";
-        case 5:
-          // the if is a kind of a hack to make this case fall-thru fluid
-          if (!$self_sort) {
-            $self_sort = "DESC";
-        }
-        case 6:
-          $level = $i;
-          _views_build_summary($query, $argument['type'], $argument['options'], $self_sort);
-          $summary = true;
-          if (!$self_sort) {
-            $sort = true;
-          }
-          break 2; // switch and for
-        case 7:
-          // to trigger empty text, send back an empty query
-          $info['query'] = NULL;
-          return $info;
-      }
-    }
-  }
-
-  if (!$summary || $sort) {
-    _views_view_build_sorts($query, $view);
-    $plugins = _views_get_style_plugins();
-    if (($view->page && ($plugins[$view->page_type]['needs_fields'])) ||
-      ($view->block && ($plugins[$view->block_type]['needs_fields']))) {
-      _views_view_build_fields($query, $view);
-    }
-  }
-
-  foreach (module_implements('views_query_alter') as $module) {
-    $function = $module .'_views_query_alter';
-    $results = $function($query, $view, $summary, $level);
-  }
-
-  $info['query'] = $query->query();
-  $info['countquery'] = $query->query(true);
-  $info['summary'] = $summary;
-  $info['level'] = $level;
-  $info['args'] = $query->where_args;
-
-  return $info;
-
-}
-
-/*
- * Take all the filters in a view and add them to the query object.
- */
-function _views_view_build_filters(&$query, &$view) {
-  $filters = _views_get_filters();
-  $view->used_filters = array();
-
-  foreach ($view->filter as $i => $filter) {
-    $filterinfo = $filters[$filter['field']]; // shortcut
-    $field = $filterinfo['field'];
-    if (!$field) {
-      $fieldbits = explode('.', $filter['field']);
-      $field = $fieldbits[1];
-    }
-    $filterinfo['field'] = $field;
-
-    foreach($view->exposed_filter as $count => $expose) {
-      if ($filter['id'] == $expose['id']) {
-        $id = $expose['id'];
-
-        if (isset($view->exposed_filter_offset)) {
-          $count += $view->exposed_filter_offset;
-        }
-
-        if (!$expose['operator'] && $_GET["op$count"]) {
-          $filter['operator'] = check_plain($_GET["op$count"]);
-          $view->used_filters["op$count"] = $_GET["op$count"];
-        }
-
-        if ($expose['optional']) {
-          if ((!isset($_GET["filter$count"]) || $_GET["filter$count"] == '') && !$expose['is_default']) {
-            continue 2; // skip
-          }
-          if ($_GET["filter$count"] == '**ALL**' ||
-            (is_array($_GET["filter$count"]) && in_array('**ALL**', $_GET["filter$count"]))) {
-            $view->used_filters["filter$count"] = $_GET["filter$count"];
-            continue 2; // skip this filter entirely.
-          }
-        }
-        if (isset($_GET["filter$count"]) && $_GET["filter$count"] != '') {
-          $value = $_GET["filter$count"];
-          if ($filterinfo['value-type'] == 'array' && !is_array($value)) {
-            $value = array($value);
-          }
-          $filter['value'] = $value;
-          $view->used_filters["filter$count"] = $_GET["filter$count"];
-        }
-        break;
-      }
-    }
-    $table = $filterinfo['table'];
-
-    $replace = array('>' => '>', '<' => '<');
-    $filter['operator'] = strtr($filter['operator'], $replace);
-
-    if (function_exists($filterinfo['handler'])) {
-      $filterinfo['handler']('handler', $filter, $filterinfo, $query);
-    }
-    else if (is_array($filter['value']) && count($filter['value'])) {
-      if ($filter['operator'] == 'OR' || $filter['operator'] == 'NOR') {
-        $query->ensure_table($table);
-        $where_args = array_merge(array($query->use_alias_prefix . $table, $field), $filter['value']);
-        $placeholder = array_fill(0, count($filter['value']), '%s');
-        if ($filter['operator'] == 'OR') {
-          $query->add_where("%s.%s IN ('". implode("','", $placeholder) ."')", $where_args);
-        }
-        else {
-          $where_args[] = $where_args[0];
-          $where_args[] = $where_args[1];
-          $query->add_where("(%s.%s NOT IN ('". implode("','", $placeholder) ."') OR %s.%s IS NULL)", $where_args);
-        }
-      }
-      else {
-        $howmany = count($filter['value']);
-        $high_table = $query->add_table($table, true, $howmany);
-        if (!$high_table) { // couldn't add the table
-          break;
-        }
-
-        $table_num = $high_table - $howmany;
-        foreach ($filter['value'] as $item) {
-          $table_num++;
-          $tn = $query->get_table_name($table, $table_num);
-          $query->add_where("%s.%s = '%s'", $tn, $field, $item);
-        }
-      }
-    }
-    else {
-      $query->ensure_table("$table");
-      $query->add_where("%s.%s %s '%s'", $query->use_alias_prefix . $table, $field, $filter['operator'], $filter['value']);
-    }
-  }
-}
-
-/*
- * Add argument data to a view; mostly passes through to handlers.
- */
-function _views_view_build_arg(&$query, $arg, $argdata) {
-  $arginfo = _views_get_arguments();
-  if (!function_exists($arginfo[$argdata['type']]['handler'])) {
-    return false;
-  }
-
-  // call the handler, unless the arg is the 'wildcard'.
-  if ($arg != $argdata['wildcard']) {
-    $arginfo[$argdata['type']]['handler']('filter', $query, $argdata, $arg);
-  }
-}
-
-/*
- * Add sorting information from a view to a query.
- */
-function _views_view_build_sorts(&$query, $view) {
-  $sorts = _views_get_sorts();
-
-  foreach ($view->sort as $i => $sort) {
-    $sortinfo = $sorts[$sort['field']];
-    $field = $sortinfo['field'];
-
-    if (!$field) {
-      $fieldbits = explode('.', $sort['field']);
-      $field = $fieldbits[1];
-    }
-    $table = $sortinfo['table'];
-    if (isset($sortinfo['handler']) && function_exists($sortinfo['handler'])) {
-      $sortinfo['field'] = $field;
-      $sortinfo['handler']('sort', $query, $sortinfo, $sort);
-    }
-    else {
-      $query->add_orderby($table, $field, $sort['sortorder']);
-    }
-  }
-}
-
-/*
- * Add field information from a view to a query.
- */
-function _views_view_build_fields(&$query, &$view) {
-  $fields = _views_get_fields();
-
-  foreach ($view->field as $field) {
-    // Some fields are not actually fields but require special handlers
-    // to display their data.
-
-    $fieldname = $field['fullname']; // combined table & fieldname
-    $fieldinfo = $fields[$fieldname]; // laziness + readability
-
-    if (isset($fieldinfo['query_handler']) && function_exists($fieldinfo['query_handler'])) {
-      $fieldinfo['query_handler']($field, $fieldinfo, $query);
-    }
-
-    if (!$fieldinfo['notafield']) {
-      if ($fieldinfo['field']) {
-        $query->add_field($fieldinfo['field'], $field['tablename'], $field['queryname']);
-      }
-      else {
-        $query->add_field($field['field'], $field['tablename'], $field['queryname']);
-      }
-    }
-    // special handling
-    if (is_array($fieldinfo['addlfields'])) {
-      foreach ($fieldinfo['addlfields'] as $name)
-        $query->add_field($name, $field['tablename'], "$field[tablename]_$name");
-    }
-  }
-  $plugins = _views_get_style_plugins();
-  if (($view->page && $plugins[$view->page_type]['needs_table_header']) ||
-      ($view->block && $plugins[$view->block_type]['needs_table_header'])) { // table only
-    $view->table_header = _views_construct_header($view, $fields);
-    $query->set_header($view->table_header);
-  }
-}
-
-/*
- * Build a summary if an argument was required and is not present. Mostly
- * this calls handlers.
- */
-function _views_build_summary(&$query, $argtype, $option, $self_sort) {
-  $arginfo = _views_get_arguments();
-  if (!function_exists($arginfo[$argtype]['handler'])) {
-    return false;
-  }
-  $primary_field = $query->fields[0];
-  $query->clear_fields();
-
-  $fieldinfo = $arginfo[$argtype]['handler']('summary', $query, $argtype, $option);
-
-  if ($fieldinfo['fieldname']) {
-    $query->add_field($fieldinfo[field], '', $fieldinfo[fieldname]);
-  }
-  $query->add_field("count($primary_field)", '', 'num_nodes');
-  $query->add_groupby($fieldinfo['field']);
-  $query->set_count_field("DISTINCT($fieldinfo[field])");
-  if ($self_sort) {
-    $arginfo[$argtype]['handler']('sort', $query, $self_sort);
-  }
-  $query->no_distinct = TRUE; // prevent DISTINCT from mucking up summaries.
-}
-
-// ---------------------------------------------------------------------------
-// Query construction object
-
-class _views_query {
-
-  /*
-   * Create the basic query object and fill with default values.
-   */
-  function _views_query($primary_table = 'node', $primary_field = 'nid', $alias_prefix = '') {
-    $this->primary_table = $primary_table;
-    $this->joins = array();
-    $this->where = array();
-    $this->orderby = array();
-    $this->groupby = array();
-    $this->tables = array();
-    $this->where_args = array();
-    $this->use_alias_prefix = $alias_prefix;
-    // Joins care about order, so we put our tables in a queue to make sure
-    // the order is correct.
-    $this->tablequeue = array();
-    if ($primary_field) {
-      $this->fields = array($alias_prefix ."$primary_table.$primary_field");
-    }
-    $this->count_field = $alias_prefix ."$primary_table.$primary_field";
-    $this->header = array();
-  }
-
-  /*
-   * Add a field to the query table, possibly with an alias. This will
-   * automatically call ensure_table to make sure the required table
-   * exists, *unless* $table is unset.
-   */
-  function add_field($field, $table = '$$', $alias = '') {
-    if ($table == '$$') {
-      // I picked $$ because it's not a legal name for a table and NULL is
-      // actually a valid possibility here, and I can't default to a variable.
-      $table = $this->primary_table;
-    }
-
-    // We check for this specifically because we don't want to add it aliased.
-    if ($table == $query->primary_table && $field == $view->primary_field) {
-      return;
-    }
-
-    if ($table) {
-      $this->ensure_table($table);
-      $table = $this->use_alias_prefix . $table .".";
-    }
-
-    if ($alias) {
-      $a = " AS $this->use_alias_prefix$alias";
-    }
-
-    if (!in_array("$table$field$a", $this->fields)) {
-      $this->fields[] = "$table$field$a";
-    }
-  }
-
-  /*
-   * Set the base field to be distinct.
-   */
-  function set_distinct() {
-    if (count($this->fields) && substr($this->fields[0], 0, 8) != 'DISTINCT') {
-      $field = $this->fields[0];
-      $this->fields[0] = "DISTINCT($field)";
-      $this->count_field = "DISTINCT($field)";
-    }
-  }
-  /*
-   * Remove all fields that may've been added; primarily used for summary
-   * mode where we're changing the query because we didn't get data we needed.
-   */
-  function clear_fields() {
-    $this->fields = array();
-  }
-
-  /*
-   * Set what field the query will count() on for paging.
-   */
-  function set_count_field($field) {
-    $this->count_field = $field;
-  }
-
-  /*
-   * Add a simple WHERE clause to the query. The caller is responsible for
-   * ensuring that all fields are fully qualified (TABLE.FIELD) and that
-   * the table already exists in the query.
-   */
-  function add_where($clause) {
-    $args = func_get_args();
-    array_shift($args); // ditch $clause
-
-    if (count($args) == 1 && is_array(reset($args))) {
-      $args = current($args);
-    }
-    if (is_array($args)) {
-      $this->where[] = $clause;
-      $this->where_args = array_merge($this->where_args, $args);
-    }
-  }
-
-  /*
-   * Add multiple an orderby's. Right now I'm not sure why this function
-   * is separate from add_orderby above; I don't think it needs to
-   * be.
-   *
-   * NOTE: $alias doesn't work when adding multiple orderbys.
-   */
-  function add_orderby($table, $field, $order, $alias = '') {
-    if (!$alias && $table) {
-      $alias = $this->use_alias_prefix . $table;
-    }
-    elseif ($alias) {
-      $alias = $this->use_alias_prefix . $alias;
-    }
-
-    if ($table) {
-      $this->ensure_table($table);
-    }
-
-    if (!is_array($field)) {
-      $field = array($field);
-    }
-
-    foreach($field as $f) {
-      // Only fill out this aliasing if there is a table;
-      // otherwise we assume it is a formula.
-      if ($table) {
-        $as = $alias . '_' . $f;
-      }
-      else {
-        $as = $alias;
-      }
-      $this->add_field($f, $table, $as);
-      $this->orderby[] = "$as $order";
-    }
-  }
-
-  /*
-   * Add a simple GROUP BY clause to the query. The caller is responsible
-   * for ensuring that the fields are fully qualified and the table is properly
-   * added.
-   */
-  function add_groupby($clause) {
-    $this->groupby[] = $clause;
-  }
-
-  /*
-   * This function will ensure a table exists; if it already exists it won't
-   * do anything, but if it doesn't it will add the table queue. It will ensure
-   * a path leads back to the views_get_title table.
-   */
-  function ensure_table($table) {
-    if ($table == $this->primary_table || $this->tables[$table]) {
-      return;
-    }
-
-    if ($this->ensure_path($table)) {
-      $this->queue_table($table);
-    }
-  }
-
-  /*
-   * This function will add a table to the query.
-   *
-   * @param $table
-   *   The name of the table to add. It needs to exist in the global table
-   *   array.
-   * @param $ensure_path
-   *   If true, it will ensure that a path back to primary_table exists. If false, it
-   *   assumes the caller is already sure about this and does not repeat it.
-   * @param $howmany
-   *   How many instances of the table to add? (Useful for interesting join
-   *   combos)
-   * @param $joininfo
-   *   In some join configurations this table may actually join back through
-   *   a different method; this is most likely to be used when tracing
-   *   a hierarchy path. (node->parent->parent2->parent3). This parameter
-   *   will specify how this table joins if it is not the default.
-   */
-  function add_table($table, $ensure_path = false, $howmany = 1, $joininfo = NULL) {
-    if ($table == $this->primary_table) {
-      return;
-    }
-
-    if ($ensure_path && !$this->ensure_path($table)) {
-      return false;
-    }
-
-    $this->tables[$table] += $howmany;
-
-    for ($i = $this->tables[$table] - $howmany + 1; $i <= $this->tables[$table]; $i++) {
-      if ($joininfo) {
-        $this->joins[$table][$i] = $joininfo;
-      }
-      $this->tablequeue[] = array('table' => $table, 'num' => $i, 'alias_prefix' => $this->use_alias_prefix);
-    }
-    return $this->tables[$table];
-  }
-
-  /*
-   * Add a table to the queue in the specified position. This is a low level
-   * operation and should only be performed after all safety checking has been done.
-   */
-  function queue_table($table) {
-    if (!isset($this->tables[$table])) {
-      $this->tables[$table] = 1;
-    }
-    else {
-      $this->tables[$table]++;
-    }
-    $this->tablequeue[] = array('table' => $table, 'num' => $this->tables[$table], 'alias_prefix' => $this->use_alias_prefix);
-  }
-
-  /*
-   * Set the table header; used for click-sorting because it's needed
-   * info to modify the ORDER BY clause.
-   */
-  function set_header($header) {
-    $this->header = $header;
-  }
-
-  /*
-   * Make sure that the specified table can be properly linked to the views_get_title
-   * table in the JOINs. This function uses recursion. If the tables
-   * needed to complete the path back to the views_get_title table are not in the
-   * query they will be added, but additional copies will NOT be added
-   * if the table is already there.
-   */
-  function ensure_path($table, $traced = array(), $add = array()) {
-    if ($table == $this->primary_table) {
-      return true;
-    }
-    $table_data = _views_get_tables();
-
-    $left_table = $table_data[$table]['join']['left']['table'];
-
-    // Does it end at our views_get_title table?
-    if ($left_table == $this->primary_table) {
-      // We are done! Add our tables and unwind.
-      foreach (array_reverse($add) as $table) {
-        $this->queue_table($table);
-      }
-      return true;
-    }
-
-    // Have we been this way?
-    if (isset($traced[$left_table])) {
-      // we looped. Broked.
-      return false;
-    }
-
-    // Do we have to add this table?
-    if (!isset($this->tables[$left_table])) {
-      $add[] = $left_table;
-    }
-
-    // Keep looking.
-    $traced[$left_table] = 1;
-    return $this->ensure_path($left_table, $traced, $add);
-  }
-
-  /*
-   * Return the alias of a given table in the JOIN queries. If a table is in
-   * the query multiple times, use this function to figure out what successive
-   * iterations of the table will be named.
-   *
-   * @param $table
-   *   The name of the table in the global table array.
-   * @param $table_num
-   *   The instance number of the table.
-   * @param $alias_prefix
-   *   An optional prefix for the table alias.
-   */
-  function get_table_name($table, $table_num, $alias_prefix = null) {
-    if (is_null($alias_prefix)) {
-      $alias_prefix = $this->use_alias_prefix;
-    }
-    return ($table_num < 2 ? $alias_prefix . $table : $alias_prefix . $table . $table_num);
-  }
-
-  /*
-   * Generate a query and a countquery from all of the information supplied
-   * to the object.
-   *
-   * @param $getcount
-   *   Provide a countquery if this is true, otherwise provide a normal query.
-   */
-  function query($getcount = false) {
-    $table_data = _views_get_tables();
-
-    // Add all the tables to the query via joins. We assume all LEFT joins.
-    foreach ($this->tablequeue as $tinfo) {
-      $table = $tinfo['table'];
-
-      // The real table name may differ from what we're calling it.
-      $table_real = (isset($table_data[$table]['name']) ? $table_data[$table]['name'] : $table);
-
-      $table_num = $tinfo['num'];
-      $table_alias = $this->get_table_name($table, $table_num, $tinfo['alias_prefix']);
-
-      $joininfo = (!$this->joins[$table][$table_num] ?
-        $table_data[$table]['join'] : $this->joins[$table][$table_num]);
-
-      $left_table_alias = isset($joininfo['left']['alias']) ? $joininfo['left']['alias'] : $tinfo['alias_prefix'];
-      $left_table_alias .= $joininfo['left']['table'];
-
-      // the { is a special character which seems to be treated differently
-      // in PHP5 than PHP4 so we do this a little oddly.
-      $join_type = $joininfo['type'] == 'inner' ? 'INNER' : 'LEFT';
-      $joins .= " $join_type JOIN {" . $table_real . "} $table_alias ON " . $left_table_alias .".".
-        $joininfo['left']['field'] . " = $table_alias." . $joininfo['right']['field'];
-
-      if (isset($joininfo['extra'])) {
-        foreach ($joininfo['extra'] as $field => $value) {
-          $joins .= " AND $table_alias.$field";
-          if (is_array($value) && count($value)) {
-            $joins .= " IN ('". implode("','", $value) ."')";
-          }
-          else if ($value !== NULL) {
-            $joins .= " = '$value'";
-          }
-        }
-      }
-    }
-
-    // If it's not a count query, add our fields
-    if (!$getcount) {
-      $fields = implode(', ', $this->fields);
-
-      // we only add the groupby if we're not counting.
-      if ($this->groupby) {
-        $groupby = "GROUP BY " . implode(', ', $this->groupby);
-      }
-
-      // ok, tablesort_sql is really, really (really) annoying.
-      // 1) it insists on adding the ORDER BY clause.
-      // 2) You're supposed to give it your stuff as $before, but
-      // 3) You have to add the comma and
-      // 4) if it doesn't have anything to add, it returns NOTHING.
-      // 5) So I'm just going to get what it sends back and chop off
-      //    the orderby, cause otherwise my code is too ugly with
-      //    various checks.
-      if ($this->header) {
-        $result = tablesort_sql($this->header);
-        if ($result) {
-          $this->orderby[] = str_replace('ORDER BY ', '', $result);
-        }
-      }
-
-      if ($this->orderby) {
-        $orderby = "ORDER BY " . implode(', ', $this->orderby);
-      }
-    }
-    else {
-      $fields = "count($this->count_field)";
-    }
-
-    if ($this->where) {
-      $where = "WHERE (" . implode(') AND (', $this->where) . ')';
-    }
-
-    $query = "SELECT $fields FROM {" . $this->primary_table . "} $this->primary_table $joins $where $groupby $orderby";
-
-    $replace = array('>' => '>', '<' => '<');
-    $query = strtr($query, $replace);
-
-    return $query;
-  }
-}
-
-/*
- * Support db_query() style argument replacement in a clause.
- */
-
-function _views_replace_args($clause, $args) {
-  // cut & pasted directly from db_query.
-  if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
-    $args = $args[0];
-  }
-  _db_query_callback($args, TRUE);
-  return preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $clause);
-}
diff --git a/views_rss.info b/views_rss.info
deleted file mode 100644
index c9619f444e47ed9f07e99c2759106831f0bdfb58..0000000000000000000000000000000000000000
--- a/views_rss.info
+++ /dev/null
@@ -1,5 +0,0 @@
-; $Id$
-name = Views RSS
-description = RSS plugin for the views feed selector argument.
-package = Views
-dependencies = views
diff --git a/views_rss.module b/views_rss.module
deleted file mode 100644
index b1a415b680c88aa2a0361d926135d46c20294075..0000000000000000000000000000000000000000
--- a/views_rss.module
+++ /dev/null
@@ -1,177 +0,0 @@
- array(
-      'name' => t('Views RSS: RSS feed'),
-      'theme' => 'views_rss_feed',
-      'needs_table_header' => TRUE,
-      'needs_fields' => TRUE,
-      'even_empty' => TRUE,
-    ),
-  );
-}
-
-/**
- * While we support the global selector, some might want to allow
- * ONLY RSS feeds so we support a stingy selector too
- */
-function views_rss_views_arguments() {
-  $arguments = array(
-    'rss_feed' => array(
-      'name' => t('RSS: RSS Feed Selector'),
-      'handler' => 'views_handler_arg_rss_feed',
-      'help' => t('This argument specifies a specific RSS feed selector; it will only select RSS feeds, unlike the built-in selector which can select pluggable feeds.'),
-    ),
-  );
-  return $arguments;
-}
-
-/**
- * handler for our own RSS argument; mimics the feed selector
- */
-function views_handler_arg_rss_feed($op, &$query, $argtype, $arg = '') {
-  switch($op) {
-    case 'summary':
-    case 'sort':
-    case 'link':
-    case 'title':
-      break;
-    case 'filter':
-      // This is a clone of the default selector, but it just invokes ours
-      // rather than calling all of them.
-      views_rss_views_feed_argument('argument', $GLOBALS['current_view'], $arg);
-  }
-}
-
-/**
- * post view for our own op -- mimics the feed selector
- */
-function views_rss_views_post_view($view, $items, $output) {
-  foreach ($view->argument as $id => $argument) {
-    if ($argument['type'] == 'rss_feed') {
-      $feed = $id;
-      break;
-    }
-  }
-
-  if ($feed !== NULL) {
-    return views_rss_views_feed_argument('post_view', $view, 'rss_feed');
-  }
-}
-
-/**
- * feed argument hook that will convert us to RSS or display an icon.
- * the 4th argument isn't part of the hook, but we use it to differentiate
- * when called as a hook or when called manually from views_rss_views_post_view
- */
-function views_rss_views_feed_argument($op, &$view, $arg) {
-  if ($op == 'argument' && $arg == 'feed') {
-    $view->page_type = 'views_rss';
-  }
-  else if ($op == 'post_view') {
-    $args = views_post_view_make_args($view, $arg, 'feed');
-    $url = views_get_url($view, $args);
-    $title = views_get_title($view, 'page', $args);
-
-    if ($view->used_filters) {
-      $filters = drupal_query_string_encode($view->used_filters);
-    }
-
-    drupal_add_feed(url($url, $filters), $title);
-  }
-}
-
-/**
- * plugin that actually displays an RSS feed
- */
-function theme_views_rss_feed($view, $nodes, $type) {
-  if ($type == 'block') {
-    return;
-  }
-  global $base_url;
-
-  $channel = array(
-    // a check_plain isn't required on these because format_rss_channel
-    // already does this.
-    'title'       => views_get_title($view, 'page'),
-    'link'        => url($view->real_url, NULL, NULL, true),
-    'description' => $view->description,
-  );
-
-  $item_length = variable_get('feed_item_length', 'teaser');
-  $namespaces = array('xmlns:dc="http://purl.org/dc/elements/1.1/"');
-
-  // Except for the original being a while and this being a foreach, this is
-  // completely cut & pasted from node.module.
-  foreach ($nodes as $node) {
-    // Load the specified node:
-    $item = node_load($node->nid);
-    $link = url("node/$node->nid", NULL, NULL, 1);
-
-    if ($item_length != 'title') {
-      $teaser = ($item_length == 'teaser') ? TRUE : FALSE;
-
-      // Filter and prepare node teaser
-      if (node_hook($item, 'view')) {
-        node_invoke($item, 'view', $teaser, FALSE);
-      }
-      else {
-        $item = node_prepare($item, $teaser);
-      }
-
-      // Allow modules to change $node->teaser before viewing.
-      node_invoke_nodeapi($item, 'view', $teaser, FALSE);
-    }
-
-    // Allow modules to add additional item fields
-    $extra = node_invoke_nodeapi($item, 'rss item');
-    $extra = array_merge($extra, array(array('key' => 'pubDate', 'value' =>  date('r', $item->created)), array('key' => 'dc:creator', 'value' => $item->name), array('key' => 'guid', 'value' => $item->nid . ' at ' . $base_url, 'attributes' => array('isPermaLink' => 'false'))));
-    foreach ($extra as $element) {
-      if ($element['namespace']) {
-        $namespaces = array_merge($namespaces, $element['namespace']);
-      }
-    }
-    
-    // Prepare the item description
-    switch ($item_length) {
-      case 'fulltext':
-        $item_text = $item->body;
-        break;
-      case 'teaser':
-        $item_text = $item->teaser;
-        if ($item->readmore) {
-          $item_text .= '

'. l(t('read more'), 'node/'. $item->nid, NULL, NULL, NULL, TRUE) .'

'; - } - break; - case 'title': - $item_text = ''; - break; - } - - $items .= format_rss_item($item->title, $link, $item_text, $extra); - } - - $channel_defaults = array( - 'version' => '2.0', - 'title' => variable_get('site_name', 'drupal') .' - '. variable_get('site_slogan', ''), - 'link' => $base_url, - 'description' => variable_get('site_mission', ''), - 'language' => $GLOBALS['locale'], - ); - $channel = array_merge($channel_defaults, $channel); - - $output = "\n"; - $output .= "\n"; - $output .= format_rss_channel($channel['title'], $channel['link'], $channel['description'], $items, $channel['language']); - $output .= "\n"; - - drupal_set_header('Content-Type: text/xml; charset=utf-8'); - print $output; - module_invoke_all('exit'); - exit; -} diff --git a/views_theme_wizard.info b/views_theme_wizard.info deleted file mode 100644 index 72bd96ceb0e0f1cd1cb502a790c587b5ae830d6f..0000000000000000000000000000000000000000 --- a/views_theme_wizard.info +++ /dev/null @@ -1,5 +0,0 @@ -; $Id$ -name = Views Theme Wizard -description = The views theme wizard helps create stub theming for views. -package = Views -dependencies = views diff --git a/views_theme_wizard.module b/views_theme_wizard.module deleted file mode 100644 index 57a7163052306352a2865bd3a4a25621e5c2945e..0000000000000000000000000000000000000000 --- a/views_theme_wizard.module +++ /dev/null @@ -1,595 +0,0 @@ - 'admin/build/views/wizard', - 'access' => user_access('administer views'), - 'title' => t('Theme wizard'), - 'callback' => 'views_theme_wizard_page', - 'type' => MENU_LOCAL_TASK, - ); - } - return $items; -} - -function views_theme_wizard_page() { - views_load_cache(); - $result = db_query("SELECT name, description FROM {view_view}"); - $views = array(); - while ($view = db_fetch_object($result)) { - $views[$view->name] = $view->name . ': ' . $view->description; - } - - $default_views = _views_get_default_views(); - $views_status = variable_get('views_defaults', array()); - foreach ($default_views as $view) { - if (!$views[$view->name] && - ($views_status[$view->name] == 'enabled' || (!$views_status[$view->name] && !$view->disabled))) { - $views[$view->name] = check_plain($view->name . ': ' . $view->description); - } - } - return drupal_get_form('views_theme_wizard_form', $views); -} - - -function views_theme_wizard_form($views, $form_values = array()) { - $form = array(); - - if (!isset($form_values['step'])) { - $step = 1; - } - else { - $step = $form_values['step']; - } - - $form['markup'] = array( - '#value' => t('

The views theming wizard generates code that you can use in your phptemplate theme to help you customize the output of a view. Simply select a theme and it will generate code for your template.php as well as template files for the individual views.

At this time this code assumes your view is a list type view! It may not generate effective code for other types of views. Future versions of this program will be smarter, and give more options, but this wizard is still a huge start.

'), - '#weight' => 0, - ); - - $op = isset($form_values['op']) ? $form_values['op'] : ''; - - while ($step != 0) { - if (1 == $step) { - $form['step'] = array( - '#type' => 'hidden', - '#value' => $step, - ); - $form['vid'] = array( - '#type' => 'select', - '#options' => $views, - '#title' => t('Select a view'), - '#weight' => 5, - ); - $form['theme_type'] = array( - '#type' => 'select', - '#title' => t('Select Theme Type'), - '#options' => views_theme_wizard_get_theme_types(), - '#weight' => 6, - ); - $form['submit'] = array( - '#type' => 'button', - '#value' => t('Select Theme Type'), - '#weight' => 10, - ); - $form['submit2'] = array( - '#type' => 'button', - '#value' => t('List Theme Fields'), - '#weight' => 11, - ); - $form['step'] = array( - '#type' => 'hidden', - '#value' => $step + 1, - ); - - $step = 0; - } - elseif (2 == $step && $op == t('List Theme Fields')) { - $view = views_get_view($form_values['vid']); - $form['code1']['#type'] = 'textarea'; - $form['code1']['#value'] = views_theme_wizard_list_fields($view); - $form['code1']['#title'] = t('This is a list of all the theme functions you can use to override individual field displays'); - $form['code1']['#rows'] = 20; - - $form['code2']['#type'] = 'textarea'; - $form['code2']['#value'] = views_theme_wizard_example_field($view); - $form['code2']['#title'] = t('This is a basic theme function', array('@s' => $view->name)); - $form['code2']['#rows'] = 20; - - $step = 0; - } - elseif (2 == $step && $op = t('Select Theme Type')) { - $view = views_get_view($form_values['vid']); - $type = $form_values['theme_type']; - $additions = module_invoke_all('views_theme_wizard_types', 'configure', $type, $view); - if (! $additions) { - $step = 3; - continue; - } - $form['theme_type'] = array( - '#type' => 'hidden', - '#value' => $type, - ); - $form['vid'] = array( - '#type' => 'hidden', - '#value' => $form_values['vid'], - ); - foreach ($additions as $k => $v) { - $form[$k] = $v; - } - $form['generate'] = array( - '#type' => 'button', - '#value' => t('Generate Theme'), - '#weight' => 10, - ); - $form['step'] = array( - '#type' => 'hidden', - '#value' => $step + 1, - ); - - $step = 0; - - } - elseif (3 == $step) { - $view = views_get_view($form_values['vid']); - $form['code1']['#type'] = 'textarea'; - $form['code1']['#value'] = views_theme_wizard_generate_list_code($form_values['theme_type'], $view, $form_values); - $form['code1']['#title'] = t('This code goes in your template.php file'); - $form['code1']['#rows'] = 20; - - $form['code2']['#type'] = 'textarea'; - $form['code2']['#value'] = views_theme_wizard_generate_list_template_code($view); - $form['code2']['#title'] = t('This code goes in a file named views-list-@s.tpl.php', array('@s' => $view->name)); - $form['code2']['#rows'] = 20; - - $form['code3']['#type'] = 'textarea'; - $form['code3']['#value'] = views_theme_wizard_generate_list_stylesheet_code($view); - $form['code3']['#title'] = t('This code goes in a file named views-list-@s.css', array('@s' => $view->name)); - $form['code3']['#rows'] = 20; - - $step = 0; - } - - } - - $form['#multistep'] = TRUE; - $form['#redirect'] = FALSE; - - return $form; -} - -function views_theme_wizard_get_theme_types() { - $types = module_invoke_all('views_theme_wizard_types', 'list'); - ksort($types); - return $types; -} - - -function views_theme_wizard_views_theme_wizard_types($op='list', $delta='', $view=NULL, $options = array()) { - - switch($op) { - case 'list': - if ('list' == $op) { - return array( - 'simple' => t('Simple List'), - 'grouped' => t('Grouped List'), - 'tree' => t('Nested Tree'), - ); - } - case 'configure': - switch ($delta) { - case 'simple': - break; - case 'grouped': - $options = array(); - foreach ($view->field as $field) { - $options[$field['queryname']] = $field['label'] ? $field['label'] : $field['queryname']; - } - $form['group_field'] = array( - '#type' => 'select', - '#title' => t('Select the field on which to group'), - '#options' => $options, - ); - $form['test'] = array('#type'=>'markup'); - return $form; - break; - case 'tree': - $options = array(); - foreach ($view->field as $field) { - $options[$field['queryname']] = $field['label'] ? $field['label'] : $field['queryname']; - } - $form['tree_key_field'] = array( - '#type' => 'select', - '#title' => t('Select the field to use as the ID for each row (usually nid)'), - '#options' => $options, - ); - $form['tree_reference_field'] = array( - '#type' => 'select', - '#title' => t('Select the field that refers to the parent node by the ID field'), - '#options' => $options, - ); - return $form; - break; - } - break; - case 'code': - switch ($delta) { - case 'simple': - return views_theme_wizard_type_generate_code_simple($view); - break; - case 'grouped': - return views_theme_wizard_type_generate_code_grouped($view, $options); - break; - case 'tree': - return views_theme_wizard_type_generate_code_tree($view, $options); - break; - } - break; - } - -} - -function views_theme_wizard_list_fields($view) { - $fields = _views_get_fields(); - $output = "These functions will override the given fields for just this view:\n\n"; - foreach ($view->field as $field) { - $fieldinfo = $fields[$field['id']]; - $output .= "$fieldinfo[name]\n phptemplate_views_handle_field_{$view->name}_$field[queryname]\n\n"; - } - $output .= "\n\nThese functions will override the given fields for every view:\n\n"; - foreach ($view->field as $field) { - $fieldinfo = $fields[$field['id']]; - $output .= "$fieldinfo[name]\n phptemplate_views_handle_field_$field[queryname]\n\n"; - } - return $output; -} - -function views_theme_wizard_example_field($view) { - $fieldname = 'phptemplate_views_handle_field_' . $view->name . '_' . $view->field[0]['queryname']; - $output = <<\$field['queryname'], \$data); - } - - if (\$info['handler'] && is_string(\$info['handler']) && function_exists(\$info['handler'])) { - return \$info['handler'](\$info, \$field, \$data->\$field['queryname'], \$data); - } - - return check_plain(\$data->\$field['queryname']); -} -EOT; - return $output; -} - -function views_theme_wizard_generate_list_code($theme_type, $view, $options) { - $now = format_date(time()); - - $header = <<name - * - * This function goes in your template.php file - */ - -EOT; - - $function = module_invoke_all('views_theme_wizard_types', 'code', $theme_type, $view, $options); - - return $header . implode($function); -} - -function views_theme_wizard_type_generate_code_simple($view) { - - $code = <<name}(\$view, \$nodes, \$type) { - \$fields = _views_get_fields(); - - \$taken = array(); - - // Set up the fields in nicely named chunks. - foreach (\$view->field as \$id => \$field) { - \$field_name = \$field['field']; - if (isset(\$taken[\$field_name])) { - \$field_name = \$field['queryname']; - } - \$taken[\$field_name] = true; - \$field_names[\$id] = \$field_name; - } - - // Set up some variables that won't change. - \$base_vars = array( - 'view' => \$view, - 'view_type' => \$type, - ); - - foreach (\$nodes as \$i => \$node) { - \$vars = \$base_vars; - \$vars['node'] = \$node; - \$vars['count'] = \$i; - \$vars['stripe'] = \$i % 2 ? 'even' : 'odd'; - foreach (\$view->field as \$id => \$field) { - \$name = \$field_names[\$id]; - \$vars[\$name] = views_theme_field('views_handle_field', \$field['queryname'], \$fields, \$field, \$node, \$view); - if (isset(\$field['label'])) { - \$vars[\$name . '_label'] = \$field['label']; - } - } - \$items[] = _phptemplate_callback('views-list-{$view->name}', \$vars); - } - if (\$items) { - return theme('item_list', \$items); - } -} -EOT; - - return $code; -} - -function views_theme_wizard_type_generate_code_grouped($view, $options) { - - $group_field = $options['group_field']; - - $code = <<name}(\$view, \$nodes, \$type) { - \$fields = _views_get_fields(); - - \$taken = array(); - - // Group our nodes - \$set = array(); - foreach (\$nodes as \$node) { - \$set[\$node->{$group_field}][] = \$node; - } - - // Set up the fields in nicely named chunks. - foreach (\$view->field as \$id => \$field) { - \$field_name = \$field['field']; - if (isset(\$taken[\$field_name])) { - \$field_name = \$field['queryname']; - } - \$taken[\$field_name] = true; - \$field_names[\$id] = \$field_name; - } - - // Set up some variables that won't change. - \$base_vars = array( - 'view' => \$view, - 'view_type' => \$type, - ); - - \$output = ''; - foreach (\$set as \$label => \$nodes) { - \$items = array(); - foreach (\$nodes as \$i => \$node) { - \$vars = \$base_vars; - \$vars['node'] = \$node; - \$vars['count'] = \$i; - \$vars['stripe'] = \$i % 2 ? 'even' : 'odd'; - foreach (\$view->field as \$id => \$field) { - \$name = \$field_names[\$id]; - \$vars[\$name] = views_theme_field('views_handle_field', \$field['queryname'], \$fields, \$field, \$node, \$view); - if (isset(\$field['label'])) { - \$vars[\$name . '_label'] = \$field['label']; - } - } - \$items[] = _phptemplate_callback('views-list-{$view->name}', \$vars); - } - if (\$items) { - \$output .= theme('item_list', \$items, \$label); - } - } - return \$output; -} -EOT; - - return $code; -} - -function views_theme_wizard_type_generate_code_tree($view, $options) { - - $tree_key_field = $options['tree_key_field']; - $tree_reference_field = $options['tree_reference_field']; - - $code = <<name}(\$view, \$nodes, \$type, \$parent=NULL) { - \$fields = _views_get_fields(); - - \$taken = array(); - - // Normalize the top level of nodes to all point to 0 as their parent - // We only have to do this on the top-level pass, because otherwise it's - // irrelevant. - if (!isset(\$parent)) { - \$parents = array(); - foreach (\$nodes as \$node) { - \$parents[] = \$node->{$tree_key_field}; - } - foreach (\$nodes as \$node) { - if (! in_array(\$node->{$tree_reference_field}, \$parents)) { - \$node->{$tree_reference_field} = 0; - } - } - } - - // Set up the fields in nicely named chunks. - foreach (\$view->field as \$id => \$field) { - \$field_name = \$field['field']; - if (isset(\$taken[\$field_name])) { - \$field_name = \$field['queryname']; - } - \$taken[\$field_name] = true; - \$field_names[\$id] = \$field_name; - } - - // Set up some variables that won't change. - \$base_vars = array( - 'view' => \$view, - 'view_type' => \$type, - ); - - static \$count = 1; - static \$stripe = 1; - - foreach (\$nodes as \$i => \$node) { - if (\$node->{$tree_reference_field} != \$parent) { - continue; - } - \$vars = \$base_vars; - \$vars['node'] = \$node; - \$vars['count'] = \$count++; - \$vars['stripe'] = \$stripe++ % 2 ? 'even' : 'odd'; - foreach (\$view->field as \$id => \$field) { - \$name = \$field_names[\$id]; - \$vars[\$name] = views_theme_field('views_handle_field', \$field['queryname'], \$fields, \$field, \$node, \$view); - if (isset(\$field['label'])) { - \$vars[\$name . '_label'] = \$field['label']; - } - } - \$item = _phptemplate_callback('views-list-{$view->name}', \$vars); - \$item .= call_user_func(__FUNCTION__, \$view, \$nodes, \$type, \$node->{$tree_key_field}); - \$items[] = \$item; - } - if (\$items) { - return theme('item_list', \$items); - } - else { - return ''; - } -} -EOT; - - return $code; -} - -/** - * generate a template file for a list theme - */ -function views_theme_wizard_generate_list_template_code($view) { - $now = format_date(time()); - $header = <<name - * - * Variables available: - * \$view -- the entire view object. Important parts of this object are - * $view->name, $view->real_url. - * \$view_type -- The type of the view. Probably 'page' or 'block' but could - * also be 'embed' or other string passed in from a custom view creator. - * \$node -- the raw data. This is not a real node object, but will contain - * the nid as well as other support fields that might be necessary. - * \$count -- the current row in the view (not TOTAL but for this page) starting - * from 0. - * \$stripe -- 'odd' or 'even', alternating. -EOT; - - $fields = _views_get_fields(); - $taken = array(); - - // Set up the fields in nicely named chunks. - foreach ($view->field as $id => $field) { - $field_name = $field['field']; - $css_field_name = views_css_safe($field['field']); - if (isset($taken[$field_name])) { - $field_name = $field['queryname']; - $css_field_name = views_css_safe($field['queryname']); - } - $taken[$field_name] = true; - $output .= << - - -
- -
-\n -EOT; - $fid = $view->field[$id]['id']; - $header .= ' * $' . $field_name . ' -- ' . $fields[$fid]['help'] . "\n"; - $header .= ' * $' . $field_name . '_label -- The assigned label for $' . $field_name . "\n"; - } - - $header .= <<name}.tpl.php file - */ - - - //now we add the stylesheet... - drupal_add_css(path_to_theme() .'/views-list-{$view->name}.css'); - - ?> - -EOT; - - - return $header .$output; -} - -/** - * generate a stylesheet file for a list theme - */ -function views_theme_wizard_generate_list_stylesheet_code($view) { - $now = format_date(time()); - $header = <<name - * - * The class selectors are filled with a single comment line. - * You should complete each selector according to your liking. -*/ -\n -EOT; - - $fields = _views_get_fields(); - $taken = array(); - - $output .= <<field as $id => $field) { - $field_name = views_css_safe($field['field']); - if (isset($taken[$field_name])) { - $field_name = views_css_safe($field['queryname']); - } - $taken[$field_name] = true; - $output .= << l(t('the views help page'), 'admin/help/views_ui'))); - case 'export': - return t('You may cut & paste this view into an import function on another system. The view will only work if all modules required by the view are installed on the target location.'); - } - } -} - -/* - * Because the add/edit page is kind of complicated. - */ -function _views_ui_help_add() { - $output = t('

A view retrieves some number of nodes from the database and displays them in a variety of formats.

'); - $output .= t("

View Types

-
-
List View
A List View provides the data for each node retrieved in the form of an unordered list. Each item in the Fields section will be displayed; the Title will be displayed as a label. The order the items appear in the Fields list is the order the items will appear in the output. Leaving the title blank will cause the field to appear with no label (which is desirable in lists that just display titles, for example).
-
Table View
A Table View provides the data for each node as one row of a table. The Fields selected in the Fields list will be displayed in the order they are listed. The title column will be shown in the header. If you set the field to 'sortable' then the header will be click-sortable; be careful here as click-sorts will be processed after built-in sort criteria, and built-in sort criteria can easily make click-sorts invalid. If using click-sorts, choose a field to be the default sort; otherwise the first field presented will be the default sort.
-
Teaser List
A Teaser List will simply present the teaser of each node retrieved.
-
Full Nodes
This will show the full content of each node retrieved.
-
Random Teaser
This will show a single random teaser.
-
Random Node
This will show a single random node's full view.
-
"); - - views_load_cache(); - $output .= t("

Fields

\n"); - $output .= t("

When using List or Table view, it is necessary to choose which fields will be displayed to the user.

\n"); - $fields = _views_get_fields(); - foreach ($fields as $field) { - $output .= "
$field[name]
$field[help]
\n"; - } - $output .= "
\n"; - - $output .= t("

Arguments

\n"); - $output .= t("

Arguments can be passed to the View through the URL, in order to create views that are configurable by the user. This is very useful to create views for taxonomy, or to sort by user. When using arguments, substitution is performed on the title. %1 will represent argument 1, %2 will represent argument 2. Each argument has a title field; this title is used if providing a summary view (which can matter because the argument is missing which could result in confusing phrases such as 'view for')

\n"); - $arguments = _views_get_arguments(); - foreach ($arguments as $argument) { - $output .= "
$argument[name]
$argument[help]
\n"; - } - $output .= "
\n"; - - $output .= t("

Filters

\n"); - $output .= t("

Views may be filtered to restrict the view on a number of criteria.

\n"); - $filters = _views_get_filters(); - foreach ($filters as $filter) { - $output .= "
$filter[name]
$filter[help]
\n"; - } - $output .= "
\n"; - - $output .= t("

Sorting Critera

\n"); - $output .= t("

The result set may be sorted on any of the following criteria.

\n"); - $sorts = _views_get_sorts(); - foreach ($sorts as $sort) { - $output .= "
$sort[name]
$sort[help]
\n"; - } - $output .= "
\n"; - - return $output; -} - -/* - * Implementation of hook_perm() - */ -function views_ui_perm() { - return array('administer views'); -} - -/* - * Implementation of hook_menu() - */ -function views_ui_menu($may_cache) { - $items = array(); - - if ($may_cache) { - $items[] = array('path' => 'admin/build/views', - 'title' => t('Views'), - 'callback' => 'views_ui_admin_page', - 'access' => user_access('administer views'), - 'description' => t('Views are customized lists of content on your system; they are highly configurable and give you control over how lists of content are presented.'), - 'type' => MENU_NORMAL_ITEM); - $items[] = array('path' => 'admin/build/views/list', - 'title' => t('List'), - 'callback' => 'views_ui_admin_page', - 'access' => user_access('administer views'), - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'weight' => '-1'); - $items[] = array('path' => 'admin/build/views/add', - 'title' => t('Add'), - 'callback' => 'views_ui_admin_add_page', - 'access' => user_access('administer views'), - 'type' => MENU_LOCAL_TASK); - $items[] = array('path' => 'admin/build/views/clone', - 'title' => t('Clone'), - 'callback' => 'views_ui_admin_clone_page', - 'access' => user_access('administer views'), - 'type' => MENU_CALLBACK); - $items[] = array('path' => 'admin/build/views/edit', - 'title' => t('Edit view'), - 'callback' => 'views_ui_admin_edit_page', - 'access' => user_access('administer views'), - 'type' => MENU_CALLBACK); - $items[] = array('path' => 'admin/build/views/import', - 'title' => t('Import'), - 'callback' => 'views_ui_admin_import_page', - 'access' => user_access('administer views'), - 'type' => MENU_LOCAL_TASK); - $items[] = array('path' => 'admin/build/views/export', - 'title' => t('Export view'), - 'callback' => 'drupal_get_form', - 'callback arguments' => array('views_ui_admin_export_page'), - 'access' => user_access('administer views'), - 'type' => MENU_CALLBACK); - $items[] = array('path' => 'admin/build/views/delete', - 'title' => t('Edit view'), - 'callback' => 'drupal_get_form', - 'callback arguments' => array('views_ui_admin_delete_confirm'), - 'access' => user_access('administer views'), - 'type' => MENU_CALLBACK); - $items[] = array('path' => 'admin/build/views/enable', - 'callback' => 'views_ui_admin_enable_page', - 'access' => user_access('administer views'), - 'type' => MENU_CALLBACK); - $items[] = array('path' => 'admin/build/views/disable', - 'callback' => 'views_ui_admin_disable_page', - 'access' => user_access('administer views'), - 'type' => MENU_CALLBACK); - - } - return $items; -} - -// --------------------------------------------------------------------------- -// Administrative Pages - -/* - * This page lists all system views and provides links to edit them. - */ -function views_ui_admin_page() { - views_load_cache(); - - $numViews = 25; - - drupal_set_title(t('administer views')); - - $result = pager_query("SELECT vid, name, description, menu_title, page_title, block_title, url, page, menu, block FROM {view_view} ORDER BY name", $numViews); - - while ($view = db_fetch_object($result)) { - $url = ($view->page ? l($view->url, $view->url) : t('No Page View')); - $provides = array(); - if ($view->page) { - $provides[] = 'Page'; - } - if ($view->block) { - $provides[] = 'Block'; - } - if ($view->menu) { - $provides[] = 'Menu'; - } - $items[] = array( - $view->name, - views_get_title($view, 'admin'), - $view->description, - implode(', ', $provides), - $url, - theme('links', array( - array('title' => t('Edit'), 'href' => "admin/build/views/edit/$view->vid"), - array('title' => t('Export'), 'href' => "admin/build/views/export/$view->vid"), - array('title' => t('Delete'), 'href' => "admin/build/views/delete/$view->vid"), - array('title' => t('Clone'), 'href' => "admin/build/views/clone/$view->vid"), - )) - ); - } - - if ($items) { - $output = theme('table', array(t('View'), t('Title'), t('Description'), t('Provides'), t('URL'), t('Actions')), $items, array("cellpadding" => "4"), t('Existing Views')); - $output .= theme('pager', NULL, $numViews); - } - else { - $output .= t('

No views have currently been defined.

'); - } - - $result = db_query("SELECT name FROM {view_view}"); - while ($view = db_fetch_object($result)) { - $used[$view->name] = true; - } - - $output .= t('

Below are system default views; if you edit one of these, a view will be created that will override any system use of the view.

'); - $items = array(); - $default_views = _views_get_default_views(); - - $views_status = variable_get('views_defaults', array()); - - foreach ($default_views as $view) { - $url = ($view->page ? l($view->url, $view->url) : t('No Page View')); - - if ($used[$view->name]) { - $status = t('Overridden'); - } - else if (isset($views_status[$view->name])) { - if ($views_status[$view->name] == 'enabled') { - $status = t('Enabled'); - } - else { - $status = t('Disabled'); - } - } - else if ($view->disabled) { - $status = t('Disabled'); - } - else { - $status = t('Enabled'); - } - - $provides = array(); - if ($view->page) { - $provides[] = t('Page'); - } - if ($view->block) { - $provides[] = t('Block'); - } - if ($view->menu) { - $provides[] = t('Menu'); - } - - $links = array(); - $links[] = array('title' => t('Add'), 'href' => "admin/build/views/add/$view->name"); - if ($status == t('Enabled')) { - $links[] = array('title' => t('Disable'), 'href' => "admin/build/views/disable/$view->name"); - } - else if ($status == t('Disabled')) { - $links[] = array('title' => t('Enable'), 'href' => "admin/build/views/enable/$view->name"); - } - - $items[] = array($view->name, views_get_title($view, 'menu'), $view->description, implode(', ', $provides), $url, $status, theme('links', $links)); - } - - if ($items) { - $output .= theme('table', array(t('Default view'), t('Title'), t('Description'), t('Provides'), t('URL'), t('Status'), t('Actions')), $items, array("cellpadding" => "4"), t('Default Views')); - } - else { - $output .= t('

No views have currently been defined.

'); - } - - return $output; -} - -/* - * Page to enable a disabled default view - */ -function views_ui_admin_enable_page($view = '') { - views_load_cache(); - - if ($view) { - $views_status = variable_get('views_defaults', array()); - $views_status[$view] = 'enabled'; - variable_set('views_defaults', $views_status); - menu_rebuild(); - } - drupal_goto('admin/build/views'); -} - -/* - * Page to disable an enabled default view - */ -function views_ui_admin_disable_page($view = '') { - views_load_cache(); - - if ($view) { - $views_status = variable_get('views_defaults', array()); - $views_status[$view] = 'disabled'; - variable_set('views_defaults', $views_status); - menu_rebuild(); - } - drupal_goto('admin/build/views'); -} - -/* - * Provide a textarea to paste a view export into. - */ -function views_ui_admin_import_page() { - views_load_cache(); - - if ($_POST['form_id'] == 'views_edit_view') { - return views_ui_admin_add_page(); - } - drupal_set_title("Import a View"); - - return drupal_get_form('views_ui_admin_import', $form); -} - -function views_ui_admin_import() { - $form['view'] = array( - '#type' => 'textarea', - '#title' => t('Import View Code'), - '#cols' => 60, - '#rows' => 6, - '#description' => t('Cut and paste the results of an Export View here.'), - ); - - $form['submit'] = array( - '#type' => 'submit', - '#value' => t("Submit"), - ); - - $form['#redirect'] = NULL; - return $form; -} - -/* - * Handle the submit button on importing a view. - */ -function views_ui_admin_import_submit($formid, $form) { - ob_start(); - eval($form['view']); - ob_end_clean(); - - $tables = array_keys(_views_get_tables()); - if (isset($view)) { - if (!is_array($view->requires) || !array_diff($view->requires, $tables)) { - views_sanitize_view($view); - drupal_set_title(t('Add a View')); - $output = drupal_get_form('views_edit_view', $view, NULL); - print theme('page', $output); - exit; - } - else { - drupal_set_message(t("You don't seem to have the following requirements: ") . implode(', ', array_diff($view->requires, $tables))); - } - } - else { - drupal_set_message(t('Unable to get a view out of that.')); - } -} - -/* - * Export a view for cut & paste. - */ -function views_ui_admin_export_page($vid = '') { - views_load_cache(); - - $code = views_create_view_code($vid); - $lines = substr_count($code, "\n"); - $form['code'] = array( - '#type' => 'textarea', - '#title' => $view->name, - '#default_value' => $code, - '#rows' => $lines); - return $form; -} - -/* - * Provide a form to add a view. Allow adding a view from default templates. - */ -function views_ui_admin_add_page($template = NULL) { - views_load_cache(); - - $op = $_POST['op']; - if ($op == t('Cancel')) { - return 'admin/build/views'; - } - - $view = _views_get_default_view($template); - - drupal_set_title(t('Add a View')); - - return drupal_get_form('views_edit_view', $view, $op); -} - -/* - * Provide a form to clone a view. - */ -function views_ui_admin_clone_page($viewname) { - views_load_cache(); - - $op = $_POST['op']; - if ($op == t('Cancel')) { - return 'admin/build/views'; - } - - $view = views_load_view($viewname); - if (!$view) { - return drupal_not_found(); - } - - unset($view->vid); - drupal_set_title(t('Add a View')); - - return drupal_get_form('views_edit_view', $view, $op); -} - -/* - * Provide a form to edit a view. - */ -function views_ui_admin_edit_page($vid = '') { - views_load_cache(); - - $op = $_POST['op']; - if ($op == t('Cancel')) { - drupal_goto('admin/build/views'); - } - - if ($op == t('Delete')) { - drupal_goto("admin/build/views/delete/$vid"); - } - - if (!($view = _views_load_view($vid))) { - drupal_goto('admin/build/views'); - } - - drupal_set_title(t('Edit view %n', array('%n' => $view->name))); - return drupal_get_form('views_edit_view', $view, $op); -} - -/* - * Provide a form to confirm deletion of a view. - */ -function views_ui_admin_delete_confirm($vid = '') { - $view = _views_load_view($vid); - - if (!$view) { - return drupal_goto('admin/build/views'); - } - - $form['vid'] = array('#type' => 'value', '#value' => $view->vid); -// bdragon note: Did you mean to drop the above line on the floor with this? - $form = confirm_form($form, - t('Are you sure you want to delete %title?', array('%title' => $view->name)), - $_GET['destination'] ? $_GET['destination'] : 'admin/build/views', - t('This action cannot be undone.'), - t('Delete'), t('Cancel') - ); - return $form; -} - -/* - * Handle the submit button to delete a view. - */ -function views_ui_admin_delete_confirm_submit($form_id, $form) { - _views_delete_view((object) $form); - menu_rebuild(); - drupal_goto('admin/build/views'); -} - -/* - * Get an empty view with basic defaults. - */ -function _views_get_default_view($template = '') { - if ($template) { - $default_views = _views_get_default_views(); - if (isset($default_views[$template])) { - $view = $default_views[$template]; - } - } - if (!$view) { - $view = new stdClass(); - $view->use_pager = true; - $view->nodes_per_page = variable_get('default_nodes_main', 10); - $view->page_header_format = variable_get('filter_default_format', 1); - $view->page_footer_format = variable_get('filter_default_format', 1); - $view->page_header_format = variable_get('filter_default_format', 1); - $view->block_header_format = variable_get('filter_default_format', 1); - $view->block_footer_format = variable_get('filter_default_format', 1); - $view->block_header_format = variable_get('filter_default_format', 1); - $view->vid = 0; - } - - return _views_check_arrays($view); -} - -// --------------------------------------------------------------------------- -// Select Box Definitions - -// These should probably have string array keys that are easier to identify. - -/** - * Select box entries for argument defaults. - */ -function _views_get_arguments_default() { - return array( - 1 => t('Return Page Not Found'), - 2 => t('Display All Values'), - 3 => t('Summary, unsorted'), - 4 => t('Summary, sorted ascending'), - 5 => t('Summary, sorted descending'), - 6 => t('Summary, sorted as view'), - 7 => t('Use Empty Text'), - ); -} - -/** - * Select box entries for sort ordering. - */ -function _views_sortorders() { - return array( - 'ASC' => t('Ascending'), - 'DESC' => t('Descending') - ); -} - -/** - * Swap two items in an array. - */ -function _views_swap(&$arr, $a, $b) { - $temp = $arr[$a]; - $arr[$a] = $arr[$b]; - $arr[$b] = $temp; -} - -/** - * Move an item up in an array. - */ -function _views_move_up(&$arr, $i) { - if ($i <= 0 || $i >= count($arr)) { - return; // can't do it. - } - _views_swap($arr, $i - 1, $i); -} - -/** - * Move an item down in an array. - */ -function _views_move_down(&$arr, $i) { - if ($i >= count($arr) - 1 || $i < 0) { - return; // can't do it. - } - _views_swap($arr, $i + 1, $i); -} - -/** - * Move an item to the front of an array. - */ -function _views_move_top(&$arr, $i) { - if ($i <= 0 || $i >= count($arr)) { - return; // can't do it. - } - $temp = $arr[$i]; - for ($x = $i; $x > 0; $x--) - $arr[$x] = $arr[$x - 1]; - $arr[0] = $temp; -} - -/** - * Move an item to the end of an array. - */ -function _views_move_bottom(&$arr, $i) { - $end = count($arr) - 1; - if ($i >= $end || $i < 0) { - return; // can't do it. - } - $temp = $arr[$i]; - for ($x = $i; $x < $end; $x++) - $arr[$x] = $arr[$x + 1]; - $arr[$end] = $temp; -} - -/** - * Figure out which of the many, many buttons on a form were clicked and - * handle it. - */ -function _views_check_sub_ops(&$form, &$order, $i) { - - if ($form['delete']['#value']) { - unset($form['delete']['#value']); - unset($order[$i]); - $order = array_values($order); // reindex - $form['delete']['#printed'] = true; - $form['up']['#printed'] = true; - $form['down']['#printed'] = true; - $form['top']['#printed'] = true; - $form['bottom']['#printed'] = true; - return 'delete'; - } - else foreach (array('up', 'down', 'top', 'bottom') as $dir) { - if ($form[$dir]['#value']) { - unset ($form[$dir]['#value']); - $func = "_views_move_$dir"; - $func($order, $i); - return true; - } - } - return false; -} - -/** - * Figure out if one of the add buttons on a form were clicked, and handle it. - */ -function _views_check_ops(&$view, $op, $form) { - if ($op == t('Add Filter')) { - $view->new_filter['id'] = $form['filter']['add']['id']['#value']; - return 'filter'; - } - else if ($op == t('Add Criteria')) { - $view->new_sort['id'] = $form['sort']['add']['id']['#value']; - return 'sort'; - } - else if ($op == t('Add Argument')) { - $view->new_argument['id'] = $form['argument']['add']['id']['#value']; - return 'argument'; - } - else if ($op == t('Add Field')) { - $fieldbits = explode('.', $form['field']['add']['id']['#value']); - $view->new_field['id'] = $form['field']['add']['id']['#value']; - $view->new_field['tablename'] = $fieldbits[0]; - $view->new_field['field'] = $fieldbits[1]; - $view->new_field['queryname'] = "$fieldbits[0]_$fieldbits[1]"; - return 'field'; - } - else if ($op == t('Expose Filter')) { - $view->new_exposed_filter['id'] = $form['exposed_filter']['add']['id']['#value']; - return 'filter'; - } -} - -/** - * Custom form element to do our nice images. - */ -function views_elements() { - $type['views_imagebutton'] = array('#input' => TRUE, '#button_type' => 'submit',); - return $type; -} - -function theme_views_imagebutton($element) { - return '\n"; -} - -function views_imagebutton_value() { - // null function guarantees default_value doesn't get moved to #value. -} - -/** - * Set up the dynamic #options on a widget - */ -function views_ui_setup_widget($widget, $default_value, $argument = NULL) { - if (!$argument) { - $argument = $widget; - } - - if (is_string($widget['#options']) && function_exists($widget['#options'])) { - $widget['#options'] = $widget['#options']('option', $argument); - } - if ($widget['#multiple'] && is_array($widget['#options'])) { - $widget['#size'] = min(count($widget['#options']), 8); - } - $widget['#default_value'] = $default_value; - return $widget; -} - -/** - * Display all the guts of a view in a form for editing. - */ -function views_edit_view($view, $op = '') { - _views_check_arrays($view); // make sure arrays that might be empty get set - - // Put in all our add buttons, then process them to see if they've been hit. - $form = array(); - views_ui_add_add_button($form, 'field', _views_get_fields(true), t('Add Field')); - views_ui_add_add_button($form, 'argument', _views_get_arguments(true), t('Add Argument')); - views_ui_add_add_button($form, 'filter', _views_get_filters(true), t('Add Filter')); - views_ui_add_add_button($form, 'sort', _views_get_sorts(true), t('Add Criteria')); - - $allbut = _views_check_ops($view, $op, $form); - if ($_POST['edit'] && $op != t('Save')) { - drupal_set_message(t('You have modified this view; changes will not be recorded until you Save the form.')); - } - - $form['exposed_filter'] = array(); - foreach (array('field', 'argument', 'filter', 'exposed_filter', 'sort') as $section) { - if (views_ui_add_section($form[$section], $view, $section)) { - $allbut = $section; - } - } - - $form['vid'] = array( - '#type' => 'value', - '#value' => $view->vid, - ); - $form['allbut'] = array( - '#type' => 'value', - '#value' => $allbut, - ); - $form['changed'] = array( - '#type' => 'hidden', - '#value' => $view->changed, - ); - - $form['basic-info'] = array( - '#type' => 'fieldset', - '#collapsible' => true, - '#collapsed' => ($allbut != NULL), - '#title' => t('Basic Information'), - ); - - $form['basic-info']['name'] = array( - '#type' => 'textfield', - '#title' => t('Name'), - '#default_value' => $view->name, - '#size' => 20, - '#maxlength' => 32, - '#description' => t('The unique identifier of the view; it is only important for overridden views and views that modules or themes will need to use. Only alphanumeric and _ allowed here'), - '#required' => true, - ); - - $form['basic-info']['access'] = array( - '#type' => 'checkboxes', - '#title' => t('Access'), - '#default_value' => $view->access, - '#options' => views_handler_filter_role(), - '#description' => t('Only the checked roles will be able to see this view in any form; if no roles are checked, access will not be restricted.'), - ); - - $form['basic-info']['description'] = array( - '#type' => 'textfield', - '#title' => t('Description'), - '#default_value' => $view->description, - '#size' => 60, - '#maxlength' => 255, - '#description' => t('A description of the view for the admin list.'), - ); - - // page info - - $form['page-info'] = array( - '#type' => 'fieldset', - '#collapsible' => true, - '#collapsed' => ($allbut != NULL || !$view->page), - '#title' => t('Page'), - ); - - $form['page-info']['page'] = array( - '#type' => 'checkbox', - '#title' => t('Provide Page View'), - '#return_value' => 1, - '#default_value' => $view->page, - '#description' => t('If checked this view will be provided as a page. If not checked, the fields in this group will be ignored.'), - ); - - $form['page-info']['url'] = array( - '#type' => 'textfield', - '#title' => t('URL'), - '#default_value' => $view->url, - '#size' => 60, - '#maxlength' => 255, - '#description' => t('Enter the URL to use for this view in the form of \'dir/dir\'. Do not begin or end the URL with a /. Example: \'view/tracker\'. This is required if providing a page view. You can also add $arg as a placeholder for arguments passed in the URL, for example \'user/$arg/tracker\' or \'view/taxonomy/$arg\'. Note that any arguments listed here will be required, even if they are listed as optional below. You do not need to list arguments at the end of the path.'), - ); - - $form['page-info']['page_type'] = array( - '#type' => 'select', - '#title' => t('View Type'), - '#default_value' => $view->page_type, - '#options' => _views_get_style_plugins(true), - '#description' => t('How the nodes should be displayed to the user.'), - ); - - $form['page-info']['page_title'] = array( - '#type' => 'textfield', - '#title' => t('Title'), - '#default_value' => $view->page_title, - '#size' => 60, - '#maxlength' => 255, - '#description' => t('The title that be shown at the top of the view. May be blank. This title ignores arguments; if you want your title to take arguments into account, use the "title" field in the arguments section.'), - ); - - $form['page-info']['use_pager'] = array( - '#type' => 'checkbox', - '#title' => t('Use Pager'), - '#return_value' => 1, - '#default_value' => $view->use_pager, - '#description' => t('If checked this query may be multiple pages. If not checked this query will be one page.'), - ); - $form['page-info']['breadcrumb_no_home'] = array( - '#type' => 'checkbox', - '#title' => t('Breadcrumb trail should not include "Home"'), - '#return_value' => 1, - '#default_value' => $view->breadcrumb_no_home, - '#description' => t('If checked the breadcrumb trail for this page will discard "Home". Usually you will not set this, but this is used for the Front Page View, where it IS Home and should not leave a trail to itself.'), - ); - $form['page-info']['nodes_per_page'] = array( - '#type' => 'textfield', - '#title' => t('Nodes per Page'), - '#default_value' => intval($view->nodes_per_page), - '#size' => 5, - '#maxlength' => 5, - '#description' => t('The number of nodes to display per page. If 0, all nodes will be displayed. If not using a pager, this will be the maximum number of nodes in the list.'), - '#attributes' => NULL, - ); - $form['page-info']['page_header_fieldset'] = array( - '#type' => 'fieldset', - '#collapsible' => TRUE, - '#collapsed' => TRUE, - '#title' => t('Header'), - ); - $form['page-info']['page_header_fieldset']['page_header'] = array( - '#type' => 'textarea', - '#default_value' => $view->page_header, - '#cols' => 60, - '#rows' => 6, - '#description' => t('Text to display at the top of the view. May contain an explanation or links or whatever you like. Optional.'), - ); - - $form['page-info']['page_header_fieldset']['page_header_format'] = filter_form($view->page_header_format, 1, array('page_header_format')); - - $form['page-info']['page_footer_fieldset'] = array( - '#type' => 'fieldset', - '#collapsible' => TRUE, - '#collapsed' => TRUE, - '#title' => t('Footer'), - ); - $form['page-info']['page_footer_fieldset']['page_footer'] = array( - '#type' => 'textarea', - '#default_value' => $view->page_footer, - '#cols' => 60, - '#rows' => 6, - '#description' => t('Text to display at the bottom of the view. May contain an explanation or links or whatever you like. Optional.'), - ); - - $form['page-info']['page_footer_fieldset']['page_footer_format'] = filter_form($view->page_footer_format, 1, array('page_footer_format')); - - $form['page-info']['page_empty_fieldset'] = array( - '#type' => 'fieldset', - '#collapsible' => TRUE, - '#collapsed' => TRUE, - '#title' => t('Empty Text'), - ); - $form['page-info']['page_empty_fieldset']['page_empty'] = array( - '#type' => 'textarea', - '#default_value' => $view->page_empty, - '#cols' => 60, - '#rows' => 6, - '#description' => t('Text to display if a view returns no nodes. Optional.'), - ); - - $form['page-info']['page_empty_fieldset']['page_empty_format'] = filter_form($view->page_empty_format, 1, array('page_empty_format')); - - $form['page-info']['menu-info'] = array( - '#type' => 'fieldset', - '#collapsible' => TRUE, - '#collapsed' => TRUE, - '#title' => t('Menu'), - ); - - $form['page-info']['menu-info']['menu'] = array( - '#type' => 'checkbox', - '#title' => t('Provide Menu'), - '#return_value' => 1, - '#default_value' => $view->menu, - '#description' => t('If checked this view be given a menu entry in the Drupal menu system. If not checked the data in this group will be ignored.'), - ); - - $form['page-info']['menu-info']['menu_tab'] = array( - '#type' => 'checkbox', - '#title' => t('Provide Menu as Tab'), - '#return_value' => 1, - '#default_value' => $view->menu_tab, - '#description' => t("If checked this view's menu entry will be provided as a tab rather than in the main menu system."), - ); - - $form['page-info']['menu-info']['menu_tab_default'] = array( - '#type' => 'checkbox', - '#title' => t('Make Default Menu Tab'), - '#return_value' => 1, - '#default_value' => $view->menu_tab_default, - '#description' => t("If checked this view's menu entry will be provided as a tab, and will be the default tab for that URL path. For example, if the URL is 'tracker/all' and it is set as the default menu tab, it will be put into the menu as 'tracker' and 'tracker/all' will be the default tab. For tabs to work properly, one tab in the group must be set as the default."), - ); - - $form['page-info']['menu-info']['menu_tab_weight'] = array( - '#type' => 'textfield', - '#title' => t('Tab Weight'), - '#default_value' => $view->menu_tab_weight, - '#width' => 10, - '#description' => t('If this is a menu tab, select the weight; lower numbers will be further to the left.'), - ); - - $form['page-info']['menu-info']['menu_title'] = array( - '#type' => 'textfield', - '#title' => t('Menu Title'), - '#default_value' => $view->menu_title, - '#size' => 60, - '#maxlength' => 255, - '#description' => t('Enter the title to use for the menu entry or tab. If blank, the page title will be used.'), - ); - - // block info - - $form['block-info'] = array( - '#type' => 'fieldset', - '#collapsible' => true, - '#collapsed' => ($allbut != NULL || !$view->block), - '#title' => t('Block'), - ); - - $form['block-info']['block'] = array( - '#type' => 'checkbox', - '#title' => t('Provide Block'), - '#return_value' => 1, - '#default_value' => $view->block, - '#description' => t('If checked this view will be provided as a block. If checked title may not be blank.'), - ); - - $form['block-info']['block_type'] = array( - '#type' => 'select', - '#title' => t('View Type'), - '#default_value' => $view->block_type, - '#options' => _views_get_style_plugins(true), - '#description' => t('How the nodes should be displayed to the user.'), - ); - - $form['block-info']['block_title'] = array( - '#type' => 'textfield', - '#title' => t('Title'), - '#default_value' => $view->block_title, - '#size' => 60, - '#maxlength' => 255, - '#description' => t('The title that will be shown at the top of the block. May be blank.'), - ); - - $form['block-info']['nodes_per_block'] = array( - '#type' => 'textfield', - '#title' => t('Nodes per Block'), - '#default_value' => $view->nodes_per_block, - '#size' => 3, - '#maxlength' => 3, - '#description' => t('If using a block, the maximum number of items to display in the block. Pagers are not used in blocks.'), - '#attributes' => NULL, - ); - - $form['block-info']['block_more'] = array( - '#type' => 'checkbox', - '#title' => t('[More] Link?'), - '#return_value' => 1, - '#default_value' => $view->block_more, - '#description' => t('If using a view as both a page and a block, display a more link in the block that links to the view URL?'), - ); - - $form['block-info']['block_header_fieldset'] = array( - '#type' => 'fieldset', - '#collapsible' => TRUE, - '#collapsed' => TRUE, - '#title' => t('Header'), - ); - $form['block-info']['block_header_fieldset']['block_use_page_header'] = array( - '#type' => 'checkbox', - '#title' => t('Use Page Header'), - '#return_value' => 1, - '#default_value' => $view->block_use_page_header, - '#description' => t('If checked, use the Page Header for block view instead. If so, you should leave the Block Header blank.'), - ); - - $form['block-info']['block_header_fieldset']['block_header'] = array( - '#type' => 'textarea', - '#title' => t('Header'), - '#default_value' => $view->block_header, - '#cols' => 60, - '#rows' => 6, - '#description' => t('Text to display at the top of the view. May contain an explanation or links or whatever you like. Optional.'), - ); - - $form['block-info']['block_header_fieldset']['block_header_format'] = filter_form($view->block_header_format, 1, array( 'block_header_format')); - - $form['block-info']['block_footer_fieldset'] = array( - '#type' => 'fieldset', - '#collapsible' => TRUE, - '#collapsed' => TRUE, - '#title' => t('Footer'), - ); - $form['block-info']['block_footer_fieldset']['block_use_page_footer'] = array( - '#type' => 'checkbox', - '#title' => t('Use Page Footer'), - '#return_value' => 1, - '#default_value' => $view->block_use_page_footer, - '#description' => t('If checked, use the page footer for block view instead. If so, you should leave the block footer blank.'), - ); - - $form['block-info']['block_footer_fieldset']['block_footer'] = array( - '#type' => 'textarea', - '#title' => t('Footer'), - '#default_value' => $view->block_footer, - '#cols' => 60, - '#rows' => 6, - '#description' => t('Text to display at the bottom of the view. May contain an explanation or links or whatever you like. Optional.'), - ); - - $form['block-info']['block_footer_fieldset']['block_footer_format'] = filter_form($view->block_footer_format, 1, array( 'block_footer_format')); - - $form['block-info']['block_empty_fieldset'] = array( - '#type' => 'fieldset', - '#collapsible' => TRUE, - '#collapsed' => TRUE, - '#title' => t('Empty text'), - ); - $form['block-info']['block_empty_fieldset']['block_use_page_empty'] = array( - '#type' => 'checkbox', - '#title' => t('Use Page empty'), - '#return_value' => 1, - '#default_value' => $view->block_use_page_empty, - '#description' => t('If checked, use the Page Empty Text for block view instead. If so, you should leave the block empty text blank.'), - ); - - $form['block-info']['block_empty_fieldset']['block_empty'] = array( - '#type' => 'textarea', - '#title' => t('Empty text'), - '#default_value' => $view->block_empty, - '#cols' => 60, - '#rows' => 6, - '#description' => t('Text to display if a view results in no nodes. Optional.'), - ); - - $form['block-info']['block_empty_fieldset']['block_empty_format'] = filter_form($view->block_empty_format, 1, array( 'block_empty_format')); - - $access = user_access('use PHP for block visibility'); - if ($access) { - $form['view_args_php_fieldset'] = array( - '#type' => 'fieldset', - '#collapsible' => TRUE, - '#collapsed' => empty($view->view_args_php) ? TRUE : FALSE, - '#title' => t('Argument Handling Code'), - ); - - $form['view_args_php_fieldset']['view_args_php'] = array( - '#type' => 'textarea', - '#title' => t('Argument Code'), - '#default_value' => $view->view_args_php, - '#cols' => 60, - '#rows' => 6, - '#description' => '

'. t('Advanced Usage Only: PHP code that returns a custom array of arguments for the view. Should not include <?php ?> delimiters.') .'

' . - '

'. t('For more information, please see the Argument Handling Code documentation in the Drupal handbook.', array('%arg' => 'http://drupal.org/node/70145')) .'

', - ); - } else { - $form['view_args_php_fieldset']['view_args_php'] = array( - '#type' => 'value', - '#value' => $view->view_args_php, - ); - } - - $form['save'] = array( - '#type' => 'submit', - '#value' => t('Save'), - ); - $form['save_and_edit'] = array( - '#type' => 'submit', - '#value' => t('Save and edit'), - ); - if ($view->vid) { - $form['delete'] = array( - '#type' => 'submit', - '#value' => t('Delete'), - ); - } - $form['cancel'] = array( - '#type' => 'submit', - '#value' => t('Cancel'), - ); - - return $form; -} - -/** - * separately build a piece of the form - */ -function views_ui_build_form(&$form) { - // NOT REALLY SURE WHY THIS SORT OF WORKS. IT'S MAGIC THAT CHX POINTED ME TO - // IN THE POLL MODULE. - $form['#post'] = $_POST; - $form = form_builder('views_edit_view', $form); -} - -/** - * Add the 'add' button for a section into the form - */ -function views_ui_add_add_button(&$form, $section, $options, $label) { - $form[$section]['add'] = array('#tree' => true, '#parents' => array($section, 'add')); - - $form[$section]['add']['id'] = array( - '#type' => 'select', - '#options' => $options, - ); - $form[$section]['add']['button'] = array( - '#type' => 'button', - '#value' => $label, - ); - views_ui_build_form($form[$section]['add']); -} - -/** - * Add one of the list sections to the form. - */ -function views_ui_add_section(&$form, &$view, $section) { - // add fields to the form. - - $form += array('#tree' => true, '#parents' => array($section)); - $view_section = &$view->$section; - - $num_items = count($view_section); - // Populate the form with fields we need to check to track - // changes through the form's life. - $form['count'] = array('#type' => 'hidden', '#default_value' => $num_items); - - $form['order'] = array( - '#type' => 'hidden', - '#default_value' => $num_items ? implode(',', range(0, $num_items - 1)) : '', - ); - - // Run the builder to get the value on the form. - views_ui_build_form($form); - $order = $form['order']['#value'] != '' - ? explode(',', $form['order']['#value']) - : array(); - - // Shortcut because operator precedence gets sticky if using $foo->$bar[] - for ($i = $num_items; $i < $form['count']['#value']; $i++) { - $view_section[] = array(); - } - - $new_section = "new_$section"; - // instantiate the new field if one was added. - if ($view->$new_section) { - $view_section[] = $view->$new_section; - $order[] = $form['count']['#value']; - $form['count']['#value']++; - } - - $func = "views_ui_add_$section"; - if ($order) { - foreach ($order as $key => $i) { - $form[$i] = array('#tree' => true, '#parents' => array($section, $i)); - - $form[$i]['id'] = array( - '#type' => 'hidden', - '#default_value' => $view_section[$i]['id'], - ); - - views_ui_add_buttons($form[$i]); - views_ui_build_form($form[$i]); - - $retval = _views_check_sub_ops($form[$i], $order, $key); - if ($retval !== 'delete') { - $retval2 = $func($form[$i], $view_section[$i], $order, $key, $i, $view); - } - - if ($retval || $retval2) { - $allbut = $section; - } - } - $form['order']['#value'] = implode(',', $order); - } - return $allbut; -} - -/** - * Add all the info for a single field into the form. - */ -function views_ui_add_field(&$form, $field, &$order, $key, $i) { - $fields = _views_get_fields(); - $fieldname = $form['id']['#value']; // combined table & fieldname - $fieldinfo = $fields[$fieldname]; // laziness + readability - - $form['fullname'] = array( - '#type' => 'hidden', - '#default_value' => $field['id'], - ); - - $form['name'] = array( - '#type' => 'markup', - '#value' => $fieldinfo['name'], // combined table & fieldname - ); - $form['queryname'] = array( - '#type' => 'hidden', - '#default_value' => $field['queryname'], - ); - $form['tablename'] = array( - '#type' => 'hidden', - '#default_value' => $field['tablename'], - ); - $form['field'] = array( - '#type' => 'hidden', - '#default_value' => $field['field'], - ); - - $form['label'] = array( - '#type' => 'textfield', - '#default_value' => $field['label'], - '#size' => 15, - '#maxlength' => 255, - ); - - if (is_array($fieldinfo['handler'])) { - $form['handler'] = array( - '#type' => 'select', - '#default_value' => $field['handler'], - '#options' => $fieldinfo['handler'], - ); - } - - if (isset($fieldinfo['option'])) { - $form['options'] = views_ui_setup_widget($fieldinfo['option'], $field['options']); - } - - - if ($fieldinfo['sortable']) { - $form['sortable'] = array( - '#type' => 'select', - '#default_value' => $field['sortable'], - '#options' => array('0' => t('No'), '1' => t('Yes')), - ); - $form['defaultsort'] = array( - '#type' => 'select', - '#default_value' => $field['defaultsort'], - '#options' => array('0' => t('None'), 'ASC' => t('Ascending'), 'DESC' => t('Descending')), - ); - } - if (isset($fieldinfo['help'])) { - $form['help'] = array( - '#type' => 'markup', - '#value' => '
' . $fieldinfo['help'] . '
', - ); - } -} - -/** - * Add all the info for a single argument into the form. - */ -function views_ui_add_argument(&$form, $argument, &$order, $key, $i) { - $arguments = _views_get_arguments(); - $arg_type = $form['id']['#value']; - $arginfo = $arguments[$arg_type]; - - $form['type'] = array( - '#type' => 'hidden', - '#default_value' => $argument['id'], - ); - - $form['name'] = array( - '#value' => $arginfo['name'], - ); - - $form['argdefault'] = array( - '#type' => 'select', - '#default_value' => max(1, intval($argument['argdefault'])), - '#options' => _views_get_arguments_default(), - ); - $form['title'] = array( - '#type' => 'textfield', - '#default_value' => $argument['title'], - '#size' => 10, - '#maxlength' => 255, - ); - if (isset($arginfo['option'])) { - $form['options'] = views_ui_setup_widget($arginfo['option'], $argument['options']); - } - $form['wildcard'] = array( - '#type' => 'textfield', - '#default_value' => $argument['wildcard'], - '#size' => 5, - '#maxlength' => 32, - ); - $form['wildcard_substitution'] = array( - '#type' => 'textfield', - '#default_value' => $argument['wildcard_substitution'], - '#size' => 5, - '#maxlength' => 32, - ); - if (isset($arginfo['help'])) { - $form['help'] = array( - '#type' => 'markup', - '#value' => $arginfo['help'], - ); - } -} - -/** - * Add all the info for a single filter into the form. - */ -function views_ui_add_filter(&$form, $filter, &$order, $key, $i, &$view) { - $filters = _views_get_filters(); - $filtername = $form['id']['#value']; // combined table & filtername - $filterinfo = $filters[$filtername]; - - $form['field'] = array( - '#type' => 'hidden', - '#default_value' => $filter['id'], - ); - - $form['name'] = array( - '#type' => 'markup', - '#value' => $filterinfo['name'], - ); - - // 'operator' is either an array or a handler - $operator = $filterinfo['operator']; - if (!is_array($operator) && function_exists($filterinfo['operator'])) { - $operator = $filterinfo['operator']('operator', $filterinfo); - } - - $form['operator'] = array( - '#type' => 'select', - '#default_value' => $filter['operator'], - '#options' => $operator, - ); - if (isset($filterinfo['option'])) { - $form['options'] = views_ui_setup_widget($filterinfo['option'], $filter['options']); - } - - $form['value'] = views_ui_setup_widget($filterinfo['value'], $filter['value'], $filterinfo); - - if (isset($filterinfo['help'])) { - $form['help'] = array( - '#type' => 'markup', - '#value' => $filterinfo['help'], - ); - } - - // This is kind of a pain in the butt -- The only way to know all of - // the filters that have been exposed is to look at the form, but that - // part of the form hasn't been built yet, so I can't use the form_builder - // method. I can't put this after that, either, because then I'd have to - // go back to add one if we see one here. So we cheat heavily with _POST. - - if ($_POST['edit']) { - $exposed_order = $_POST['edit']['exposed_filter']['order']; - if ($exposed_order !== '') { - $exposed_order = explode(',', $exposed_order); - foreach ($exposed_order as $x) { - if ($_POST['edit']['exposed_filter'][$x]['id'] == $filtername) { - $exposed = true; - break; - } - } - } - } - else { // do this if there's never been a submit. - $exposed_order = array_keys($view->exposed_filter); - foreach ($exposed_order as $x) { - if ($view->exposed_filter[$x]['id'] == $filtername) { - $exposed = true; - break; - } - } - } - if (!$exposed) { - // I can't find a way to see if this button was pressed other than - // directly checking, because #form_submitted doesn't work on arrays - - if ($_POST['edit']['filter'][$i]['expose']) { - $view->new_exposed_filter['id'] = $filtername; - return true; - } - else { - $form['expose'] = array( - '#type' => 'button', - '#default_value' => t('Expose'), - '#name' => "edit[filter][$i][expose]", - ); - } - } -} - -/** - * Add all the info for a single exposed filter into the form. - */ -function views_ui_add_exposed_filter(&$form, $filter, &$order, $key, $i) { - $filters = _views_get_filters(); - $filtername = $form['id']['#value']; // combined table & filtername - $filterinfo = $filters[$filtername]; - - $form['field'] = array( - '#type' => 'hidden', - '#default_value' => $filter['id'], - ); - - $form['name'] = array( - '#type' => 'markup', - '#value' => $filterinfo['name'], - ); - - $form['label'] = array( - '#type' => 'textfield', - '#default_value' => $filter['label'], - '#size' => 15, - '#maxlength' => 255, - ); - - $form['optional'] = array( - '#type' => 'checkbox', - '#default_value' => $filter['optional'], - ); - - $form['is_default'] = array( - '#type' => 'checkbox', - '#default_value' => $filter['is_default'], - ); - - $form['single'] = array( - '#type' => 'checkbox', - '#default_value' => $filter['single'], - ); - - $form['operator'] = array( - '#type' => 'checkbox', - '#default_value' => $filter['operator'], - ); -} - -/** - * Add all the info for a single sort into the form. - */ -function views_ui_add_sort(&$form, $sort, &$order, $key, $i) { - $sorts = _views_get_sorts(); - $sortname = $form['id']['#value']; // combined table & sortname - $sortinfo = $sorts[$sortname]; - - $form['field'] = array( - '#type' => 'hidden', - '#default_value' => $sort['id'], - ); - - $form['name'] = array( - '#value' => $sortinfo['name'], - ); - - $form['sortorder'] = array( - '#type' => 'select', - '#title' => NULL, - '#default_value' => $sort['sortorder'], - '#options' => _views_sortorders(), - ); - // option can be either 'string', 'integer', an array or a handler - // that must return an array. - if (isset($sortinfo['option'])) { - $form['options'] = views_ui_setup_widget($sortinfo['option'], $sort['options']); - } - if (isset($sortinfo['help'])) { - $form['help'] = array( - '#type' => 'markup', - '#value' => $sortinfo['help'], - ); - } -} - -/** - * Add the up, down, top, bottom, delete buttons to a form. - */ -function views_ui_add_buttons(&$form_item) { - $form_item['delete'] = views_ui_add_button('user-trash.png', t('Delete'), t('Delete this item.')); - $form_item['up'] = views_ui_add_button('go-up.png', t('Up'), t('Move this item up.')); - $form_item['down'] = views_ui_add_button('go-down.png', t('Down'), t('Move this item down.')); - $form_item['top'] = views_ui_add_button('go-top.png', t('Top'), t('Move this item to the top.')); - $form_item['bottom'] = views_ui_add_button('go-bottom.png', t('Bottom'), t('Move this item to the bottom.')); -} - -/** - * Add a single button to a form. - */ -function views_ui_add_button($image, $name, $text) { - $module_path = base_path() . drupal_get_path('module', 'views'); - - return array( - '#type' => 'views_imagebutton', - '#image' => $module_path . '/' . $image, - '#title' => $text, - '#default_value' => $name, - ); -} - -/** - * Display the form built by _views_view_form() - */ -function theme_views_edit_view($form) { - - $output .= drupal_render($form['basic-info'], false); - $output .= drupal_render($form['page-info'], false); - $output .= drupal_render($form['block-info'], false); - - $allbut = $form['allbut']['#value']; - - // drupal_render wants a reference so use full array notation. - - // fields - $collapsed = $allbut && $allbut != 'field'; - $group = views_ui_render_section($form['field'], array('name', 'label', 'handler', 'options', 'sortable', 'defaultsort'), array(t('Name'), t('Label'), t('Handler'), t('Option'), t('Sortable'), t('Default Sort')), 'fields', $collapsed); - $group .= views_ui_render_section_add($form['field']['add'], array('id', 'button'), t('Add Field')); - - $group .= '

'. t('Fields are only meaningful with List view and Table View; they allow you to choose which fields are presented and in what order.') .'

'; - $output .= theme('fieldset', array('#title' => t('Fields'), '#children' => $group, - '#collapsible' => true, '#collapsed' => $collapsed,)); - - - // arguments - $collapsed = $allbut && $allbut != 'argument'; - $group = views_ui_render_section($form['argument'], array('name', 'argdefault', 'title', 'options', 'wildcard', 'wildcard_substitution'), array(t('Argument Type'), t('Default'), t('Title'), t('Option'), t('Wildcard'), t('Wildcard Sub')), 'arguments', $collapsed); - - $group .= views_ui_render_section_add($form['argument']['add'], array('id', 'button'), t('Add Argument')); - - $group .= drupal_render($form['view_args_php_fieldset']); - - $group .= '

'. t('Arguments are parsed directly from the URL. They are not necessary to any given view, but allow flexibility.') .'

'; - $output .= theme('fieldset', array('#title' => t('Arguments'), '#children' => $group, - '#collapsible' => true, '#collapsed' => $collapsed,)); - - // filter - $collapsed = $allbut && $allbut != 'filter'; - $group = views_ui_render_section($form['filter'], array('name', 'operator', 'value', 'options', 'expose'), array(t('Field'), t('Operator'), t('Value'), t('Option'), ''), 'filters', $collapsed); - - $group .= views_ui_render_section_add($form['filter']['add'], array('id', 'button'), t('Add Filter')); - - $group .= '

'. t('Filters allow you to select a subset of all the nodes to display. All Filters are ANDed together.') .'

'; - $output .= theme('fieldset', array('#title' => t('Filters'), '#children' => $group, - '#collapsible' => true, '#collapsed' => $collapsed,)); - $group = ''; - - // exposed exposed_filter - $collapsed = $allbut && $allbut != 'exposed_filter'; - $group = views_ui_render_section($form['exposed_filter'], array('name', 'label', 'optional', 'is_default', 'single', 'operator'), array(t('Field'), t('Label'), t('Optional'), t('Filter settings Default'), t('Force Single'), t('Lock Operator')), 'exposed_filters', $collapsed); - - -// $group .= views_ui_render_section_add($form['exposed_filter']['add'], array('id', 'button'), t('Expose Filter')); - - $group .= '

'. t('Exposed filters will be presented to the viewer. If not set required, then filters will include a "<None>" Value if possible. If set default, filters will default as set here, otherwise filter settings will be ignored. If Lock Operator is set, no operator will be made available to the user.') .'

'; - $output .= theme('fieldset', array('#title' => t('Exposed Filters'), '#children' => $group, - '#collapsible' => true, '#collapsed' => $collapsed,)); - $group = ''; - - // sort - $collapsed = $allbut && $allbut != 'sort'; - $group = views_ui_render_section($form['sort'], array('name', 'sortorder', 'options'), array(t('Field'), t('Order'), t('Option')), 'sort criteria', $collapsed); - - $group .= views_ui_render_section_add($form['sort']['add'], array('id', 'button'), t('Add criteria')); - $output .= theme('fieldset', array('#title' => t('Sort Criteria'), '#children' => $group, - '#collapsible' => true, '#collapsed' => $collapsed,)); - - $output .= drupal_render($form, false); - return $output; -} - -/** - * Render one of the dynamic sections on our form. - */ -function views_ui_render_section(&$form, $items, $header, $section, &$collapsed) { - // always do the buttons - $items = array_merge($items, array('delete', 'top', 'up', 'down', 'bottom')); - $num_items = count($items); - - $order = ($form['order']['#value'] != '' - ? explode(',', $form['order']['#value']) - : array()); - - $count = count($order) - 1; - foreach ($order as $key => $i) { - $row = array(); - foreach ($items as $item) { - if (($key == 0 && ($item == 'up' || $item == 'top')) || - ($key == $count && ($item == 'down' || $item == 'bottom'))) { - $form[$i][$item]['#printed'] = true; - $row[] = ' '; // array('data' => ' ', 'width' => 16); - } - else { - $row[] = drupal_render($form[$i][$item], false); - } - } - $rows[] = $row; - if (isset($form[$i]['help'])) { - $rows[] = array(array('data' => drupal_render($form[$i]['help']), 'colspan' => $num_items)); - } - } - if (!$rows) { - $rows[] = array(array('data' => t('This view currently has no %s defined.', array('%s' => $section)), 'colspan' => $num_items)); - $collapsed = true; - } - - $header[] = array('data' => t('Ops'), 'colspan' => 5); - return theme('table', $header, $rows) . "
"; -} - -/** - * Render the add buttons for one of the dynamic sections on our form. - */ -function views_ui_render_section_add(&$form, $items, $label) { - foreach ($items as $item) { - $row[] = drupal_render($form[$item], false); - } - $rows[] = $row; - - $header = array(array('data' => $label, 'colspan' => count($items))); - return theme('table', $header, $rows) . "
"; -} - -/** - * Validate that a view sent via form is OK. - */ -function views_edit_view_validate($form_id, $view, $form) { - $op = $view['op']; - - if ($op != t('Save') && $op != t('Save and edit')) { - return; // only validate on saving! - } - - if ($view['vid']) { - $changed = db_result(db_query("SELECT changed FROM {view_view} WHERE vid = %d", $view['vid'])); - if ($changed && $view['changed'] != $changed) { - form_set_error('', t('Another user has modified this view, unable to save. You can get this error by using the Back button to re-edit a view after saving one; if you do this, be sure to Reload before making any changes!')); - return; - } - } - - if (!$view['name']) { - form_error($form['basic-info']['name'], t('View name is required.')); - } - - // view name must be alphanumeric or underscores, no other punctuation. - if (preg_match('/[^a-zA-Z0-9_]/', $view['name'])) { - form_error($form['basic-info']['name'], t('View name must be alphanumeric or underscores only.')); - } - - // test uniqueness of name - $vid = db_result(db_query("SELECT vid FROM {view_view} WHERE name='%s'", $view['name'])); - if ($vid && $vid != $view['vid']) { - form_error($form['basic-info']['name'], t('View name already in use.')); - } - - if ($view['page']) { - if ($view['use_pager'] && !$view['nodes_per_page']) { - form_error($form['page-info']['nodes_per_page'], t('Nodes per page cannot be 0 if using the pager.')); - } - } - - if ($view['block'] && $view['nodes_per_block'] < 1) { - form_error($form['block-info']['nodes_per_block'], t('If being used as a block, Nodes Per Block must be positive.')); - } - - // validation based on type: - - $plugins = _views_get_style_plugins(); - if ($view['page']) { - $validator = $plugins[$view['page_type']]['validate']; - if (function_exists($validator)) { - $validator('page', $view, $form); - } - } - - if ($view['block']) { - $validator = $plugins[$view['block_type']]['validate']; - if (function_exists($validator)) { - $validator('block', $view, $form); - } - } - - foreach (array('field', 'argument', 'sort', 'filter') as $type) { - $function = "_views_get_$type" . 's'; - $info = $function(); - if (is_array($view[$type])) { - foreach ($view[$type] as $key => $data) { - if (!is_numeric($key)) { - continue; // some non-data data is in here. - } - $validator = $info[$data['id']]['validate']; - if (function_exists($validator)) { - $validator($data, $view, $form); - } - } - } - } -} - -function views_ui_reorder(&$view) { - // re-order things as they were ordered on the form. - $order = $view['order'] != '' ? explode(',', $view['order']) : array(); - foreach ($order as $position => $key) { - $placeholder[] = $view[$key]; - } - $view = $placeholder; -} - -/** - * Handle submit buttons on a view form. - */ -function views_edit_view_submit($form_id, $form) { - $view = (object) $form; - - // Transform any data that requires it here. - $view->access = array_keys(array_filter($view->access)); - - // ensure for MYSQL 5 irritation reasons. - $view->nodes_per_page = intval($view->nodes_per_page); - $view->nodes_per_block = intval($view->nodes_per_block); - $view->menu_tab_weight = intval($view->menu_tab_weight); - - // re-order things as they were ordered on the form. - foreach (array('field', 'argument', 'filter', 'sort', 'exposed_filter') as $section) { - views_ui_reorder($view->$section); - } - - _views_save_view($view); - menu_rebuild(); - if ($form['vid']) { - drupal_set_message(t('View successfully saved.')); - } - else { - drupal_set_message(t('View successfully added.')); - } - - if ($form['op'] == t('Save')) { - return 'admin/build/views'; - } - -} - -/** - * Validate a view with a type: list. - */ -function views_ui_plugin_validate_list($type, $view, $form) { - // list (and table) modes require there to be at least 1 field active. - if (is_array($view['field'])) { - $fields = array_filter(array_keys($view['field']), 'is_numeric'); - } - if (!$fields) { - form_error($form["$type-info"][$type . '_type'], t('List and Table types require at least one field.')); - } - - if (isset($view['field']['count'])) { - $defaultsort = false; - for ($i = 0; $i < $view['field']['count']; $i++) { - if ($view['field'][$i]['defaultsort']) { - if ($defaultsort) { - form_error($form['field'][$i]['defaultsort'], t('You can only set on Default Sort on one field.')); - break; - } - $defaultsort = true; - } - } - } -} - -/** - * Validate a view with type: table. - */ -function views_ui_plugin_validate_table($type, $view, $form) { - // pass thru to list cause for now they're the same. - return views_ui_plugin_validate_list($type, $view, $form); -} -// --------------------------------------------------------------------------- -// View creator tool - -/* - * Get a true/false. - */ -function views_tf($val) { - return ($val ? 'TRUE' : 'FALSE'); -} - -/* - * This function creates view code for a view. - */ -function views_create_view_code($vid) { - $view = _views_load_view($vid); - if (!$view) { - return t("View '%vid' not found.", array('%vid' => $vid)); - } - - $requires = array(); - - $output = " \$view = new stdClass();\n"; - $output .= " \$view->name = " . var_export($view->name, true) . ";\n"; - $output .= " \$view->description = " . var_export($view->description, true) . ";\n"; - $output .= " \$view->access = " . var_export($view->access, true) . ";\n"; - if (user_access('use PHP for block visibility')) { - $output .= " \$view->view_args_php = " . var_export($view->view_args_php, true) . ";\n"; - } - // page items - if ($view->page) { - $output .= " \$view->page = " . views_tf($view->page) . ";\n"; - $output .= " \$view->page_title = " . var_export($view->page_title, true) . ";\n"; - $output .= " \$view->page_header = " . var_export($view->page_header, true) .";\n"; - $output .= " \$view->page_header_format = " . var_export($view->page_header_format, true) . ";\n"; - $output .= " \$view->page_footer = " . var_export($view->page_footer, true) .";\n"; - $output .= " \$view->page_footer_format = " . var_export($view->page_footer_format, true) . ";\n"; - $output .= " \$view->page_empty = " . var_export($view->page_empty, true) .";\n"; - $output .= " \$view->page_empty_format = " . var_export($view->page_empty_format, true) . ";\n"; - $output .= " \$view->page_type = " . var_export($view->page_type, true) . ";\n"; - $output .= " \$view->url = " . var_export($view->url, true) . ";\n"; - $output .= " \$view->use_pager = " . views_tf($view->use_pager) . ";\n"; - $output .= " \$view->nodes_per_page = " . var_export($view->nodes_per_page, true) . ";\n"; - if ($view->menu) { - $output .= " \$view->menu = " . views_tf($view->menu) . ";\n"; - $output .= " \$view->menu_title = " . var_export($view->menu_title, true) . ";\n"; - $output .= " \$view->menu_tab = " . views_tf($view->menu_tab) . ";\n"; - $output .= " \$view->menu_tab_default = " . views_tf($view->menu_tab_default) . ";\n"; - $output .= " \$view->menu_tab_weight = " . var_export($view->menu_tab_weight, true) . ";\n"; - } - } - if ($view->block) { - $output .= " \$view->block = " . views_tf($view->block) . ";\n"; - $output .= " \$view->block_title = " . var_export($view->block_title, true) . ";\n"; - $output .= " \$view->block_header = " . var_export($view->block_header, true) . ";\n"; - $output .= " \$view->block_header_format = " . var_export($view->block_header_format, true) . ";\n"; - $output .= " \$view->block_footer = " . var_export($view->block_footer, true) . ";\n"; - $output .= " \$view->block_footer_format = " . var_export($view->block_footer_format, true) . ";\n"; - $output .= " \$view->block_empty = " . var_export($view->block_empty, true) .";\n"; - $output .= " \$view->block_empty_format = " . var_export($view->block_empty_format, true) . ";\n"; - $output .= " \$view->block_type = " . var_export($view->block_type, true) . ";\n"; - $output .= " \$view->nodes_per_block = " . var_export($view->nodes_per_block, true) . ";\n"; - $output .= " \$view->block_more = " . views_tf($view->block_more) . ";\n"; - $output .= " \$view->block_use_page_header = " . views_tf($view->block_use_page_header) . ";\n"; - $output .= " \$view->block_use_page_footer = " . views_tf($view->block_use_page_footer) . ";\n"; - $output .= " \$view->block_use_page_empty = " . views_tf($view->block_use_page_empty) . ";\n"; - } - - $output .= " \$view->sort = array (\n"; - foreach ($view->sort as $sort) { - $output .= " array (\n"; - $fieldbits = explode('.', $sort['field']); - $output .= " 'tablename' => " . var_export($fieldbits[0], true) . ",\n"; - $output .= " 'field' => " . var_export($fieldbits[1], true) . ",\n"; - $output .= " 'sortorder' => " . var_export($sort['sortorder'], true) . ",\n"; - $output .= " 'options' => " . var_export($sort['options'], true) . ",\n"; - $output .= " ),\n"; - $requires[$fieldbits[0]] = 1; - } - $output .= " );\n"; - - $output .= " \$view->argument = array (\n"; - foreach ($view->argument as $argument) { - $output .= " array (\n"; - $output .= " 'type' => " . var_export($argument['type'], true) . ",\n"; - $output .= " 'argdefault' => " . var_export($argument['argdefault'], true) . ",\n"; - $output .= " 'title' => " . var_export($argument['title'], true) . ",\n"; - $output .= " 'options' => " . var_export($argument['options'], true) . ",\n"; - $output .= " 'wildcard' => " . var_export($argument['wildcard'], true) . ",\n"; - $output .= " 'wildcard_substitution' => " . var_export($argument['wildcard_substitution'], true) . ",\n"; - $output .= " ),\n"; - } - $output .= " );\n"; - - $output .= " \$view->field = array (\n"; - foreach ($view->field as $field) { - $output .= " array (\n"; - $output .= " 'tablename' => " . var_export($field['tablename'], true) . ",\n"; - $output .= " 'field' => " . var_export($field['field'], true) . ",\n"; - $output .= " 'label' => " . var_export($field['label'], true) . ",\n"; - if ($field['handler']) { - $output .= " 'handler' => " . var_export($field['handler'], true) . ",\n"; - } - if ($field['sortable']) { - $output .= " 'sortable' => " . var_export($field['sortable'], true) . ",\n"; - } - if ($field['defaultsort']) { - $output .= " 'defaultsort' => " . var_export($field['defaultsort'], true) . ",\n"; - } - if ($field['options']) { - $output .= " 'options' => " . var_export($field['options'], true) . ",\n"; - } - $output .= " ),\n"; - $requires[$field['tablename']] = 1; - } - $output .= " );\n"; - - $output .= " \$view->filter = array (\n"; - foreach ($view->filter as $filter) { - $output .= " array (\n"; - $fieldbits = explode('.', $filter['field']); - $output .= " 'tablename' => " . var_export($fieldbits[0], true) . ",\n"; - $output .= " 'field' => " . var_export($fieldbits[1], true) . ",\n"; - $output .= " 'operator' => " . var_export($filter['operator'], true) . ",\n"; - $output .= " 'options' => " . var_export($filter['options'], true) . ",\n"; - $output .= " 'value' => " . var_export($filter['value'], true) . ",\n"; - $output .= " ),\n"; - $requires[$fieldbits[0]] = 1; - } - $output .= " );\n"; - - $output .= " \$view->exposed_filter = array (\n"; - foreach ($view->exposed_filter as $filter) { - $output .= " array (\n"; - $fieldbits = explode('.', $filter['field']); - $output .= " 'tablename' => " . var_export($fieldbits[0], true) . ",\n"; - $output .= " 'field' => " . var_export($fieldbits[1], true) . ",\n"; - $output .= " 'label' => " . var_export($filter['label'], true) . ",\n"; - $output .= " 'optional' => " . var_export($filter['optional'], true) . ",\n"; - $output .= " 'is_default' => " . var_export($filter['is_default'], true) . ",\n"; - $output .= " 'operator' => " . var_export($filter['operator'], true) . ",\n"; - $output .= " 'single' => " . var_export($filter['single'], true) . ",\n"; - $output .= " ),\n"; - $requires[$fieldbits[0]] = 1; - } - $output .= " );\n"; - $output .= " \$view->requires = array(" . implode(', ', array_keys($requires)) . ");\n"; - $output .= " \$views[\$view->name] = \$view;\n"; - return $output; -} - -