Commit 39de66cc authored by tim.plunkett's avatar tim.plunkett

Issue #1800178 by tim.plunkett: Move the documentation out of code and into the handbook.

parent d4926f0b
Information about upgrading existing views from Drupal 6 to Drupal 7 is located
in the module's advanced help under api upgrading.
Welcome to Views 3. Please see the advanced help for more information.
If you're having trouble installing this module, please ensure that your
tar program is not flattening the directory tree, truncating filenames
or losing files.
Installing Views:
Place the entirety of this directory in sites/all/modules/views
You must also install the CTools module (http://www.drupal.org/project/ctools) to use Views.
Navigate to administer >> build >> modules. Enable Views and Views UI.
If you're new to Views, try the Simple Views module which can create some
often used Views for you, this might save you some time.
Here you can find many modules extending the functionality of Views:
http://drupal.org/taxonomy/term/89
- If the interface text is *bolded*, it got strong tags.
- If it's a button they need to click, that's *bold* too.
- If the text is not bolded (ex: links to click, options to check), it
got /italicized/.
- If it's user-entered text it got 'single quotes'.
The views module allows administrators and site designers to create, manage, and display lists of content. Each list managed by the views module is known as a "view", and the output of a view is known as a "display". Displays are provided in either block or page form, and a single view may have multiple displays. Optional navigation aids, including a system path and menu item, can be set for each page-based display of a view. By default, views may be created that list content (a <em>Node</em> view type), content revisions (a <em>Node revisions</em> view type) or users (a <em>User</em> view type). A view may be restricted to members of specific user roles, and may be added, edited or deleted at the <a href="base_url:admin/structure/views">views administration page</a>.
For more technical users, views can be understood as a user interface to compose SQL-queries and to pull information (Content, Users, etc.) from the database and show it on a screen as desired.
The "building block" design of the views system provides power and flexibility, allowing parameters to be specified only when needed. While an advanced view may use all of available parameters to create complex and highly interactive applications, a simple content listing may specify only a few options. All views rely on a conceptual framework that includes:
<ul>
<li><a href="topic:views/field">Fields</a>, or the individual pieces of data being displayed. Adding the fields <em>Node: Title</em>, <em>Node: Type</em>, and <em>Node: Post date</em> to a node view, for example, includes the title, content type and creation date in the displayed results </li>
<li><a href="topic:views/relationship">Relationships</a>, or information about how data elements relate to one another. If relationship data is available, like that provided by a CCK <em>nodereference</em> field, items from a related node may be included in the view </li>
<li><a href="topic:views/argument">Arguments</a>, or additional parameters that dynamically refine the view results, passed as part of the path. Adding an argument of <em>Node: Type</em> to a node view with a path of "content", for example, dynamically filters the displayed items by content type. In this example (shown with Clean URLs enabled), accessing the view through the path "<em>http://www.example.com/content/page</em>" displays all posts of the type "page", the path "<em>http://www.example.com/content/story</em>" displays all posts of the type "story", and "<em>http://www.example.com/content</em>" displays all posts regardless of type) </li>
<li><a href="topic:views/sort">Sort criteria</a>, which determine the order of items displayed in the view results. Adding the sort criteria <em>Node: Post date</em> (in descending order) to a node <em>view</em>, for example, sorts the displayed posts in descending order by creation date </li>
<li><a href="topic:views/filter">Filters</a>, which limit items displayed in the results. Adding the filter <em>Node: Published</em> (and setting it equal to "Published") to a node view, for example, prevents unpublished items from being displayed</li>
<li><a href="topic:views/display">Displays</a>, which control where the output will be seen. Every view has a default display, which doesn't actually display the view anywhere, but is used to hold the default settings for the view, and is used when the view is called programmatically if another display is not specified. Much more useful to users are the <a href="topic:views/display-page">page</a> display, which gives a view a path and allows it to be the primary content of a page, or the <a href="topic:views/display-block">block</a> display which allows it to appear as secondary content on other pages.</li>
<li><a href="topic:views/header">Header</a>, which allow you to add by default one or more text area above the views output. </li>
<li><a href="topic:views/footer">Footer</a>, which allow you to add by default one or more text area beneath the views output. </li>
<li>The <a href="topic:views/footer">Emtpy Text</a> content will be displayed, when you choose in the Arguments Section "Action to take if argument is not present" the option "Display empty text".</li>
</ul>
Parallels between the components in the Views interface and an sql query:
<table>
<thead>
<tr>
<th>Sql Query</th>
<th>Views Component</th>
<tr>
</thead>
<tr>
<td>SELECT n.title, u.name</td>
<td>fields</td>
</tr>
<tr>
<td>FROM {node} n base table</td>
<td>view type</td>
</tr>
<tr>
<td>INNER JOIN {users} u ON n.uid = u.uid</td>
<td>relationship</td>
</tr>
<tr>
<td>WHERE n.status = 1</td>
<td>filter</td>
</tr>
<tr>
<td>AND u.uid = arg(1)</td>
<td>argument</td>
</tr>
<tr>
<td>ORDER BY n.changed DESC</td>
<td>sort</td>
</tr>
</table>
In the category <strong>Other</strong> you have different options to set Advanced configurations in your View.
<strong>Machine Name:</strong>
You can change the default machine name of the view.
<strong>Comment: No comment</strong>
You can Use the comment option to write comments for your Views, the comments are only shown in the Views UI. Comment your Display for other Maintainer
<strong>Use AJAX: No</strong>
If set, this view will use an AJAX mechanism for paging, table sorting and exposed filters. This prevents the entire page from refreshing. It is not recommended that you use this if this view is the main content of the page as it will prevent deep linking to specific pages, but it is very useful for side content. Block displays require this setting to be ON if exposed filters are being used.
<strong>Hide attachments in summary: No</strong>
<strong>Use aggregation: No</strong>
All fields that are selected for grouping will be collapsed to one record per distinct value. Other fields which are selected for aggregation will have the function run on them. For example, you can group nodes on title and count the number of nids in order to get a list of duplicate titles.
For more Information how aggregation work see the "Use Aggregation" Help Page
<strong>Query settings: Settings</strong>
Here can you set advanced Settings for the SQL Settings
<ul>
<li><strong>Disable SQL rewriting</strong></li>
<li><strong>Distinct: No</strong></li>
This will make the view display only distinct items. If there are multiple identical items, each will be displayed only once. You can use this to try and remove duplicates from a view, though it does not always work. Note that this can slow queries down, so use it with caution.
<li><strong>Use Slave Server</strong></li>
<li><strong>Query Comment</strong></li>
</ul>
<strong>Field Language: Current user's language</strong>
<strong>Caching: None</strong>
You can choose a "Time-based" Caching if you want. With it you get the option to choose the length of time raw query results should be cached and "The length of time rendered HTML output should be cached."
<strong>Link display: Page</strong>
<strong>CSS class: None</strong>
You can define some own CSS Classes for your View
<strong>Theme: Information</strong>
Clicking on the "Theme: Information" link provides you with a listing of all posiible theming files. The highlighted files are the ones Views is currently using. All other filenames are suggested templates.
For more Information see the <a href="/help/views/analyze-theme" title="Theme Information" >"Theme information"</a> Page
In Views 3 you can set Advanced Style Settings, they help you to insert markup of your own from the Views UI, so that you can fairly easily override the default markup without having to restyle via templates.
<ul>
<li> Customize field HTML</li>
With Customize field HTML you can generate html tags around the field.
<li>Customize label HTML</li>
Here you can generate html tags around the label of a field.
<li>Customize field and label wrapper HTML</li>
Here you can generate html tags around the wrapper of the label and field
</ul>
<a href="path:images/views3-semanticviews.png"><img src="path:images/views3-semanticviews.png" /></a>
Usage example
In a view with a field:
<ol>
<li>Configure the field. (Click on the field.)</li>
<li>In the modal that opens, scroll down to <strong>Style Settings</strong>.</li>
<li>Choose one or more of the three <i>Customize</i> options. This will reveal a dropdown menu where you can choose from one or more HTML tags to use on that field and allow you to add a CSS class specific to that field should you desire.</li>
<li>Decide if you want to keep the Views default classes. Unchecking this box means your markup is *it*.</li>
</ol>
In Views 2 you needed for Style Settings the <a href="http://drupal.org/project/semanticviews">Semantic Views</a> Modul, now the Semantic Views module has been mostly incorporated into Views 3.x. Semantic Views is still around for people who need it, though. For some details on how the original module is different from the Views implementation, please see <a href="http://drupal.org/node/1013876">this issue</a>.
See: <a href="topic:views/group-by">Group by</a>
Modifying default values of a views exposed form is tricky, because FAPI was not designed to work with GET forms. One consequence is that it often can't tell if textfields (there are others) were submitted or not.
As a consequence, it *always* thinks the value was submitted, even if it was not. To fix that, Views modifies $form_state['input'][$identifier] with the default value if $form_state['input'][$identifier] was not set. In order to modify the default value in an alter, you need to do this:
<pre>
&lt;?php
if (empty($form_state['view']->exposed_input[$identifier])) .
{ $form_state['input'][$identifier] = $default_value; }
?&gt;
</pre>
where $identifier is the particular filter for which you want to change the default value, and $default_value is the new default value you want to set.
If you use a hook_form_FORM_ID_alter or hook_form_alter, you can modify exposed filters on the fly based on information that is external to Views. For example, I modified the exposed filter of a form to set a taxonomy term ID based on the user's GeoIP.
To do this, I used the following function, where geoip_redirect_get_tid() loads the relevant term id based on the user's current ip_address():
<pre>
&lt;?php
function MODULENAME_form_views_exposed_form_alter(&$form, $form_state) {
if(strpos($form['#id'], 'volunteer-directory') !== FALSE) {
$city_tid = geoip_redirect_get_tid();
if(is_numeric($city_tid) && $city_tid != 7660) {
if (empty($form_state['view']->exposed_input['tid'])) {
$form_state['input']['tid'] = $city_tid;
}
}
}
}
?&gt;
</pre>
<p>Clicking on the "Theme: Information" link provides you with a listing of all posiible theming files. The highlighted files are the ones Views is currently using. All other filenames are suggested templates.</p>
<p>You may use any of the following possible theme files to modify individual parts of your view. In total, there are four parts to theming a view.</p>
<ul>
<li> The <strong>display</strong> theme is usually views-view.tpl.php and it largely controls the decorations around a view; where the header, footer, pager, more link, feed icon, etc, will be placed. </li>
<li> The <strong>style</strong> will control how all of the results of the display are put together. It may be as simple as just displaying all of the rows, or it may be a complex table generator or something in between. </li>
<li> The <strong>row</strong> style controls each individual row; not all styles utilize the row style (notably the table), but most others do.
<li> Finally, <strong>field</strong> themes allow you to override the look and even the data of each individual field, if the style uses fields. The actual template the system will use should be hilighted in <strong>bold</strong>.</li>
</ul>
<div class="help-box" style="text-align:center">
<a href="path:images/style-breakdown-large.png"><img src="path:images/style-breakdown.png" /></a>
<em>A breakdown of View output</em>
</div>
<p>The link to the left of each type will give you information about the default template used for that type. You may cut and paste this and place it in your theme with the appropriate template, or you may copy the base file from the views/theme directory (or, if provided by a module, from the module's directory). <strong>It is important that you clear the theme registry cache every time you add a new template, or the new template will not be picked up.</strong></p>
<p><strong>Important note:</strong> You place your custom template files in your theme directory, <strong>not views/theme</strong>. This is always true of theming with Drupal.
<p>In addition to this tool, the very useful <a href="http://drupal.org/project/devel">devel</a> module contains a tool called the "Theme developer" which does a good job of visually showing you which areas of your site use which themes. Be careful with it, though, as the theme developer causes the Views edit page to break.</p>
<p>Also, this feature will only work properly with Drupal 6.3 and later; prior to Drupal 6.3 <a href="http://drupal.org/node/241570">this patch</a> will be required.</p>
Views can be stored in the database, which is typical of smaller sites and hobby sites. However, Views may also be stored directly in the code as "default" views, (which simply means they're available by default). Modules often come with views that are specific to the module data, but it's also possible -- and <b>highly</b> recommended -- that sites which have separate "development" and "production" sites export their views into default views in a site-specific module. This makes it very easy to transfer views from dev to production without making database changes.
<h3>Creating a module</h3>
First, create a directory in <em>sites/all/modules</em> for your new module. Call it whatever you like, but for this example we will call it <em>mymodule</em>.
In this directory, create a <em>mymodule.module</em> file. It can be empty for now, but it should at least contain an opening PHP tag:
<pre>&lt;?php
</pre>
It should not contain a closing ?&gt; tag, as the closing ?&gt; tag is not required and anything AFTER the closing tag, such as a space or a linefeed, will be displayed directly to the browser and can potentially cause problems.
The .module file will contain functions and drupal hooks. Hooks are specially named functions that Drupal will call in order to get your module's response at certain times while generating pages. The only function you will need for this exercise is the 'views_api' hook that tells Views that this module supports the Views API and what version:
<pre>function mymodule_views_api() {
return array('api' => 2.0);
}
</pre>
For other uses you may well add additional functions.
Second, you need to create a <em>mymodule.info</em> file:
<pre>name = My module
description = My site specific module.
core = 6.x
</pre>
Once you have these two files set up, you should be able to activate your new module at the <em>Administer >> Modules</em> page.
<h3>Exporting your views</h3>
The easiest way to do this is to activate the 'views_export' module, and navigate to <em>Administer >> Structure >> Views >> Tools >> Bulk export</em> Place a check next to each view that you want in your module, type the module name into the text field, and click export. This will create the entire <em>hook_views_default_views()</em> function for you.
You can also export individual views. If you do this, keep in mind that this export does not include the line that adds the exported $view into the larger $views array:
<pre>$views[$view->name] = $view</pre>
To place this into your <em>hook_views_default_views()</em> you will need to place that after the view, and make sure the function returns $views at the end.
<h3>Placing your exported views into your module</h3>
Cut and paste the entire output of the bulk export tool into mymodule.views_default.inc -- and be sure to put a &lt;?php at the top of the file so that the webserver knows that it's PHP code! Then visit the Views tools page and clear the Views cache. Your views should now be listed as <b>Overridden</b> on the view list page. If you <b>revert</b> these views, they will be removed from the database, but will remain in code.
<h3>Theming your views in your module</h3>
You can theme these views in the module and not need to rely on the theme to do this at all; and in fact, the theme can continue to override these just like it ordinarily would, even if your module provides a theme. This is very useful for distributing a module where the view needs to look "just so."
To do this, you need to implement <em>hook_theme()</em> in your module:
<pre>function mymodule_theme($existing) {
return array(
'views_view__viewname__displayid' => array (
'arguments' => array('view' => NULL),
'template' => 'views-view--viewname--displayid',
'base hook' => 'views_view',
'path' => drupal_get_path('module', 'mymodule'),
),
);
}
</pre>
There are a small number of gotchas in doing this that you must be aware of.
<ol>
<li>When referring to a template filename, you always use dashes in the name. i.e, <em>views-view--viewname--displayid.tpl.php</em>. However, when referring to the hook or function names, you use underscores instead of dashes. i.e, <em>views_view</em> and <em>views_view__viewname__displayid</em></li>
<li>The 'arguments' change based upon which of the 3 types you're overriding. There's the 'display', the 'style' and the 'row' style. The above code is assuming the display, which is usually just <em>views_view</em>. Here are the possibilities:
<pre>display: array('view_array' => array(), 'view' => NULL),
style: array('view' => NULL, 'options' => NULL, 'rows' => NULL, 'title' => NULL),
row: array('view' => NULL, 'options' => NULL, 'row' => NULL, 'field_alias' => NULL),
field: array('view' => NULL, 'field' => NULL, 'row' => NULL),
</pre>
Be sure to use the right arguments line or the theme system will not properly translate.
</li>
<li>The 'template' line should never include the extension, so drop the .tpl.php from it.</li>
<li>You need to make sure that the Views preprocess functions get registered. The 'base hook' line in the definition does that, but it can only do it if it comes after the Views registration, which actually happens very late in theme building. 99% of the time, your module will come before Views. You have two choices to deal with this:
<ol>
<li>Set your module's weight to 11 or higher in the database. Views' weight is 10. You can make this happen automatically when the module is first installed by creating a mymodule.install file and using this code:
<pre>function mymodule_install() {
db_query("UPDATE {system} SET weight = 11 WHERE name = 'mymodule'");
}
</pre>
If you use this method, the <em>base hook</em> should be set to the name of the original template being used. i.e, if this is a variate of views-view-list.tpl.php, this should be 'views_view_list'.
</li>
<li>You can also just force it to list the preprocessors without actually having to detect them. This doesn't require modifying your module's weight, which is not always possible, you can insert this code into the array:
<pre> 'preprocess functions' => array(
'template_preprocess',
'template_preprocess_views_view',
'mymodule_preprocess_views_view__viewname_displayid',
),
</pre>
The first one is the global 'template_preprocess' function which all templates utilize. It does some basic things such as setting up $zebra and a few other items. See <a href="http://api.drupal.org/api/function/template_preprocess/6">api.drupal.org</a> for specifics.
The second one is the plugin specific preprocess. Like 'base hook' it should conform to the name used by the original template. i.e, if the original template was <em>views-view-list.tpl.php</em> then that preprocess function would be named <em>template_preprocess_views_view_list</em>.
The third one is your module's preprocess function, if it needs one. In general, you probably will not need one, and you should only attempt to use one if you are reasonably familiar with the concept of preprocess functions and Drupal's theme system in general. See Drupal's theme documentation for more information.
</li>
</ol>
</li>
<li>
If you leave the path blank the template file will be searched for in "./" which is the Drupal install base path.
</li>
</ol>
For the new table defined by the Node example module to be understood by the views module you need to create a node_example.views.inc file that describes the table and its relationships to the rest of the database. In order for views to know that this file is to be loaded you need to implement hook_views_api. This is done by adding the following function into your node_example.module file
<pre>
&lt;?php
/**
* Implements hook_views_api().
*
* This tells drupal that there is Views integration file named
* module-name.views.inc
*/
function node_example_views_api() {
// Note that you can include 'path' in this array so that your views.inc
// file can be stored in a different location.
return array(
'api' => 2.0
);
}
?&gt;
</pre>
Below is the contents of a simple node_example.views.inc file that allows you to create views that include the new color and quantity information.
<pre>
&lt;?php
/**
* This file is used to tell the views module about the new node_example table.
*
* Database definition:
* @code
* CREATE TABLE node_example (
* vid int(10) unsigned NOT NULL default '0',
* nid int(10) unsigned NOT NULL default '0',
* color varchar(255) NOT NULL default '',
* quantity int(10) unsigned NOT NULL default '0',
* PRIMARY KEY (vid, nid),
* KEY `node_example_nid` (nid)
* )
* @endcode
*/
function node_example_views_data() {
// Basic table information.
// ----------------------------------------------------------------
// node_example table
// New group within Views called 'Example'
// The group will appear in the UI in the dropdown tha allows you
// to narrow down which fields and filters are available.
$data = array();
$data['node_example']['table']['group'] = t('Example');
// Let Views know that our example table joins to the 'node'
// base table. This means it will be available when listing
// nodes and automatically make its fields appear.
//
// We also show up for node revisions.
$data['node_example']['table']['join'] = array(
'node_revisions' => array(
'left_field' => 'vid',
'field' => 'vid',
),
'node' => array(
'left_field' => 'vid',
'field' => 'vid',
),
);
// quantity
$data['node_example']['quantity'] = array(
'title' => t('Quantity'),
'help' => t('Quantity of items.'),
'field' => array(
'id' => 'numeric',
'click sortable' => TRUE,
),
'filter' => array(
'id' => 'numeric',
),
'sort' => array(
'id' => 'standard',
),
);
// Color
$data['node_example']['color'] = array(
'title' => t('Color'),
'help' => t('Color of item.'),
'field' => array(
'id' => 'standard',
'click sortable' => TRUE,
),
'filter' => array(
'id' => 'string',
),
'argument' => array(
'id' => 'string',
),
'sort' => array(
'id' => 'standard',
),
);
return $data;
}
?&gt;
</pre>
Some notes on usage:
Within Views, click on the Add tab. You have a number of type options here. Normally you would select either 'Node' (if you only want to display information on current nodes) or 'Node revision' (if you want to display information on all revisions of the nodes)
With this configuration you always pull out of the database, data for every single node, whether or not it has color and quantity information. To display information on just those nodes that have color and quantity information you can use a filter so that only nodes which don't have a NULL color or a NULL quantity are displayed.
<h3>Type/relationship extension</h3>
When your tables have first class data, you will often need to have own View types and View relationships defined. With the current node_example table this isn't required although I try to justify it below on an efficiency basis. See [[http://groups.drupal.org/node/17236#comment-58980|this discussion]] as to why it isn't justified.
Pulling data out of the database for every node when you only want data for the new Example node type is inefficient. To reduce the initial data extraction to just that relating to the new Example nodes requires that you make the node_example table the base table. This can be done by adding the following code into the node_example.views.inc file just before the 'return $data;'
<pre>
&lt;?php
// **** Begin optional extra for type and relationships ****
// Use node_example as a new base table
// by creating a new views type called 'Node example'
// This allows it to be selected as the 'view type'
// when you initially add a new view.
$data['node_example']['table']['base'] = array(
'field' => 'vid',
'title' => t('Node example'),
'help' => t("Node example type with color and quantity information."),
'weight' => -9,
);
// When using the new 'Node example' type you need to use relationships
// to access fields in other tables.
// Relationship to the 'Node revision' table
$data['node_example']['vid'] = array(
'title' => t('Node revision'),
'help' => t('The particular node revision the color and quantity is attached to'),
'relationship' => array(
'label' => t('Node revision'),
'base' => 'node_revisions',
'base field' => 'vid',
// This allows us to not show this relationship if the base is already
// node_revisions so users won't create circular relationships.
'skip base' => array('node', 'node_revisions'),
),
);
// Relationship to the 'Node' table
$data['node_example']['nid'] = array(
'title' => t('Node'),
'help' => t('The particular node the color and quantity is attached to'),
'relationship' => array(
'label' => t('Node'),
'base' => 'node',
'base field' => 'nid',
// This allows us to not show this relationship if the base is already
// node so users won't create circular relationships.
'skip base' => array('node', 'node_revisions'),
),
);
// **** End optional extra for type and relationships ****
?&gt;
</pre>
The above code adds a new 'Node example' to the view types that can be selected within the Add tab window of views. Selecting this sets the node_example table to be the base table.
If you select 'Node example' as view type, when you initially go into the edit window of views you will find the only fields available are the color and quantity fields. To get fields from other tables you need to add a relationship. Relationships may be found at the top in the same column as the fields.
Views allows handlers to output form elements, wrapping them automatically in a form, and handling validation / submission.
The form is multistep by default, allowing other modules to add additional steps, such as confirmation screens.
<h2>Implementation</h2>
A views handler outputs a special placeholder in render(), while the real form with matching structure gets added in views_form().
When the View is being preprocessed for the theme file, all placeholders get replaced with the rendered form elements.
The views handler can also implement views_form_validate() and views_form_submit().
<pre>
function render($values) {
return '&lt;!--form-item-' . $this-&gt;options['id'] . '--' . $this-&gt;view-&gt;row_index . '--&gt;';
}
function form_element_name() {
// Make sure this value is unique for all the view fields
return $this-&gt;options['id'];
}
function form_element_row_id($row_id) {
// You could use values from $this-&gt;view-&gt;result[$row_id]
// to provide complex row ids.
return $row_id;
}
function views_form(&$form, &$form_state) {
// The view is empty, abort.
if (empty($this-&gt;view-&gt;result)) {
return;
}
$field_name = $this-&gt;form_element_name();
$form[$field_name] = array(
'#tree' => TRUE,
);
// At this point, the query has already been run, so we can access the results
foreach ($this-&gt;view-&gt;result as $row_id => $row) {
$form_element_row_id = $this-&gt;form_element_row_id($row_id);
$form[$field_name][$form_element_row_id] = array(
'#type' => 'textfield',
'#title' => t('Your name'),
'#default_value' => '',
);
}
}
// Optional validate function.
function views_form_validate($form, &$form_state) {
$field_name = $this->form_element_name();
foreach ($form_state['values'][$field_name] as $row_id => $value) {
if ($value == 'Drupal') {
form_set_error($field_name . '][' . $row_id, "You can't be named Drupal. That's my name.");
}
}
}
// Optional submit function.
function views_form_submit($form, &$form_state) {
// Do something here
}
</pre>
The form is multistep by default, with one step: 'views_form_views_form'.
A "form_example" module could add a confirmation step by setting:
<pre>
$form_state['step'] = 'form_example_confirmation';
</pre>
in form_example_views_form_submit().
Then, views_form would call form_example_confirmation($form, $form_state, $view, $output) to get that step.
<b>Important:</b> You can fetch the Views object in form_alter and validate / submit hooks from the form state:
<pre>
$view = $form_state['build_info']['args'][0];
</pre>
<h2>Relevant Views functions</h2>
<ul>
<li>template_preprocess_views_view()</li>
<li>views_form()</li>
<li>views_form_views_form()</li>
<li>views_form_views_form_validate()</li>
<li>views_form_views_form_submit()</li>
<li>theme_views_form_views_form()</li>
</ul>
<h2>Hooks</h2>
<ul>
<li>hook_views_form_substitutions()</li>
</ul>
In Views areas (header, footer, empty-text) are pluggable, this means you can write your own php logic to place whatever you want.
<h3>Requirements</h3>
You should have read <a href="topic:views/api">API</a> and <a href="topic:views/api-tables">Tables API</a> to get a basic knowledge
how to extend views.
<h3>Create your own area handler</h3>
The first step is to tell views: Hey i want to add a new area handler.
Therefore you have to implement hook_views_data and add a new one. For example:
<pre>
function yourmodule_views_data() {
$data['views']['collapsible_area'] = array(
'title' =&gt; t('Collabsible Text area'),
'help' =&gt; t('Provide collabsible markup text for the area.'),
'area' =&gt; array(
'handler' =&gt; 'yourmodule_handler_collapsible_area_text',
),
);
}
</pre>
The second step is to write this handler. Therefore create a file called yourmodule_handler_collapsible_area_text.inc and
add it to the .info file of your module.
Then add content to your area file like this:
<pre>
class yourmodule_handler_collapsible_area_text extends views_handler_area_text {
function render($empty = FALSE) {
// Here you just return a string of your content you want.
if ($render = parent::render($empty)) {
$element = array(
'#type' =&gt; 'fieldset',
'#title' =&gt; t('Title'),
'#value' =&gt; $render,
);
$output = theme('fieldset', $element);
return $output;
}
}
}
</pre>
As on every handler you can add options so you can configure the behavior. If the area isn't shown yet in the views interface, please clear the cache :)
This diff is collapsed.
In order to take advantage of the changes in Drupal 7, Views has gone through several API changes.
Here's what you should know.
<h3>Handler registry</h3>
Views now uses Drupal's dynamic-loading code registry.
You can safely remove your implementations of hook_views_handlers(), since they are no longer used.
Please remember to specify the handlers in your module's .info file. For example:
<pre>
name = Example module
description = "Gives an example of a module."
core = 8.x
files[] = example.module
files[] = example.install
; Views handlers
files[] = includes/views/handlers/example_handler_argument_string.inc
</pre>
<h3>Removed handlers</h3>
Note that views_handler_filter_float has been removed.
This functionality is now handled by views_handler_filter_numeric.
There's no need for having a special handler any more, thanks to the new DB layer in Drupal 7.
views_handler_sort_formula has been removed.
Everyone who used it can extend from views_handler_sort, too.
<h3>Ctools dependency</h3>
Views requires ctools now, so it can use the dependency system of ctools.
The only thing you have to do is to remove views_process_dependency.
<h3>Changed add_where api</h3>
If your field is a plain sql field:
<pre>
$this->query->add_where($this->options['group'], "$this->tableAlias.$this->realField " . $this->operator . " '%s'", $this->value);
</pre>
has to be converted to
<pre>
$this->query->add_where($this->options['group'], "$this->tableAlias.$this->realField", $this->value, $this->operator);
</pre>
If your field is a complex where condition:
<pre>
$this->query->add_where($this->options['group'], "$upper($field) NOT LIKE $upper('%%%s')", $this->value);
</pre>
has to be converted to
<pre>
$placeholder = $this->placeholder();
$this->query->add_where_expression($this->options['group'], "$field LIKE $placeholder", array($placeholder => '%' . db_like($this->value)));
</pre>
placeholder() generates a automatic unique placeholder for you.
add_where with operator 'formula' can be converted to add_where_expression.
add_having with operator 'formula' can be converted to add_having_expression.
<h3>Changed place for display specific settings</h3>
In the new ui the new place for display settings is at the top of the second column.
Therefore use something like this code in your display plugin:
<pre>
$categories['block'] = array(
'title' => t('Block settings'),
'column' => 'second',
'build' => array(
'#weight' => -10,
),
);