views.api.php 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348
  1. <?php
  2. /**
  3. * @file
  4. * Describe hooks provided by the Views module.
  5. */
  6. /**
  7. * @mainpage Views 3 API Manual
  8. *
  9. * Much of this information is actually stored in the advanced help; please
  10. * check the API topic. This help will primarily be aimed at documenting
  11. * classes and function calls.
  12. *
  13. * Topics:
  14. * - @link views_lifetime The life of a view @endlink
  15. * - @link views_hooks Views hooks @endlink
  16. * - @link views_handlers About Views handlers @endlink
  17. * - @link views_plugins About Views plugins @endlink
  18. * - @link views_templates Views template files @endlink
  19. * - @link views_module_handlers Views module handlers @endlink
  20. */
  21. /**
  22. * @defgroup views_lifetime The life of a view
  23. * @{
  24. * This page explains the basic cycle of a view and what processes happen.
  25. *
  26. * @todo.
  27. * @}
  28. */
  29. /**
  30. * @defgroup views_handlers About Views handlers
  31. * @{
  32. * In Views, a handler is an object that is part of the view and is part of the
  33. * query building flow.
  34. *
  35. * Handlers are objects; much of the time, the base handlers will work, but
  36. * often you'll need to override the handler to achieve something meaningful.
  37. * One typical handler override will be views_handler_filter_operator_in which
  38. * allows you to have a filter select from a list of options; you'll need to
  39. * override this to provide your list.
  40. *
  41. * Handlers have two distinct code flows; the UI flow and the view building
  42. * flow.
  43. *
  44. * For the query flow:
  45. * - handler->construct()
  46. * - Create the initial handler; at this time it is not yet attached to a
  47. * view. It is here that you can set basic defaults if needed, but there
  48. * will be no knowledge of the environment yet.
  49. * - handler->set_definition()
  50. * - Set the data from hook_views_data() relevant to the handler.
  51. * - handler->init()
  52. * - Attach the handler to a view, and usually provides the options from the
  53. * display.
  54. * - handler->pre_query()
  55. * - Run prior to the query() stage to do early processing.
  56. * - handler->query()
  57. * - Do the bulk of the work this handler needs to do to add itself to the
  58. * query.
  59. *
  60. * Fields, being the only handlers concerned with output, also have an extended
  61. * piece of the flow:
  62. *
  63. * - handler->pre_render(&$values)
  64. * - Called prior to the actual rendering, this allows handlers to query for
  65. * extra data; the entire resultset is available here, and this is where
  66. * items that have "multiple values" per record can do their extra query for
  67. * all of the records available. There are several examples of this at work
  68. * in the code, see for example views_handler_field_user_roles.
  69. * - handler->render()
  70. * - This does the actual work of rendering the field.
  71. *
  72. * Most handlers are just extensions of existing classes with a few tweaks that
  73. * are specific to the field in question. For example,
  74. * views_handler_filter_in_operator provides a simple mechanism to set a
  75. * multiple-value list for setting filter values. Below,
  76. * views_handler_filter_node_type overrides the list options, but inherits
  77. * everything else.
  78. *
  79. * @code
  80. * class views_handler_filter_node_type extends views_handler_filter_in_operator {
  81. * function get_value_options() {
  82. * if (!isset($this->value_options)) {
  83. * $this->value_title = t('Node type');
  84. * $types = node_get_types();
  85. * foreach ($types as $type => $info) {
  86. * $options[$type] = $info->name;
  87. * }
  88. * $this->value_options = $options;
  89. * }
  90. * }
  91. * }
  92. * @endcode
  93. *
  94. * Handlers are stored in their own files and loaded on demand. Like all other
  95. * module files, they must first be registered through the module's info file.
  96. * For example:
  97. *
  98. * @code
  99. * name = Example module
  100. * description = "Gives an example of a module."
  101. * core = 7.x
  102. * files[] = example.module
  103. * files[] = example.install
  104. *
  105. * ; Views handlers
  106. * files[] = includes/views/handlers/example_handler_argument_string.inc
  107. * @endcode
  108. *
  109. * The best place to learn more about handlers and how they work is to explore
  110. * @link views_handlers Views' handlers @endlink and use existing handlers as a
  111. * guide and a model. Understanding how views_handler and its child classes work
  112. * is handy but you can do a lot just following these models. You can also
  113. * explore the views module directory, particularly node.views.inc.
  114. *
  115. * Please note that while all handler names in views are prefixed with views_,
  116. * you should use your own module's name to prefix your handler names in order
  117. * to ensure namespace safety. Note that the basic pattern for handler naming
  118. * goes like this:
  119. *
  120. * [module]_handler_[type]_[tablename]_[fieldname].
  121. *
  122. * Sometimes table and fieldname are not appropriate, but something that
  123. * resembles what the table/field would be can be used.
  124. *
  125. * See also:
  126. * - @link views_field_handlers Views field handlers @endlink
  127. * - @link views_sort_handlers Views sort handlers @endlink
  128. * - @link views_filter_handlers Views filter handlers @endlink
  129. * - @link views_argument_handlers Views argument handlers @endlink
  130. * - @link views_relationship_handlers Views relationship handlers @endlink
  131. * - @link views_area_handlers Views area handlers @endlink
  132. * @}
  133. */
  134. /**
  135. * @defgroup views_plugins About Views plugins
  136. *
  137. * In Views, a plugin is a bit like a handler, but plugins are not directly
  138. * responsible for building the query. Instead, they are objects that are used
  139. * to display the view or make other modifications.
  140. *
  141. * There are several types of plugins in Views:
  142. * - Display: Display plugins are responsible for controlling *where* a view
  143. * lives; that is, how they are being exposed to other parts of Drupal. Page
  144. * and block are the most common displays, as well as the ubiquitous 'master'
  145. * (or 'default') display.
  146. * - Style: Style plugins control how a view is displayed. For the most part
  147. * they are object wrappers around theme templates. Styles could for example
  148. * be HTML lists or tables.
  149. * - Row style: Row styles handle each individual record from the main view
  150. * table. The two included by default render the entire entity (nodes only),
  151. * or selected fields.
  152. * - Argument default: Argument default plugins allow pluggable ways of
  153. * providing default values for contextual filters (previously 'arguments').
  154. * This is useful for blocks and other display types lacking a natural
  155. * argument input. Examples are plugins to extract node and user IDs from the
  156. * URL.
  157. * - Argument validator: Validator plugins can ensure arguments are valid, and
  158. * even do transformations on the arguments. They can also provide replacement
  159. * patterns for the view title. For example, the 'content' validator
  160. * verifies verifies that the argument value corresponds to a node, loads
  161. * that node and provides the node title as a replacement pattern.
  162. * - Access: Access plugins are responsible for controlling access to the view.
  163. * Views includes plugins for checking user roles and individual permissions.
  164. * - Query: Query plugins generate and execute a query, so they can be seen as
  165. * a data backend. The default implementation is using SQL. There are
  166. * contributed modules reading data from other sources, see for example the
  167. * Views XML Backend module.
  168. * - Cache: Cache plugins control the storage and loading of caches. Currently
  169. * they can do both result and render caching, but maybe one day cache the
  170. * generated query.
  171. * - Pager plugins: Pager plugins take care of everything regarding pagers.
  172. * From getting and setting the total amount of items to render the pager and
  173. * setting the global pager arrays.
  174. * - Exposed form plugins: Exposed form plugins are responsible for building,
  175. * rendering and controlling exposed forms. They can expose new parts of the
  176. * view to the user and more.
  177. * - Localization plugins: Localization plugins take care how the view options
  178. * are translated. There are example implementations for t(), 'no
  179. * translation' and i18n.
  180. * - Display extenders: Display extender plugins allow scaling of views options
  181. * horizontally. This means that you can add options and do stuff on all
  182. * views displays. One theoretical example is metatags for views.
  183. *
  184. * Plugins are registered by implementing hook_views_plugins() in your
  185. * modulename.views.inc file and returning an array of data.
  186. * For examples please look at views_views_plugins() in
  187. * views/includes/plugins.inc as it has examples for all of them.
  188. *
  189. * Similar to handlers, make sure that you add your plugin files to the
  190. * module.info file.
  191. *
  192. * The array defining plugins will look something like this:
  193. * @code
  194. * return array(
  195. * 'display' => array(
  196. * // ... list of display plugins,
  197. * ),
  198. * 'style' => array(
  199. * // ... list of style plugins,
  200. * ),
  201. * 'row' => array(
  202. * // ... list of row style plugins,
  203. * ),
  204. * 'argument default' => array(
  205. * // ... list of argument default plugins,
  206. * ),
  207. * 'argument validator' => array(
  208. * // ... list of argument validator plugins,
  209. * ),
  210. * 'access' => array(
  211. * // ... list of access plugins,
  212. * ),
  213. * 'query' => array(
  214. * // ... list of query plugins,
  215. * ),,
  216. * 'cache' => array(
  217. * // ... list of cache plugins,
  218. * ),,
  219. * 'pager' => array(
  220. * // ... list of pager plugins,
  221. * ),,
  222. * 'exposed_form' => array(
  223. * // ... list of exposed_form plugins,
  224. * ),,
  225. * 'localization' => array(
  226. * // ... list of localization plugins,
  227. * ),
  228. * 'display_extender' => array(
  229. * // ... list of display extender plugins,
  230. * ),
  231. * );
  232. * @endcode
  233. *
  234. * Each plugin will be registered with an identifier for the plugin, plus a
  235. * fairly lengthy list of items that can define how and where the plugin is
  236. * used. Here is an example of a row style plugin from Views core:
  237. * @code
  238. * 'node' => array(
  239. * 'title' => t('Node'),
  240. * 'help' => t('Display the node with standard node view.'),
  241. * 'handler' => 'views_plugin_row_node_view',
  242. * // Not necessary for most modules.
  243. * 'path' => drupal_get_path('module', 'views') . '/modules/node',
  244. * 'theme' => 'views_view_row_node',
  245. * // Only works with 'node' as base.
  246. * 'base' => array('node'),
  247. * 'uses options' => TRUE,
  248. * 'type' => 'normal',
  249. * ),
  250. * @endcode
  251. *
  252. * Of particular interest is the *path* directive, which works a little
  253. * differently from handler registration; each plugin must define its own path,
  254. * rather than relying on a global info for the paths. For example:
  255. * @code
  256. * 'feed' => array(
  257. * 'title' => t('Feed'),
  258. * 'help' => t('Display the view as a feed, such as an RSS feed.'),
  259. * 'handler' => 'views_plugin_display_feed',
  260. * 'uses hook menu' => TRUE,
  261. * 'use ajax' => FALSE,
  262. * 'use pager' => FALSE,
  263. * 'accept attachments' => FALSE,
  264. * 'admin' => t('Feed'),
  265. * 'help topic' => 'display-feed',
  266. * ),
  267. * @endcode
  268. *
  269. * Please be sure to prefix your plugin identifiers with your module name to
  270. * ensure namespace safety; after all, two different modules could try to
  271. * implement the 'grid2' plugin, and that would cause one plugin to completely
  272. * fail.
  273. *
  274. * @todo Finish this document.
  275. *
  276. * See also:
  277. * - @link views_display_plugins Views display plugins @endlink
  278. * - @link views_style_plugins Views style plugins @endlink
  279. * - @link views_row_plugins Views row plugins @endlink
  280. */
  281. /**
  282. * @defgroup views_hooks Views hooks
  283. * @{
  284. * Hooks that can be implemented by other modules in order to implement the
  285. * Views API.
  286. */
  287. /**
  288. * Describes data tables (or the equivalent) to Views.
  289. *
  290. * This hook should be placed in MODULENAME.views.inc and it will be auto
  291. * loaded. MODULENAME.views.inc must be in the directory specified by the 'path'
  292. * key returned by MODULENAME_views_api(), or the same directory as the .module
  293. * file, if 'path' is unspecified.
  294. *
  295. * @return array
  296. * An associative array describing the data structure. Primary key is the
  297. * name used internally by Views for the table(s) – usually the actual table
  298. * name. The values for the key entries are described in detail below.
  299. */
  300. function hook_views_data() {
  301. // This example describes how to write hook_views_data() for the following
  302. // table:
  303. //
  304. // CREATE TABLE example_table (
  305. // nid INT(11) NOT NULL COMMENT 'Primary key; refers to {node}.nid.',
  306. // plain_text_field VARCHAR(32) COMMENT 'Just a plain text field.',
  307. // numeric_field INT(11) COMMENT 'Just a numeric field.',
  308. // boolean_field INT(1) COMMENT 'Just an on/off field.',
  309. // timestamp_field INT(8) COMMENT 'Just a timestamp field.',
  310. // PRIMARY KEY(nid)
  311. // );
  312. // First, the entry $data['example_table']['table'] describes properties of
  313. // the actual table – not its content.
  314. // The 'group' index will be used as a prefix in the UI for any of this
  315. // table's fields, sort criteria, etc. so it's easy to tell where they came
  316. // from.
  317. $data['example_table']['table']['group'] = t('Example table');
  318. // Define this as a base table – a table that can be described in itself by
  319. // views (and not just being brought in as a relationship). In reality this
  320. // is not very useful for this table, as it isn't really a distinct object of
  321. // its own, but it makes a good example.
  322. $data['example_table']['table']['base'] = array(
  323. // This is the identifier field for the view.
  324. 'field' => 'nid',
  325. 'title' => t('Example table'),
  326. 'help' => t('Example table contains example content and can be related to nodes.'),
  327. 'weight' => -10,
  328. );
  329. // This table references the {node} table. The declaration below creates an
  330. // 'implicit' relationship to the node table, so that when 'node' is the base
  331. // table, the fields are automatically available.
  332. $data['example_table']['table']['join'] = array(
  333. // Index this array by the table name to which this table refers.
  334. 'node' => array(
  335. // The primary key in the referenced table.
  336. 'left_field' => 'nid',
  337. // The foreign key in this table.
  338. 'field' => 'nid',
  339. ),
  340. );
  341. // Next, describe each of the individual fields in this table to Views. This
  342. // is done by describing $data['example_table']['FIELD_NAME']. This part of
  343. // the array may then have further entries:
  344. // - title: The label for the table field, as presented in Views.
  345. // - help: The description text for the table field.
  346. // - relationship: A description of any relationship handler for the table
  347. // field.
  348. // - field: A description of any field handler for the table field.
  349. // - sort: A description of any sort handler for the table field.
  350. // - filter: A description of any filter handler for the table field.
  351. // - argument: A description of any argument handler for the table field.
  352. // - area: A description of any handler for adding content to header,
  353. // footer or as no result behaviour.
  354. //
  355. // The handler descriptions are described with examples below.
  356. // Node ID table field.
  357. $data['example_table']['nid'] = array(
  358. 'title' => t('Example content'),
  359. 'help' => t('Some example content that references a node.'),
  360. // Define a relationship to the {node} table, so example_table views can
  361. // add a relationship to nodes. If you want to define a relationship the
  362. // other direction, use hook_views_data_alter(), or use the 'implicit' join
  363. // method described above.
  364. 'relationship' => array(
  365. // The name of the table to join with.
  366. 'base' => 'node',
  367. // The name of the field on the joined table.
  368. 'base field' => 'nid',
  369. // 'field' => 'nid' -- see hook_views_data_alter(); not needed here.
  370. 'handler' => 'views_handler_relationship',
  371. 'label' => t('Default label for the relationship'),
  372. 'title' => t('Title shown when adding the relationship'),
  373. 'help' => t('More information on this relationship'),
  374. ),
  375. );
  376. // Example plain text field.
  377. $data['example_table']['plain_text_field'] = array(
  378. 'title' => t('Plain text field'),
  379. 'help' => t('Just a plain text field.'),
  380. 'field' => array(
  381. 'handler' => 'views_handler_field',
  382. // This is use by the table display plugin.
  383. 'click sortable' => TRUE,
  384. ),
  385. 'sort' => array(
  386. 'handler' => 'views_handler_sort',
  387. ),
  388. 'filter' => array(
  389. 'handler' => 'views_handler_filter_string',
  390. ),
  391. 'argument' => array(
  392. 'handler' => 'views_handler_argument_string',
  393. ),
  394. );
  395. // Example numeric text field.
  396. $data['example_table']['numeric_field'] = array(
  397. 'title' => t('Numeric field'),
  398. 'help' => t('Just a numeric field.'),
  399. 'field' => array(
  400. 'handler' => 'views_handler_field_numeric',
  401. 'click sortable' => TRUE,
  402. ),
  403. 'filter' => array(
  404. 'handler' => 'views_handler_filter_numeric',
  405. ),
  406. 'sort' => array(
  407. 'handler' => 'views_handler_sort',
  408. ),
  409. );
  410. // Example boolean field.
  411. $data['example_table']['boolean_field'] = array(
  412. 'title' => t('Boolean field'),
  413. 'help' => t('Just an on/off field.'),
  414. 'field' => array(
  415. 'handler' => 'views_handler_field_boolean',
  416. 'click sortable' => TRUE,
  417. ),
  418. 'filter' => array(
  419. 'handler' => 'views_handler_filter_boolean_operator',
  420. // Note that you can override the field-wide label.
  421. 'label' => t('Published'),
  422. // This setting is used by the boolean filter handler, as possible option.
  423. 'type' => 'yes-no',
  424. // use boolean_field = 1 instead of boolean_field <> 0 in WHERE statement.
  425. 'use equal' => TRUE,
  426. ),
  427. 'sort' => array(
  428. 'handler' => 'views_handler_sort',
  429. ),
  430. );
  431. // Example timestamp field.
  432. $data['example_table']['timestamp_field'] = array(
  433. 'title' => t('Timestamp field'),
  434. 'help' => t('Just a timestamp field.'),
  435. 'field' => array(
  436. 'handler' => 'views_handler_field_date',
  437. 'click sortable' => TRUE,
  438. ),
  439. 'sort' => array(
  440. 'handler' => 'views_handler_sort_date',
  441. ),
  442. 'filter' => array(
  443. 'handler' => 'views_handler_filter_date',
  444. ),
  445. );
  446. return $data;
  447. }
  448. /**
  449. * Alter table structure.
  450. *
  451. * You can add/edit/remove existing tables defined by hook_views_data().
  452. *
  453. * This hook should be placed in MODULENAME.views_default.inc and it will be
  454. * auto-loaded. MODULENAME.views_default.inc must be in the directory specified
  455. * by the 'path' key returned by MODULENAME_views_api(), or the same directory
  456. * as the .module file, if 'path' is unspecified.
  457. *
  458. * After adding this hook to an existing module, you will need to clear the
  459. * Drupal menu cache and the Views cache to have your default views be
  460. * recognized.
  461. *
  462. * @param array $data
  463. * An array of all Views data, passed by reference. See hook_views_data() for
  464. * structure.
  465. *
  466. * @see hook_views_data()
  467. */
  468. function hook_views_data_alter(&$data) {
  469. // This example alters the title of the node:nid field in the Views UI.
  470. $data['node']['nid']['title'] = t('Node-Nid');
  471. // This example adds an example field to the users table.
  472. $data['users']['example_field'] = array(
  473. 'title' => t('Example field'),
  474. 'help' => t('Some example content that references a user'),
  475. 'field' => array(
  476. 'handler' => 'modulename_handler_field_example_field',
  477. ),
  478. );
  479. // This example changes the handler of the node title field.
  480. // In this handler you could do stuff, like preview of the node when clicking
  481. // the node title.
  482. $data['node']['title']['field']['handler'] = 'modulename_handler_field_node_title';
  483. // This example adds a relationship to table {foo}, so that 'foo' views can
  484. // add this table using a relationship. Because we don't want to write over
  485. // the primary key field definition for the {foo}.fid field, we use a
  486. // placeholder field name as the key.
  487. $data['foo']['sample_name'] = array(
  488. 'title' => t('Example relationship'),
  489. 'help' => t('Example help'),
  490. 'relationship' => array(
  491. // Table we're joining to.
  492. 'base' => 'example_table',
  493. // Field on the joined table.
  494. 'base field' => 'eid',
  495. // Real field name on the 'foo' table.
  496. 'field' => 'fid',
  497. 'handler' => 'views_handler_relationship',
  498. 'label' => t('Default label for relationship'),
  499. 'title' => t('Title seen when adding relationship'),
  500. 'help' => t('More information about relationship.'),
  501. ),
  502. );
  503. // Note that the $data array is not returned – it is modified by reference.
  504. }
  505. /**
  506. * Override the default data for a Field API field.
  507. *
  508. * Field module's Implements hook_views_data() invokes this for each
  509. * field in the module that defines the field type (as declared in the field
  510. * array). It is not invoked in other modules.
  511. *
  512. * If no hook implementation exists, hook_views_data() falls back to
  513. * field_views_field_default_views_data().
  514. *
  515. * @param array $field
  516. * A field definition array, as returned by field_info_fields().
  517. *
  518. * @return array
  519. * An array of views data, in the same format as the return value of
  520. * hook_views_data().
  521. *
  522. * @see field_views_data()
  523. * @see hook_field_views_data_alter()
  524. * @see hook_field_views_data_views_data_alter()
  525. */
  526. function hook_field_views_data($field) {
  527. return array();
  528. }
  529. /**
  530. * Alter the views data for a single Field API field.
  531. *
  532. * This is called even if there is no hook_field_views_data() implementation for
  533. * the field, and therefore may be used to alter the default data that
  534. * field_views_field_default_views_data() supplies for the field.
  535. *
  536. * @param array $result
  537. * An array of views table data provided for a single field. This has the same
  538. * format as the return value of hook_views_data().
  539. * @param array $field
  540. * A field definition array, as returned by field_info_fields().
  541. * @param string $module
  542. * The module that defines the field type.
  543. *
  544. * @see field_views_data()
  545. * @see hook_field_views_data()
  546. * @see hook_field_views_data_views_data_alter()
  547. */
  548. function hook_field_views_data_alter(&$result, $field, $module) {
  549. }
  550. /**
  551. * Alter the views data on a per field basis.
  552. *
  553. * Field module's Implements hook_views_data_alter() invokes this for
  554. * each field in the module that defines the field type (as declared in the
  555. * field array). It is not invoked in other modules.
  556. *
  557. * Unlike hook_field_views_data_alter(), this operates on the whole of the views
  558. * data. This allows a field module to add data that concerns its fields to
  559. * other tables, which would not yet be defined at the point when
  560. * hook_field_views_data() and hook_field_views_data_alter() are invoked. For
  561. * example, entityreference adds reverse relationships on the tables for the
  562. * entities which are referenced by entityreference fields.
  563. *
  564. * (Note: this is weirdly named so as not to conflict with
  565. * hook_field_views_data_alter().)
  566. *
  567. * @see hook_field_views_data()
  568. * @see hook_field_views_data_alter()
  569. * @see field_views_data_alter()
  570. */
  571. function hook_field_views_data_views_data_alter(&$data, $field) {
  572. $field_name = $field['field_name'];
  573. $data_key = 'field_data_' . $field_name;
  574. // Views data for this field is in $data[$data_key]
  575. }
  576. /**
  577. * Describes plugins defined by the module.
  578. *
  579. * This hook should be placed in MODULENAME.views.inc and it will be
  580. * auto-loaded. MODULENAME.views.inc must be in the directory specified by the
  581. * 'path' key returned by MODULENAME_views_api(), or the same directory as the
  582. * .module file, if 'path' is unspecified. All plugin files need to be
  583. * referenced in MODULENAME.info with the files[] directive.
  584. *
  585. * @return array
  586. * An array on the form $plugins['PLUGIN TYPE']['PLUGIN NAME']. The plugin
  587. * must be one of row, display, display_extender, style, argument default,
  588. * argument validator, access, query, cache, pager, exposed_form or
  589. * localization. The plugin name should be prefixed with your module name.
  590. * The value for each entry is an associative array that may contain the
  591. * following entries:
  592. * - Used by all plugin types:
  593. * - title (required): The name of the plugin, as shown in Views. Wrap in
  594. * t().
  595. * - handler (required): The name of the file containing the class
  596. * describing the handler, which must also be the name of the handler's
  597. * class.
  598. * - path: Path to the handler. Only required if the handler is not placed
  599. * in the same folder as the .module file or in the subfolder 'views'.
  600. * - parent: The name of the plugin this plugin extends. Since Drupal 7 this
  601. * is no longer required, but may still be useful from a code readability
  602. * perspective.
  603. * - no ui: Set to TRUE to denote that the plugin doesn't appear to be
  604. * selectable in the ui, though on the api side they still exists.
  605. * - uses options: Set to TRUE to denote that the plugin has an additional
  606. * options form.
  607. * - help: A short help text, wrapped in t() used as description on the
  608. * plugin settings form.
  609. * - help topic: The name of an entry by advanced help for the plugin.
  610. * - theme: The name of a theme suggestion to use for the display.
  611. * - js: An array with paths to js files that should be included for the
  612. * display. Note that the path should be relative Drupal root, not module
  613. * root.
  614. * - type: Each plugin can specify a type parameter to group certain
  615. * plugins together. For example all row plugins related to feeds are
  616. * grouped together, because a rss style plugin only accepts feed row
  617. * plugins.
  618. *
  619. * - Used by display plugins:
  620. * - admin: The administrative name of the display, as displayed on the
  621. * Views overview and also used as default name for new displays. Wrap in
  622. * t().
  623. * - no remove: Set to TRUE to make the display non-removable. (Basically
  624. * only used for the master/default display.)
  625. * - use ajax: Set to TRUE to allow AJAX loads in the display. If it's
  626. * disabled there will be no ajax option in the ui.
  627. * - use pager: Set to TRUE to allow paging in the display.
  628. * - use more: Set to TRUE to allow the 'use more' setting in the display.
  629. * - accept attachments: Set to TRUE to allow attachment displays to be
  630. * attached to this display type.
  631. * - contextual links locations: An array with places where contextual links
  632. * should be added. Can for example be 'page' or 'block'. If you don't
  633. * specify it there will be contextual links around the rendered view. If
  634. * this is not set or regions have been specified, views will display an
  635. * option to 'hide contextual links'. Use an empty array if you do not
  636. * want this.
  637. * - uses hook menu: Set to TRUE to have the display included by
  638. * views_menu_alter(). views_menu_alter executes then execute_hook_menu
  639. * on the display object.
  640. * - uses hook block: Set to TRUE to have the display included by
  641. * views_block_info().
  642. * - theme: The name of a theme suggestion to use for the display.
  643. * - js: An array with paths to js files that should be included for the
  644. * display. Note that the path should be relative Drupal root, not module
  645. * root.
  646. *
  647. * - Used by style plugins:
  648. * - uses row plugin: Set to TRUE to allow row plugins for this style.
  649. * - uses row class: Set to TRUE to allow the CSS class settings for rows.
  650. * - uses fields: Set to TRUE to have the style plugin accept field
  651. * handlers.
  652. * - uses grouping: Set to TRUE to allow the grouping settings for rows.
  653. * - even empty: May have the value 'even empty' to tell Views that the
  654. * style should be rendered even if there are no results.
  655. *
  656. * - Used by row plugins:
  657. * - uses fields: Set to TRUE to have the row plugin accept field handlers.
  658. */
  659. function hook_views_plugins() {
  660. $plugins = array();
  661. $plugins['argument validator'] = array(
  662. 'taxonomy_term' => array(
  663. 'title' => t('Taxonomy term'),
  664. 'handler' => 'views_plugin_argument_validate_taxonomy_term',
  665. // Declaring path explicitly not necessary for most modules.
  666. 'path' => drupal_get_path('module', 'views') . '/modules/taxonomy',
  667. ),
  668. );
  669. return array(
  670. // This just tells our themes are elsewhere.
  671. 'module' => 'views',
  672. 'argument validator' => array(
  673. 'taxonomy_term' => array(
  674. 'title' => t('Taxonomy term'),
  675. 'handler' => 'views_plugin_argument_validate_taxonomy_term',
  676. // Declaring path explicitly not necessary for most modules.
  677. 'path' => drupal_get_path('module', 'views') . '/modules/taxonomy',
  678. ),
  679. ),
  680. 'argument default' => array(
  681. 'taxonomy_tid' => array(
  682. 'title' => t('Taxonomy term ID from URL'),
  683. 'handler' => 'views_plugin_argument_default_taxonomy_tid',
  684. 'path' => drupal_get_path('module', 'views') . '/modules/taxonomy',
  685. 'parent' => 'fixed',
  686. ),
  687. ),
  688. );
  689. }
  690. /**
  691. * Alter existing plugins data, defined by modules.
  692. *
  693. * @see hook_views_plugins()
  694. */
  695. function hook_views_plugins_alter(&$plugins) {
  696. // Add apachesolr to the base of the node row plugin.
  697. $plugins['row']['node']['base'][] = 'apachesolr';
  698. }
  699. /**
  700. * Alter existing plugin option definitions.
  701. *
  702. * This can be used to edit default or add new option definitions to existing
  703. * plugins. The reason for doing this is that only overriding the relevent form
  704. * with hook_form_alter() is insufficent because submitted form values will be
  705. * ignored if they haven't been declared as an available option.
  706. *
  707. * An alternative approach you could also take is to extend each plugin
  708. * individually. However if your goal is to override many, or even all plugins,
  709. * this results in a lot of additional code and files. This makes it a lot more
  710. * troublesome to maintain the codebase, as well as interoperability with other
  711. * modules.
  712. *
  713. * @param array $options
  714. * The option definitions to be altered.
  715. * @param $plugin
  716. * A views object of the plugin where the default options are defined.
  717. *
  718. * @see views_object::option_definition()
  719. * @see hook_views_handler_option_definition_alter()
  720. * @see hook_form_alter()
  721. */
  722. function hook_views_plugin_option_definition_alter(&$options, $plugin) {
  723. // Add a new option definition.
  724. $options['option_name'] = array('default' => '');
  725. }
  726. /**
  727. * Alter existing handler option definitions.
  728. *
  729. * This can be used to edit default or add new option definitions to existing
  730. * handlers. The reason for doing this is that only overriding the relevent form
  731. * with hook_form_alter() is insufficent because submitted form values will be
  732. * ignored if they haven't been declared as an available option.
  733. *
  734. * An alternative approach you could also take is to extend each handler
  735. * individually. However if your goal is to override many, or even all handlers,
  736. * this results in a lot of additional code and files. This makes it a lot more
  737. * troublesome to maintain the codebase, as well as interoperability with other
  738. * modules.
  739. *
  740. * @param array $options
  741. * The option definitions to be altered.
  742. * @param $handler
  743. * A views object of the handler where the default options are defined.
  744. *
  745. * @see views_handler::option_definition()
  746. * @see hook_views_plugin_option_definition_alter()
  747. * @see hook_form_alter()
  748. */
  749. function hook_views_handler_option_definition_alter(&$options, $handler) {
  750. // Add a new option definition.
  751. $options['option_name'] = array('default' => '');
  752. }
  753. /**
  754. * Register View API information.
  755. *
  756. * This is required for your module to have its include files loaded; for
  757. * example, when implementing hook_views_default_views().
  758. *
  759. * @return array
  760. * An array with the following possible keys:
  761. * - api: (required) The version of the Views API the module implements.
  762. * - path: (optional) If includes are stored somewhere other than within the
  763. * root module directory, specify its path here.
  764. * - template path: (optional) A path where the module has stored its views
  765. * template files. When you have specified this key views automatically
  766. * uses the template files for the views. You can use the same naming
  767. * conventions like for normal views template files.
  768. */
  769. function hook_views_api() {
  770. return array(
  771. 'api' => 3,
  772. 'path' => drupal_get_path('module', 'example') . '/includes/views',
  773. 'template path' => drupal_get_path('module', 'example') . '/themes',
  774. );
  775. }
  776. /**
  777. * Allows modules to provide their own views.
  778. *
  779. * These can either be used as-is or as a "starter" for users to build from.
  780. *
  781. * This hook should be placed in MODULENAME.views_default.inc and it will be
  782. * auto-loaded. MODULENAME.views_default.inc must be in the directory specified
  783. * by the 'path' key returned by MODULENAME_views_api(), or the same directory
  784. * as the .module file, if 'path' is unspecified.
  785. *
  786. * The $view->disabled boolean flag indicates whether the View should be
  787. * enabled (FALSE) or disabled (TRUE) by default.
  788. *
  789. * @return array
  790. * An associative array containing the structures of views, as generated from
  791. * the Export tab, keyed by the view name. A best practice is to go through
  792. * and add t() to all title and label strings, with the exception of menu
  793. * strings.
  794. */
  795. function hook_views_default_views() {
  796. // Begin copy and paste of output from the Export tab of a view.
  797. $view = new view();
  798. $view->name = 'frontpage';
  799. $view->description = 'Emulates the default Drupal front page; you may set the default home page path to this view to make it your front page.';
  800. $view->tag = 'default';
  801. $view->base_table = 'node';
  802. $view->human_name = 'Front page';
  803. $view->core = 0;
  804. $view->api_version = '3.0';
  805. $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */
  806. /* Display: Master */
  807. $handler = $view->new_display('default', 'Master', 'default');
  808. $handler->display->display_options['access']['type'] = 'none';
  809. $handler->display->display_options['cache']['type'] = 'none';
  810. $handler->display->display_options['query']['type'] = 'views_query';
  811. $handler->display->display_options['query']['options']['query_comment'] = FALSE;
  812. $handler->display->display_options['exposed_form']['type'] = 'basic';
  813. $handler->display->display_options['pager']['type'] = 'full';
  814. $handler->display->display_options['style_plugin'] = 'default';
  815. $handler->display->display_options['row_plugin'] = 'node';
  816. /* Sort criterion: Content: Sticky */
  817. $handler->display->display_options['sorts']['sticky']['id'] = 'sticky';
  818. $handler->display->display_options['sorts']['sticky']['table'] = 'node';
  819. $handler->display->display_options['sorts']['sticky']['field'] = 'sticky';
  820. $handler->display->display_options['sorts']['sticky']['order'] = 'DESC';
  821. /* Sort criterion: Content: Post date */
  822. $handler->display->display_options['sorts']['created']['id'] = 'created';
  823. $handler->display->display_options['sorts']['created']['table'] = 'node';
  824. $handler->display->display_options['sorts']['created']['field'] = 'created';
  825. $handler->display->display_options['sorts']['created']['order'] = 'DESC';
  826. /* Filter criterion: Content: Promoted to front page */
  827. $handler->display->display_options['filters']['promote']['id'] = 'promote';
  828. $handler->display->display_options['filters']['promote']['table'] = 'node';
  829. $handler->display->display_options['filters']['promote']['field'] = 'promote';
  830. $handler->display->display_options['filters']['promote']['value'] = '1';
  831. $handler->display->display_options['filters']['promote']['group'] = 0;
  832. $handler->display->display_options['filters']['promote']['expose']['operator'] = FALSE;
  833. /* Filter criterion: Content: Published */
  834. $handler->display->display_options['filters']['status']['id'] = 'status';
  835. $handler->display->display_options['filters']['status']['table'] = 'node';
  836. $handler->display->display_options['filters']['status']['field'] = 'status';
  837. $handler->display->display_options['filters']['status']['value'] = '1';
  838. $handler->display->display_options['filters']['status']['group'] = 0;
  839. $handler->display->display_options['filters']['status']['expose']['operator'] = FALSE;
  840. /* Display: Page */
  841. $handler = $view->new_display('page', 'Page', 'page');
  842. $handler->display->display_options['path'] = 'frontpage';
  843. /* Display: Feed */
  844. $handler = $view->new_display('feed', 'Feed', 'feed');
  845. $handler->display->display_options['defaults']['title'] = FALSE;
  846. $handler->display->display_options['title'] = 'Front page feed';
  847. $handler->display->display_options['pager']['type'] = 'some';
  848. $handler->display->display_options['style_plugin'] = 'rss';
  849. $handler->display->display_options['row_plugin'] = 'node_rss';
  850. $handler->display->display_options['path'] = 'rss.xml';
  851. $handler->display->display_options['displays'] = array(
  852. 'default' => 'default',
  853. 'page' => 'page',
  854. );
  855. $handler->display->display_options['sitename_title'] = '1';
  856. // (Export ends here.)
  857. // Add view to list of views to provide.
  858. $views[$view->name] = $view;
  859. // Repeat all of the above for each view the module should provide. At the
  860. // end, return array of default views.
  861. return $views;
  862. }
  863. /**
  864. * Alter default views defined by other modules.
  865. *
  866. * This hook is called right before all default views are cached to the
  867. * database. It takes a keyed array of views by reference.
  868. *
  869. * Example usage to add a field to a view:
  870. * @code
  871. * $handler =& $view->display['DISPLAY_ID']->handler;
  872. * // Add the user name field to the view.
  873. * $handler->display->display_options['fields']['name']['id'] = 'name';
  874. * $handler->display->display_options['fields']['name']['table'] = 'users';
  875. * $handler->display->display_options['fields']['name']['field'] = 'name';
  876. * $handler->display->display_options['fields']['name']['label'] = 'Author';
  877. * $handler->display->display_options['fields']['name']['link_to_user'] = 1;
  878. * @endcode
  879. */
  880. function hook_views_default_views_alter(&$views) {
  881. if (isset($views['taxonomy_term'])) {
  882. $views['taxonomy_term']->display['default']->display_options['title'] = 'Categories';
  883. }
  884. }
  885. /**
  886. * Performs replacements in the query before being performed.
  887. *
  888. * @param object $view
  889. * The View being executed.
  890. *
  891. * @return array
  892. * An array with keys being the strings to replace, and the values the strings
  893. * to replace them with. The strings to replace are often surrounded with
  894. * '***', as illustrated in the example implementation.
  895. */
  896. function hook_views_query_substitutions($view) {
  897. // Example from views_views_query_substitutions().
  898. global $language_content;
  899. return array(
  900. '***CURRENT_VERSION***' => VERSION,
  901. '***CURRENT_TIME***' => REQUEST_TIME,
  902. '***CURRENT_LANGUAGE***' => $language_content->language,
  903. '***DEFAULT_LANGUAGE***' => language_default('language'),
  904. );
  905. }
  906. /**
  907. * This hook is called to get a list of placeholders and their substitutions.
  908. *
  909. * Used when preprocessing a View with form elements.
  910. *
  911. * @return array
  912. * An array with keys being the strings to replace, and the values the strings
  913. * to replace them with.
  914. */
  915. function hook_views_form_substitutions() {
  916. return array(
  917. '<!--views-form-example-substitutions-->' => 'Example Substitution',
  918. );
  919. }
  920. /**
  921. * Allows altering a view at the very beginning of processing a preview.
  922. *
  923. * Occurs before anything is done.
  924. *
  925. * This hook is only triggered when the one of the following are invoked:
  926. * - $view->execute_display()
  927. * - $view->preview()
  928. *
  929. * As such code placed in this hook will not fire during:
  930. * - $view->build()
  931. * - $view->execute()
  932. * - $view->render()
  933. *
  934. * Likely, hook_views_pre_build() or hook_views_pre_execute() are much better
  935. * choices for most use cases since they are always invoked, not just when
  936. * previewing a display.
  937. *
  938. * Adding output to the view can be accomplished by placing text on
  939. * $view->attachment_before and $view->attachment_after.
  940. *
  941. * @param object $view
  942. * The view object about to be processed.
  943. * @param string $display_id
  944. * The machine name of the active display.
  945. * @param array $args
  946. * An array of arguments passed into the view.
  947. */
  948. function hook_views_pre_view(&$view, &$display_id, &$args) {
  949. // Change the display if the acting user has 'administer site configuration'
  950. // permission, to display something radically different.
  951. // (Note that this is not necessarily the best way to solve that task. Feel
  952. // free to contribute another example!)
  953. if (
  954. $view->name == 'my_special_view'
  955. && user_access('administer site configuration')
  956. && $display_id == 'public_display'
  957. ) {
  958. $view->set_display('private_display');
  959. }
  960. }
  961. /**
  962. * Called after the display's pre_execute phase but before the build process.
  963. *
  964. * Adding output to the view can be accomplished by placing text on
  965. * $view->attachment_before and $view->attachment_after.
  966. *
  967. * @param object $view
  968. * The view object about to be processed.
  969. */
  970. function hook_views_pre_build(&$view) {
  971. // Because of some inexplicable business logic, we should remove all
  972. // attachments from all views on Mondays.
  973. // (This alter could be done later in the execution process as well.)
  974. if (date('D') == 'Mon') {
  975. unset($view->attachment_before);
  976. unset($view->attachment_after);
  977. }
  978. }
  979. /**
  980. * This hook is called right after the build process.
  981. *
  982. * The query is now fully built, but it has not yet been run through
  983. * db_rewrite_sql.
  984. *
  985. * Adding output to the view can be accomplished by placing text on
  986. * $view->attachment_before and $view->attachment_after.
  987. *
  988. * @param object $view
  989. * The view object about to be processed.
  990. */
  991. function hook_views_post_build(&$view) {
  992. // If the exposed field 'type' is set, hide the column containing the content
  993. // type. (Note that this is a solution for a particular view, and makes
  994. // assumptions about both exposed filter settings and the fields in the view.
  995. // Also note that this alter could be done at any point before the view being
  996. // rendered.)
  997. if ($view->name == 'my_view' && isset($view->exposed_raw_input['type']) && $view->exposed_raw_input['type'] != 'All') {
  998. // 'Type' should be interpreted as content type.
  999. if (isset($view->field['type'])) {
  1000. $view->field['type']->options['exclude'] = TRUE;
  1001. }
  1002. }
  1003. }
  1004. /**
  1005. * This hook is called right before the execute process.
  1006. *
  1007. * The query is now fully built, but it has not yet been run through
  1008. * db_rewrite_sql.
  1009. *
  1010. * Adding output to the view can be accomplished by placing text on
  1011. * $view->attachment_before and $view->attachment_after.
  1012. *
  1013. * @param object $view
  1014. * The view object about to be processed.
  1015. */
  1016. function hook_views_pre_execute(&$view) {
  1017. // Whenever a view queries more than two tables, show a message that notifies
  1018. // view administrators that the query might be heavy.
  1019. // (This action could be performed later in the execution process, but not
  1020. // earlier.)
  1021. if (count($view->query->tables) > 2 && user_access('administer views')) {
  1022. drupal_set_message(t('The view %view may be heavy to execute.', array('%view' => $view->name)), 'warning');
  1023. }
  1024. }
  1025. /**
  1026. * This hook is called right after the execute process.
  1027. *
  1028. * The query has been executed, but the pre_render() phase has not yet happened
  1029. * for handlers.
  1030. *
  1031. * Adding output to the view can be accomplished by placing text on
  1032. * $view->attachment_before and $view->attachment_after. Altering the content
  1033. * can be achieved by editing the items of $view->result.
  1034. *
  1035. * @param object $view
  1036. * The view object about to be processed.
  1037. */
  1038. function hook_views_post_execute(&$view) {
  1039. // If there are more than 100 results, show a message that encourages the user
  1040. // to change the filter settings.
  1041. // (This action could be performed later in the execution process, but not
  1042. // earlier.)
  1043. if ($view->total_rows > 100) {
  1044. drupal_set_message(t('You have more than 100 hits. Use the filter settings to narrow down your list.'));
  1045. }
  1046. }
  1047. /**
  1048. * This hook is called right before the render process.
  1049. *
  1050. * The query has been executed, and the pre_render() phase has already happened
  1051. * for handlers, so all data should be available.
  1052. *
  1053. * Adding output to the view can be accomplished by placing text on
  1054. * $view->attachment_before and $view->attachment_after. Altering the content
  1055. * can be achieved by editing the items of $view->result.
  1056. *
  1057. * This hook can be utilized by themes.
  1058. *
  1059. * @param object $view
  1060. * The view object about to be processed.
  1061. */
  1062. function hook_views_pre_render(&$view) {
  1063. // Scramble the order of the rows shown on this result page.
  1064. // Note that this could be done earlier, but not later in the view execution
  1065. // process.
  1066. shuffle($view->result);
  1067. }
  1068. /**
  1069. * Post process any rendered data.
  1070. *
  1071. * This can be valuable to be able to cache a view and still have some level of
  1072. * dynamic output. In an ideal world, the actual output will include HTML
  1073. * comment based tokens, and then the post process can replace those tokens.
  1074. *
  1075. * Example usage. If it is known that the view is a node view and that the
  1076. * primary field will be a nid, you can do something like this:
  1077. *
  1078. * <!--post-FIELD-NID-->
  1079. *
  1080. * And then in the post render, create an array with the text that should
  1081. * go there:
  1082. *
  1083. * strtr($output, array('<!--post-FIELD-1-->' => 'output for FIELD of nid 1');
  1084. *
  1085. * All of the cached result data will be available in $view->result, as well,
  1086. * so all ids used in the query should be discoverable.
  1087. *
  1088. * This hook can be utilized by themes.
  1089. *
  1090. * @param object $view
  1091. * The view object about to be processed.
  1092. * @param string $output
  1093. * A flat string with the rendered output of the view.
  1094. * @param array $cache
  1095. * The cache settings.
  1096. */
  1097. function hook_views_post_render(&$view, &$output, &$cache) {
  1098. // When using full pager, disable any time-based caching if there are less
  1099. // then 10 results.
  1100. if ($view->query->pager instanceof views_plugin_pager_full && $cache->options['type'] == 'time' && count($view->result) < 10) {
  1101. $cache['options']['results_lifespan'] = 0;
  1102. $cache['options']['output_lifespan'] = 0;
  1103. }
  1104. }
  1105. /**
  1106. * Alter the query before executing the query.
  1107. *
  1108. * This hook should be placed in MODULENAME.views.inc and it will be
  1109. * auto-loaded. MODULENAME.views.inc must be in the directory specified by the
  1110. * 'path' key returned by MODULENAME_views_api(), or the same directory as the
  1111. * .module file, if 'path' is unspecified.
  1112. *
  1113. * @param object $view
  1114. * The view object about to be processed.
  1115. * @param object $query
  1116. * An object describing the query.
  1117. *
  1118. * @see hook_views_query_substitutions()
  1119. */
  1120. function hook_views_query_alter(&$view, &$query) {
  1121. // (Example assuming a view with an exposed filter on node title.)
  1122. // If the input for the title filter is a positive integer, filter against
  1123. // node ID instead of node title.
  1124. if ($view->name == 'my_view' && is_numeric($view->exposed_raw_input['title']) && $view->exposed_raw_input['title'] > 0) {
  1125. // Traverse through the 'where' part of the query.
  1126. foreach ($query->where as &$condition_group) {
  1127. foreach ($condition_group['conditions'] as &$condition) {
  1128. // If this is the part of the query filtering on title, change the
  1129. // condition to filter on node ID.
  1130. if ($condition['field'] == 'node.title') {
  1131. $condition = array(
  1132. 'field' => 'node.nid',
  1133. 'value' => $view->exposed_raw_input['title'],
  1134. 'operator' => '=',
  1135. );
  1136. }
  1137. }
  1138. }
  1139. }
  1140. }
  1141. /**
  1142. * Alter the information box that (optionally) appears with a view preview.
  1143. *
  1144. * Includes query and performance statistics.
  1145. *
  1146. * This hook should be placed in MODULENAME.views.inc and it will be
  1147. * auto-loaded. MODULENAME.views.inc must be in the directory specified by the
  1148. * 'path' key returned by MODULENAME_views_api(), or the same directory as the
  1149. * .module file, if 'path' is unspecified.
  1150. *
  1151. * Warning: $view is not a reference in PHP4 and cannot be modified here. But it
  1152. * IS a reference in PHP5, and can be modified. Please be careful with it.
  1153. *
  1154. * @param array $rows
  1155. * An associative array with two keys:
  1156. * - query: An array of rows suitable for theme('table'), containing
  1157. * information about the query and the display title and path.
  1158. * - statistics: An array of rows suitable for theme('table'), containing
  1159. * performance statistics.
  1160. * @param object $view
  1161. * The view object.
  1162. *
  1163. * @see theme_table()
  1164. */
  1165. function hook_views_preview_info_alter(&$rows, $view) {
  1166. // Adds information about the tables being queried by the view to the query
  1167. // part of the info box.
  1168. $rows['query'][] = array(
  1169. t('<strong>Table queue</strong>'),
  1170. count($view->query->table_queue) . ': (' . implode(', ', array_keys($view->query->table_queue)) . ')',
  1171. );
  1172. }
  1173. /**
  1174. * This hooks allows to alter the links at the top of the view edit form.
  1175. *
  1176. * Some modules might want to add links there.
  1177. *
  1178. * @param array $links
  1179. * An array of links which will be displayed at the top of the view edit form.
  1180. * Each entry should be on a form suitable for theme('link').
  1181. * @param object $view
  1182. * The full view object which is currently edited.
  1183. * @param string $display_id
  1184. * The current display id which is edited. For example that's 'default' or
  1185. * 'page_1'.
  1186. */
  1187. function hook_views_ui_display_top_links_alter(&$links, $view, $display_id) {
  1188. // Put the export link first in the list.
  1189. if (isset($links['export'])) {
  1190. $links = array('export' => $links['export']) + $links;
  1191. }
  1192. }
  1193. /**
  1194. * This hooks allows you to alter the ajax form definitions for the sub-forms
  1195. * that handle the editing of the different pieces of a view, for example
  1196. * adding or editing fields or filters.
  1197. *
  1198. * Other modules may want to change existing form callbacks or add their own
  1199. * new forms.
  1200. *
  1201. * @param array $forms
  1202. * An array of forms where the keys are keys, that are passed in via the url
  1203. * and are used to identify the forms, and the values are arrays of
  1204. * information defining the form, including the form id and the arguments.
  1205. *
  1206. * @see views_ui_ajax_forms()
  1207. */
  1208. function hook_views_ui_ajax_forms_alter(&$forms) {
  1209. // Add a new custom form for categorizing fields, filters, etc. attached to
  1210. // the view. You would then implement the form function
  1211. // mymodule_views_categorize_fields_form($form, &$form_state) and $form_state
  1212. // would contain $form_state['type'] and $form_state['id'].
  1213. // The urls that would call this form would be (both nojs and ajax versions):
  1214. // admin/structure/views/nojs/categorise-item/<view_name>/<display_name>/<type>/<id>
  1215. // admin/structure/views/ajax/categorise-item/<view_name>/<display_name>/<type>/<id>
  1216. $forms['categorise-item'] = array(
  1217. 'form_id' => 'mymodule_views_categorize_fields_form',
  1218. 'args' => array('type', 'id'),
  1219. );
  1220. // Modify the add-item form callback.
  1221. // You would then implement the form function
  1222. // mymodule_add_item_form_custom(), which would override the existing
  1223. // views_ui_add_item_form().
  1224. // Note that you would likely use hook_form_alter() in this case instead of
  1225. // doing this, this is just an example.
  1226. $forms['add-item']['form_id'] = 'mymodule_add_item_form_custom';
  1227. }
  1228. /**
  1229. * Allows altering the commands which are used on a views AJAX request.
  1230. *
  1231. * @param array $commands
  1232. * An array of ajax commands.
  1233. * @param object $view
  1234. * The view which is requested.
  1235. */
  1236. function hook_views_ajax_data_alter(&$commands, $view) {
  1237. // Replace Views' method for scrolling to the top of the element with your
  1238. // custom scrolling method.
  1239. foreach ($commands as &$command) {
  1240. if ($command['command'] == 'viewsScrollTop') {
  1241. $command['command'] .= 'myScrollTop';
  1242. }
  1243. }
  1244. }
  1245. /**
  1246. * Allow modules to respond to the Views cache being invalidated.
  1247. *
  1248. * This hook should fire whenever a view is enabled, disabled, created,
  1249. * updated, or deleted.
  1250. *
  1251. * @param string $cid
  1252. * The cache identifier that is being cleared.
  1253. *
  1254. * @see views_invalidate_cache()
  1255. */
  1256. function hook_views_invalidate_cache($cid) {
  1257. cache_clear_all('views:*', 'cache_mymodule', TRUE);
  1258. }
  1259. /**
  1260. * Allow modules to alter a view prior to being saved.
  1261. */
  1262. function hook_views_view_presave($view) {
  1263. // Do some adjustments to the view. Handle with care.
  1264. if (mymodule_check_view($view)) {
  1265. mymodule_do_some_voodoo($view);
  1266. }
  1267. }
  1268. /**
  1269. * Allow modules to respond to a view being saved.
  1270. */
  1271. function hook_views_view_save($view) {
  1272. // Make a watchdog entry.
  1273. watchdog('views', 'The view @name was deleted by @user at @time', array('@name' => $view->name, '@user' => $GLOBALS['user']->name, '@time' => format_date(time())));
  1274. }
  1275. /**
  1276. * Allow modules to respond to a view being deleted or reverted.
  1277. */
  1278. function hook_views_view_delete($view) {
  1279. // Make a watchdog entry.
  1280. watchdog('views', 'The view @name was deleted by @user at @time', array('@name' => $view->name, '@user' => $GLOBALS['user']->name, '@time' => format_date(time())));
  1281. }
  1282. /**
  1283. * @}
  1284. */
  1285. /**
  1286. * @defgroup views_module_handlers Views module handlers
  1287. * @{
  1288. * Handlers exposed by various modules to Views.
  1289. * @}
  1290. */