plugins.inc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587
  1. <?php
  2. /**
  3. * @file
  4. * Built in plugins for Views output handling.
  5. */
  6. // @todo: Remove this once update.php can use the registry
  7. views_include('base');
  8. /**
  9. * Implements hook_views_plugins().
  10. */
  11. function views_views_plugins() {
  12. $js_path = drupal_get_path('module', 'ctools') . '/js';
  13. $plugins = array(
  14. // display, style, row, argument default, argument validator and access.
  15. 'display' => array(
  16. // Default settings for all display plugins.
  17. 'default' => array(
  18. 'title' => t('Master'),
  19. 'help' => t('Default settings for this view.'),
  20. 'handler' => 'views_plugin_display_default',
  21. 'theme' => 'views_view',
  22. 'no ui' => TRUE,
  23. 'no remove' => TRUE,
  24. 'js' => array('misc/form.js', 'misc/collapse.js', 'misc/textarea.js', 'misc/tabledrag.js', 'misc/autocomplete.js', "$js_path/dependent.js"),
  25. 'use ajax' => TRUE,
  26. 'use pager' => TRUE,
  27. 'use more' => TRUE,
  28. 'accept attachments' => TRUE,
  29. 'help topic' => 'display-default',
  30. ),
  31. 'page' => array(
  32. 'title' => t('Page'),
  33. 'help' => t('Display the view as a page, with a URL and menu links.'),
  34. 'handler' => 'views_plugin_display_page',
  35. 'theme' => 'views_view',
  36. 'uses hook menu' => TRUE,
  37. 'contextual links locations' => array('page'),
  38. 'use ajax' => TRUE,
  39. 'use pager' => TRUE,
  40. 'use more' => TRUE,
  41. 'accept attachments' => TRUE,
  42. 'admin' => t('Page'),
  43. 'help topic' => 'display-page',
  44. ),
  45. 'block' => array(
  46. 'title' => t('Block'),
  47. 'help' => t('Display the view as a block.'),
  48. 'handler' => 'views_plugin_display_block',
  49. 'theme' => 'views_view',
  50. 'uses hook block' => TRUE,
  51. 'contextual links locations' => array('block'),
  52. 'use ajax' => TRUE,
  53. 'use pager' => TRUE,
  54. 'use more' => TRUE,
  55. 'accept attachments' => TRUE,
  56. 'admin' => t('Block'),
  57. 'help topic' => 'display-block',
  58. ),
  59. 'attachment' => array(
  60. 'title' => t('Attachment'),
  61. 'help' => t('Attachments added to other displays to achieve multiple views in the same view.'),
  62. 'handler' => 'views_plugin_display_attachment',
  63. 'theme' => 'views_view',
  64. 'contextual links locations' => array(),
  65. 'use ajax' => TRUE,
  66. 'use pager' => FALSE,
  67. 'use more' => TRUE,
  68. 'accept attachments' => FALSE,
  69. 'help topic' => 'display-attachment',
  70. ),
  71. 'feed' => array(
  72. 'title' => t('Feed'),
  73. 'help' => t('Display the view as a feed, such as an RSS feed.'),
  74. 'handler' => 'views_plugin_display_feed',
  75. 'uses hook menu' => TRUE,
  76. 'use ajax' => FALSE,
  77. 'use pager' => FALSE,
  78. 'accept attachments' => FALSE,
  79. 'admin' => t('Feed'),
  80. 'help topic' => 'display-feed',
  81. ),
  82. 'embed' => array(
  83. 'title' => t('Embed'),
  84. 'help' => t('Provide a display which can be embedded using the views api.'),
  85. 'handler' => 'views_plugin_display_embed',
  86. 'theme' => 'views_view',
  87. 'uses hook menu' => FALSE,
  88. 'use ajax' => TRUE,
  89. 'use pager' => TRUE,
  90. 'accept attachments' => FALSE,
  91. 'admin' => t('Embed'),
  92. 'no ui' => !variable_get('views_ui_display_embed', FALSE),
  93. ),
  94. ),
  95. 'display_extender' => array(
  96. // Default settings for all display_extender plugins.
  97. 'default' => array(
  98. 'title' => t('Empty display extender'),
  99. 'help' => t('Default settings for this view.'),
  100. 'handler' => 'views_plugin_display_extender',
  101. // You can force the plugin to be enabled
  102. 'enabled' => FALSE,
  103. 'no ui' => TRUE,
  104. ),
  105. ),
  106. 'style' => array(
  107. // Default settings for all style plugins.
  108. 'default' => array(
  109. 'title' => t('Unformatted list'),
  110. 'help' => t('Displays rows one after another.'),
  111. 'handler' => 'views_plugin_style_default',
  112. 'theme' => 'views_view_unformatted',
  113. 'uses row plugin' => TRUE,
  114. 'uses row class' => TRUE,
  115. 'uses grouping' => TRUE,
  116. 'uses options' => TRUE,
  117. 'type' => 'normal',
  118. 'help topic' => 'style-unformatted',
  119. ),
  120. 'list' => array(
  121. 'title' => t('HTML list'),
  122. 'help' => t('Displays rows as an HTML list.'),
  123. 'handler' => 'views_plugin_style_list',
  124. 'theme' => 'views_view_list',
  125. 'uses row plugin' => TRUE,
  126. 'uses row class' => TRUE,
  127. 'uses options' => TRUE,
  128. 'type' => 'normal',
  129. 'help topic' => 'style-list',
  130. ),
  131. 'grid' => array(
  132. 'title' => t('Grid'),
  133. 'help' => t('Displays rows in a grid.'),
  134. 'handler' => 'views_plugin_style_grid',
  135. 'theme' => 'views_view_grid',
  136. 'uses fields' => FALSE,
  137. 'uses row plugin' => TRUE,
  138. 'uses row class' => TRUE,
  139. 'uses options' => TRUE,
  140. 'type' => 'normal',
  141. 'help topic' => 'style-grid',
  142. ),
  143. 'table' => array(
  144. 'title' => t('Table'),
  145. 'help' => t('Displays rows in a table.'),
  146. 'handler' => 'views_plugin_style_table',
  147. 'theme' => 'views_view_table',
  148. 'uses row plugin' => FALSE,
  149. 'uses row class' => TRUE,
  150. 'uses fields' => TRUE,
  151. 'uses options' => TRUE,
  152. 'type' => 'normal',
  153. 'help topic' => 'style-table',
  154. ),
  155. 'default_summary' => array(
  156. 'title' => t('List'),
  157. 'help' => t('Displays the default summary as a list.'),
  158. 'handler' => 'views_plugin_style_summary',
  159. 'theme' => 'views_view_summary',
  160. 'type' => 'summary', // only shows up as a summary style
  161. 'uses options' => TRUE,
  162. 'help topic' => 'style-summary',
  163. ),
  164. 'unformatted_summary' => array(
  165. 'title' => t('Unformatted'),
  166. 'help' => t('Displays the summary unformatted, with option for one after another or inline.'),
  167. 'handler' => 'views_plugin_style_summary_unformatted',
  168. 'theme' => 'views_view_summary_unformatted',
  169. 'type' => 'summary', // only shows up as a summary style
  170. 'uses options' => TRUE,
  171. 'help topic' => 'style-summary-unformatted',
  172. ),
  173. 'rss' => array(
  174. 'title' => t('RSS Feed'),
  175. 'help' => t('Generates an RSS feed from a view.'),
  176. 'handler' => 'views_plugin_style_rss',
  177. 'theme' => 'views_view_rss',
  178. 'uses row plugin' => TRUE,
  179. 'uses options' => TRUE,
  180. 'type' => 'feed',
  181. 'help topic' => 'style-rss',
  182. ),
  183. ),
  184. 'row' => array(
  185. 'fields' => array(
  186. 'title' => t('Fields'),
  187. 'help' => t('Displays the fields with an optional template.'),
  188. 'handler' => 'views_plugin_row_fields',
  189. 'theme' => 'views_view_fields',
  190. 'uses fields' => TRUE,
  191. 'uses options' => TRUE,
  192. 'type' => 'normal',
  193. 'help topic' => 'style-row-fields',
  194. ),
  195. 'rss_fields' => array(
  196. 'title' => t('Fields'),
  197. 'help' => t('Display fields as RSS items.'),
  198. 'handler' => 'views_plugin_row_rss_fields',
  199. 'theme' => 'views_view_row_rss',
  200. 'uses fields' => TRUE,
  201. 'uses options' => TRUE,
  202. 'type' => 'feed',
  203. 'help topic' => 'style-row-fields',
  204. ),
  205. ),
  206. 'argument default' => array(
  207. 'parent' => array(
  208. 'no ui' => TRUE,
  209. 'handler' => 'views_plugin_argument_default',
  210. 'parent' => '',
  211. ),
  212. 'fixed' => array(
  213. 'title' => t('Fixed value'),
  214. 'handler' => 'views_plugin_argument_default_fixed',
  215. ),
  216. 'php' => array(
  217. 'title' => t('PHP Code'),
  218. 'handler' => 'views_plugin_argument_default_php',
  219. ),
  220. 'raw' => array(
  221. 'title' => t('Raw value from URL'),
  222. 'handler' => 'views_plugin_argument_default_raw',
  223. ),
  224. ),
  225. 'argument validator' => array(
  226. 'php' => array(
  227. 'title' => t('PHP Code'),
  228. 'handler' => 'views_plugin_argument_validate_php',
  229. ),
  230. 'numeric' => array(
  231. 'title' => t('Numeric'),
  232. 'handler' => 'views_plugin_argument_validate_numeric',
  233. ),
  234. ),
  235. 'access' => array(
  236. 'none' => array(
  237. 'title' => t('None'),
  238. 'help' => t('Will be available to all users.'),
  239. 'handler' => 'views_plugin_access_none',
  240. 'help topic' => 'access-none',
  241. ),
  242. 'role' => array(
  243. 'title' => t('Role'),
  244. 'help' => t('Access will be granted to users with any of the specified roles.'),
  245. 'handler' => 'views_plugin_access_role',
  246. 'uses options' => TRUE,
  247. 'help topic' => 'access-role',
  248. ),
  249. 'perm' => array(
  250. 'title' => t('Permission'),
  251. 'help' => t('Access will be granted to users with the specified permission string.'),
  252. 'handler' => 'views_plugin_access_perm',
  253. 'uses options' => TRUE,
  254. 'help topic' => 'access-perm',
  255. ),
  256. ),
  257. 'query' => array(
  258. 'parent' => array(
  259. 'no ui' => TRUE,
  260. 'handler' => 'views_plugin_query',
  261. 'parent' => '',
  262. ),
  263. 'views_query' => array(
  264. 'title' => t('SQL Query'),
  265. 'help' => t('Query will be generated and run using the Drupal database API.'),
  266. 'handler' => 'views_plugin_query_default'
  267. ),
  268. ),
  269. 'cache' => array(
  270. 'parent' => array(
  271. 'no ui' => TRUE,
  272. 'handler' => 'views_plugin_cache',
  273. 'parent' => '',
  274. ),
  275. 'none' => array(
  276. 'title' => t('None'),
  277. 'help' => t('No caching of Views data.'),
  278. 'handler' => 'views_plugin_cache_none',
  279. 'help topic' => 'cache-none',
  280. ),
  281. 'time' => array(
  282. 'title' => t('Time-based'),
  283. 'help' => t('Simple time-based caching of data.'),
  284. 'handler' => 'views_plugin_cache_time',
  285. 'uses options' => TRUE,
  286. 'help topic' => 'cache-time',
  287. ),
  288. ),
  289. 'exposed_form' => array(
  290. 'parent' => array(
  291. 'no ui' => TRUE,
  292. 'handler' => 'views_plugin_exposed_form',
  293. 'parent' => '',
  294. ),
  295. 'basic' => array(
  296. 'title' => t('Basic'),
  297. 'help' => t('Basic exposed form'),
  298. 'handler' => 'views_plugin_exposed_form_basic',
  299. 'uses options' => TRUE,
  300. 'help topic' => 'exposed-form-basic',
  301. ),
  302. 'input_required' => array(
  303. 'title' => t('Input required'),
  304. 'help' => t('An exposed form that only renders a view if the form contains user input.'),
  305. 'handler' => 'views_plugin_exposed_form_input_required',
  306. 'uses options' => TRUE,
  307. 'help topic' => 'exposed-form-input-required',
  308. ),
  309. ),
  310. 'pager' => array(
  311. 'parent' => array(
  312. 'no ui' => TRUE,
  313. 'handler' => 'views_plugin_pager',
  314. 'parent' => '',
  315. ),
  316. 'none' => array(
  317. 'title' => t('Display all items'),
  318. 'help' => t("Display all items that this view might find"),
  319. 'handler' => 'views_plugin_pager_none',
  320. 'help topic' => 'pager-none',
  321. 'uses options' => TRUE,
  322. 'type' => 'basic',
  323. ),
  324. 'some' => array(
  325. 'title' => t('Display a specified number of items'),
  326. 'help' => t('Display a limited number items that this view might find.'),
  327. 'handler' => 'views_plugin_pager_some',
  328. 'help topic' => 'pager-some',
  329. 'uses options' => TRUE,
  330. 'type' => 'basic',
  331. ),
  332. 'full' => array(
  333. 'title' => t('Paged output, full pager'),
  334. 'short title' => t('Full'),
  335. 'help' => t('Paged output, full Drupal style'),
  336. 'handler' => 'views_plugin_pager_full',
  337. 'help topic' => 'pager-full',
  338. 'uses options' => TRUE,
  339. ),
  340. 'mini' => array(
  341. 'title' => t('Paged output, mini pager'),
  342. 'short title' => t('Mini'),
  343. 'help' => t('Use the mini pager output.'),
  344. 'handler' => 'views_plugin_pager_mini',
  345. 'help topic' => 'pager-mini',
  346. 'uses options' => TRUE,
  347. 'parent' => 'full',
  348. ),
  349. ),
  350. 'localization' => array(
  351. 'parent' => array(
  352. 'no ui' => TRUE,
  353. 'handler' => 'views_plugin_localization',
  354. 'parent' => '',
  355. ),
  356. 'none' => array(
  357. 'title' => t('None'),
  358. 'help' => t('Do not pass admin strings for translation.'),
  359. 'handler' => 'views_plugin_localization_none',
  360. 'help topic' => 'localization-none',
  361. ),
  362. 'core' => array(
  363. 'title' => t('Core'),
  364. 'help' => t("Use Drupal core t() function. Not recommended, as it doesn't support updates to existing strings."),
  365. 'handler' => 'views_plugin_localization_core',
  366. 'help topic' => 'localization-core',
  367. ),
  368. ),
  369. );
  370. // Add a help message pointing to the i18views module if it is not present.
  371. if (!module_exists('i18nviews')) {
  372. $plugins['localization']['core']['help'] .= ' ' . t('If you need to translate Views labels into other languages, consider installing the <a href="!path">Internationalization</a> package\'s Views translation module.', array('!path' => url('http://drupal.org/project/i18n', array('absolute' => TRUE))));
  373. }
  374. if (module_invoke('ctools', 'api_version', '1.3')) {
  375. $plugins['style']['jump_menu_summary'] = array(
  376. 'title' => t('Jump menu'),
  377. 'help' => t('Puts all of the results into a select box and allows the user to go to a different page based upon the results.'),
  378. 'handler' => 'views_plugin_style_summary_jump_menu',
  379. 'theme' => 'views_view_summary_jump_menu',
  380. 'type' => 'summary', // only shows up as a summary style
  381. 'uses options' => TRUE,
  382. 'help topic' => 'style-summary-jump-menu',
  383. );
  384. $plugins['style']['jump_menu'] = array(
  385. 'title' => t('Jump menu'),
  386. 'help' => t('Puts all of the results into a select box and allows the user to go to a different page based upon the results.'),
  387. 'handler' => 'views_plugin_style_jump_menu',
  388. 'theme' => 'views_view_jump_menu',
  389. 'uses row plugin' => TRUE,
  390. 'uses fields' => TRUE,
  391. 'uses options' => TRUE,
  392. 'type' => 'normal',
  393. 'help topic' => 'style-jump-menu',
  394. );
  395. }
  396. return $plugins;
  397. }
  398. /**
  399. * Builds and return a list of all plugins available in the system.
  400. *
  401. * @return Nested array of plugins, grouped by type.
  402. */
  403. function views_discover_plugins() {
  404. $cache = array('display' => array(), 'style' => array(), 'row' => array(), 'argument default' => array(), 'argument validator' => array(), 'access' => array(), 'cache' => array(), 'exposed_form' => array());
  405. // Get plugins from all modules.
  406. foreach (module_implements('views_plugins') as $module) {
  407. $function = $module . '_views_plugins';
  408. $result = $function();
  409. if (!is_array($result)) {
  410. continue;
  411. }
  412. $module_dir = isset($result['module']) ? $result['module'] : $module;
  413. // Setup automatic path/file finding for theme registration
  414. if ($module_dir == 'views') {
  415. $theme_path = drupal_get_path('module', $module_dir) . '/theme';
  416. $theme_file = 'theme.inc';
  417. $path = drupal_get_path('module', $module_dir) . '/plugins';
  418. }
  419. else {
  420. $theme_path = $path = drupal_get_path('module', $module_dir);
  421. $theme_file = "$module.views.inc";
  422. }
  423. foreach ($result as $type => $info) {
  424. if ($type == 'module') {
  425. continue;
  426. }
  427. foreach ($info as $plugin => $def) {
  428. $def['module'] = $module_dir;
  429. if (!isset($def['theme path'])) {
  430. $def['theme path'] = $theme_path;
  431. }
  432. if (!isset($def['theme file'])) {
  433. $def['theme file'] = $theme_file;
  434. }
  435. if (!isset($def['path'])) {
  436. $def['path'] = $path;
  437. }
  438. if (!isset($def['file'])) {
  439. $def['file'] = $def['handler'] . '.inc';
  440. }
  441. if (!isset($def['parent'])) {
  442. $def['parent'] = 'parent';
  443. }
  444. // Set the internal name to be able to read it out later.
  445. $def['name'] = $plugin;
  446. // merge the new data in
  447. $cache[$type][$plugin] = $def;
  448. }
  449. }
  450. }
  451. // Let other modules modify the plugins.
  452. drupal_alter('views_plugins', $cache);
  453. return $cache;
  454. }
  455. /**
  456. * Abstract base class to provide interface common to all plugins.
  457. */
  458. class views_plugin extends views_object {
  459. /**
  460. * The top object of a view.
  461. *
  462. * @var view
  463. */
  464. var $view = NULL;
  465. /**
  466. * The current used views display.
  467. *
  468. * @var views_display
  469. */
  470. var $display = NULL;
  471. /**
  472. * The plugin type of this plugin, for example style or query.
  473. */
  474. var $plugin_type = NULL;
  475. /**
  476. * The plugin name of this plugin, for example table or full.
  477. */
  478. var $plugin_name = NULL;
  479. /**
  480. * Init will be called after construct, when the plugin is attached to a
  481. * view and a display.
  482. */
  483. /**
  484. * Provide a form to edit options for this plugin.
  485. */
  486. function options_form(&$form, &$form_state) {
  487. // Some form elements belong in a fieldset for presentation, but can't
  488. // be moved into one because of the form_state['values'] hierarchy. Those
  489. // elements can add a #fieldset => 'fieldset_name' property, and they'll
  490. // be moved to their fieldset during pre_render.
  491. $form['#pre_render'][] = 'views_ui_pre_render_add_fieldset_markup';
  492. }
  493. /**
  494. * Validate the options form.
  495. */
  496. function options_validate(&$form, &$form_state) { }
  497. /**
  498. * Handle any special handling on the validate form.
  499. */
  500. function options_submit(&$form, &$form_state) { }
  501. /**
  502. * Add anything to the query that we might need to.
  503. */
  504. function query() { }
  505. /**
  506. * Provide a full list of possible theme templates used by this style.
  507. */
  508. function theme_functions() {
  509. if (empty($this->definition['theme'])) {
  510. $this->definition['theme'] = 'views_view';
  511. }
  512. return views_theme_functions($this->definition['theme'], $this->view, $this->display);
  513. }
  514. /**
  515. * Provide a list of additional theme functions for the theme information page
  516. */
  517. function additional_theme_functions() {
  518. $funcs = array();
  519. if (!empty($this->definition['additional themes'])) {
  520. foreach ($this->definition['additional themes'] as $theme => $type) {
  521. $funcs[] = views_theme_functions($theme, $this->view, $this->display);
  522. }
  523. }
  524. return $funcs;
  525. }
  526. /**
  527. * Validate that the plugin is correct and can be saved.
  528. *
  529. * @return
  530. * An array of error strings to tell the user what is wrong with this
  531. * plugin.
  532. */
  533. function validate() { return array(); }
  534. /**
  535. * Returns the summary of the settings in the display.
  536. */
  537. function summary_title() {
  538. return t('Settings');
  539. }
  540. /**
  541. * Return the human readable name of the display.
  542. *
  543. * This appears on the ui beside each plugin and beside the settings link.
  544. */
  545. function plugin_title() {
  546. if (isset($this->definition['short title'])) {
  547. return check_plain($this->definition['short title']);
  548. }
  549. return check_plain($this->definition['title']);
  550. }
  551. }
  552. /**
  553. * Get enabled display extenders.
  554. */
  555. function views_get_enabled_display_extenders() {
  556. $enabled = array_filter(variable_get('views_display_extenders', array()));
  557. $options = views_fetch_plugin_names('display_extender');
  558. foreach ($options as $name => $plugin) {
  559. $enabled[$name] = $name;
  560. }
  561. return $enabled;
  562. }