plugins.inc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  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',
  161. // only shows up as a summary style.
  162. 'uses options' => TRUE,
  163. 'help topic' => 'style-summary',
  164. ),
  165. 'unformatted_summary' => array(
  166. 'title' => t('Unformatted'),
  167. 'help' => t('Displays the summary unformatted, with option for one after another or inline.'),
  168. 'handler' => 'views_plugin_style_summary_unformatted',
  169. 'theme' => 'views_view_summary_unformatted',
  170. 'type' => 'summary',
  171. // only shows up as a summary style.
  172. 'uses options' => TRUE,
  173. 'help topic' => 'style-summary-unformatted',
  174. ),
  175. 'rss' => array(
  176. 'title' => t('RSS Feed'),
  177. 'help' => t('Generates an RSS feed from a view.'),
  178. 'handler' => 'views_plugin_style_rss',
  179. 'theme' => 'views_view_rss',
  180. 'uses row plugin' => TRUE,
  181. 'uses options' => TRUE,
  182. 'type' => 'feed',
  183. 'help topic' => 'style-rss',
  184. ),
  185. ),
  186. 'row' => array(
  187. 'fields' => array(
  188. 'title' => t('Fields'),
  189. 'help' => t('Displays the fields with an optional template.'),
  190. 'handler' => 'views_plugin_row_fields',
  191. 'theme' => 'views_view_fields',
  192. 'uses fields' => TRUE,
  193. 'uses options' => TRUE,
  194. 'type' => 'normal',
  195. 'help topic' => 'style-row-fields',
  196. ),
  197. 'rss_fields' => array(
  198. 'title' => t('Fields'),
  199. 'help' => t('Display fields as RSS items.'),
  200. 'handler' => 'views_plugin_row_rss_fields',
  201. 'theme' => 'views_view_row_rss',
  202. 'uses fields' => TRUE,
  203. 'uses options' => TRUE,
  204. 'type' => 'feed',
  205. 'help topic' => 'style-row-fields',
  206. ),
  207. ),
  208. 'argument default' => array(
  209. 'parent' => array(
  210. 'no ui' => TRUE,
  211. 'handler' => 'views_plugin_argument_default',
  212. 'parent' => '',
  213. ),
  214. 'fixed' => array(
  215. 'title' => t('Fixed value'),
  216. 'handler' => 'views_plugin_argument_default_fixed',
  217. ),
  218. 'php' => array(
  219. 'title' => t('PHP Code'),
  220. 'handler' => 'views_plugin_argument_default_php',
  221. ),
  222. 'raw' => array(
  223. 'title' => t('Raw value from URL'),
  224. 'handler' => 'views_plugin_argument_default_raw',
  225. ),
  226. ),
  227. 'argument validator' => array(
  228. 'php' => array(
  229. 'title' => t('PHP Code'),
  230. 'handler' => 'views_plugin_argument_validate_php',
  231. ),
  232. 'numeric' => array(
  233. 'title' => t('Numeric'),
  234. 'handler' => 'views_plugin_argument_validate_numeric',
  235. ),
  236. ),
  237. 'access' => array(
  238. 'none' => array(
  239. 'title' => t('None'),
  240. 'help' => t('Will be available to all users.'),
  241. 'handler' => 'views_plugin_access_none',
  242. 'help topic' => 'access-none',
  243. ),
  244. 'role' => array(
  245. 'title' => t('Role'),
  246. 'help' => t('Access will be granted to users with any of the specified roles.'),
  247. 'handler' => 'views_plugin_access_role',
  248. 'uses options' => TRUE,
  249. 'help topic' => 'access-role',
  250. ),
  251. 'perm' => array(
  252. 'title' => t('Permission'),
  253. 'help' => t('Access will be granted to users with the specified permission string.'),
  254. 'handler' => 'views_plugin_access_perm',
  255. 'uses options' => TRUE,
  256. 'help topic' => 'access-perm',
  257. ),
  258. ),
  259. 'query' => array(
  260. 'parent' => array(
  261. 'no ui' => TRUE,
  262. 'handler' => 'views_plugin_query',
  263. 'parent' => '',
  264. ),
  265. 'views_query' => array(
  266. 'title' => t('SQL Query'),
  267. 'help' => t('Query will be generated and run using the Drupal database API.'),
  268. 'handler' => 'views_plugin_query_default',
  269. ),
  270. ),
  271. 'cache' => array(
  272. 'parent' => array(
  273. 'no ui' => TRUE,
  274. 'handler' => 'views_plugin_cache',
  275. 'parent' => '',
  276. ),
  277. 'none' => array(
  278. 'title' => t('None'),
  279. 'help' => t('No caching of Views data.'),
  280. 'handler' => 'views_plugin_cache_none',
  281. 'help topic' => 'cache-none',
  282. ),
  283. 'time' => array(
  284. 'title' => t('Time-based'),
  285. 'help' => t('Simple time-based caching of data.'),
  286. 'handler' => 'views_plugin_cache_time',
  287. 'uses options' => TRUE,
  288. 'help topic' => 'cache-time',
  289. ),
  290. ),
  291. 'exposed_form' => array(
  292. 'parent' => array(
  293. 'no ui' => TRUE,
  294. 'handler' => 'views_plugin_exposed_form',
  295. 'parent' => '',
  296. ),
  297. 'basic' => array(
  298. 'title' => t('Basic'),
  299. 'help' => t('Basic exposed form'),
  300. 'handler' => 'views_plugin_exposed_form_basic',
  301. 'uses options' => TRUE,
  302. 'help topic' => 'exposed-form-basic',
  303. ),
  304. 'input_required' => array(
  305. 'title' => t('Input required'),
  306. 'help' => t('An exposed form that only renders a view if the form contains user input.'),
  307. 'handler' => 'views_plugin_exposed_form_input_required',
  308. 'uses options' => TRUE,
  309. 'help topic' => 'exposed-form-input-required',
  310. ),
  311. ),
  312. 'pager' => array(
  313. 'parent' => array(
  314. 'no ui' => TRUE,
  315. 'handler' => 'views_plugin_pager',
  316. 'parent' => '',
  317. ),
  318. 'none' => array(
  319. 'title' => t('Display all items'),
  320. 'help' => t("Display all items that this view might find"),
  321. 'handler' => 'views_plugin_pager_none',
  322. 'help topic' => 'pager-none',
  323. 'uses options' => TRUE,
  324. 'type' => 'basic',
  325. ),
  326. 'some' => array(
  327. 'title' => t('Display a specified number of items'),
  328. 'help' => t('Display a limited number items that this view might find.'),
  329. 'handler' => 'views_plugin_pager_some',
  330. 'help topic' => 'pager-some',
  331. 'uses options' => TRUE,
  332. 'type' => 'basic',
  333. ),
  334. 'full' => array(
  335. 'title' => t('Paged output, full pager'),
  336. 'short title' => t('Full'),
  337. 'help' => t('Paged output, full Drupal style'),
  338. 'handler' => 'views_plugin_pager_full',
  339. 'help topic' => 'pager-full',
  340. 'uses options' => TRUE,
  341. ),
  342. 'mini' => array(
  343. 'title' => t('Paged output, mini pager'),
  344. 'short title' => t('Mini'),
  345. 'help' => t('Use the mini pager output.'),
  346. 'handler' => 'views_plugin_pager_mini',
  347. 'help topic' => 'pager-mini',
  348. 'uses options' => TRUE,
  349. 'parent' => 'full',
  350. ),
  351. ),
  352. 'localization' => array(
  353. 'parent' => array(
  354. 'no ui' => TRUE,
  355. 'handler' => 'views_plugin_localization',
  356. 'parent' => '',
  357. ),
  358. 'none' => array(
  359. 'title' => t('None'),
  360. 'help' => t('Do not pass admin strings for translation.'),
  361. 'handler' => 'views_plugin_localization_none',
  362. 'help topic' => 'localization-none',
  363. ),
  364. 'core' => array(
  365. 'title' => t('Core'),
  366. 'help' => t("Use Drupal core t() function. Not recommended, as it doesn't support updates to existing strings."),
  367. 'handler' => 'views_plugin_localization_core',
  368. 'help topic' => 'localization-core',
  369. ),
  370. ),
  371. );
  372. // Add a help message pointing to the i18views module if it is not present.
  373. if (!module_exists('i18nviews')) {
  374. $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))));
  375. }
  376. if (module_invoke('ctools', 'api_version', '1.3')) {
  377. $plugins['style']['jump_menu_summary'] = array(
  378. 'title' => t('Jump menu'),
  379. '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.'),
  380. 'handler' => 'views_plugin_style_summary_jump_menu',
  381. 'theme' => 'views_view_summary_jump_menu',
  382. 'type' => 'summary',
  383. // only shows up as a summary style.
  384. 'uses options' => TRUE,
  385. 'help topic' => 'style-summary-jump-menu',
  386. );
  387. $plugins['style']['jump_menu'] = array(
  388. 'title' => t('Jump menu'),
  389. '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.'),
  390. 'handler' => 'views_plugin_style_jump_menu',
  391. 'theme' => 'views_view_jump_menu',
  392. 'uses row plugin' => TRUE,
  393. 'uses fields' => TRUE,
  394. 'uses options' => TRUE,
  395. 'type' => 'normal',
  396. 'help topic' => 'style-jump-menu',
  397. );
  398. }
  399. return $plugins;
  400. }
  401. /**
  402. * Builds and return a list of all plugins available in the system.
  403. *
  404. * @return Nested array of plugins, grouped by type.
  405. */
  406. function views_discover_plugins() {
  407. $cache = array('display' => array(), 'style' => array(), 'row' => array(), 'argument default' => array(), 'argument validator' => array(), 'access' => array(), 'cache' => array(), 'exposed_form' => array());
  408. // Get plugins from all modules.
  409. foreach (module_implements('views_plugins') as $module) {
  410. $function = $module . '_views_plugins';
  411. $result = $function();
  412. if (!is_array($result)) {
  413. continue;
  414. }
  415. $module_dir = isset($result['module']) ? $result['module'] : $module;
  416. // Setup automatic path/file finding for theme registration.
  417. if ($module_dir == 'views') {
  418. $theme_path = drupal_get_path('module', $module_dir) . '/theme';
  419. $theme_file = 'theme.inc';
  420. $path = drupal_get_path('module', $module_dir) . '/plugins';
  421. }
  422. else {
  423. $theme_path = $path = drupal_get_path('module', $module_dir);
  424. $theme_file = "$module.views.inc";
  425. }
  426. foreach ($result as $type => $info) {
  427. if ($type == 'module') {
  428. continue;
  429. }
  430. foreach ($info as $plugin => $def) {
  431. $def['module'] = $module_dir;
  432. if (!isset($def['theme path'])) {
  433. $def['theme path'] = $theme_path;
  434. }
  435. if (!isset($def['theme file'])) {
  436. $def['theme file'] = $theme_file;
  437. }
  438. if (!isset($def['path'])) {
  439. $def['path'] = $path;
  440. }
  441. if (!isset($def['file'])) {
  442. $def['file'] = $def['handler'] . '.inc';
  443. }
  444. if (!isset($def['parent'])) {
  445. $def['parent'] = 'parent';
  446. }
  447. // Set the internal name to be able to read it out later.
  448. $def['name'] = $plugin;
  449. // merge the new data in.
  450. $cache[$type][$plugin] = $def;
  451. }
  452. }
  453. }
  454. // Let other modules modify the plugins.
  455. drupal_alter('views_plugins', $cache);
  456. return $cache;
  457. }
  458. /**
  459. * Abstract base class to provide interface common to all plugins.
  460. */
  461. class views_plugin extends views_object {
  462. /**
  463. * The top object of a view.
  464. *
  465. * @var view
  466. */
  467. public $view = NULL;
  468. /**
  469. * The current used views display.
  470. *
  471. * @var views_display
  472. */
  473. public $display = NULL;
  474. /**
  475. * The plugin type of this plugin, for example style or query.
  476. */
  477. public $plugin_type = NULL;
  478. /**
  479. * The plugin name of this plugin, for example table or full.
  480. */
  481. public $plugin_name = NULL;
  482. /**
  483. * Init will be called after construct, when the plugin is attached to a
  484. * view and a display.
  485. */
  486. /**
  487. * Provide a form to edit options for this plugin.
  488. */
  489. public function options_form(&$form, &$form_state) {
  490. // Some form elements belong in a fieldset for presentation, but can't
  491. // be moved into one because of the form_state['values'] hierarchy. Those
  492. // elements can add a #fieldset => 'fieldset_name' property, and they'll
  493. // be moved to their fieldset during pre_render.
  494. $form['#pre_render'][] = 'views_ui_pre_render_add_fieldset_markup';
  495. }
  496. /**
  497. * Validate the options form.
  498. */
  499. public function options_validate(&$form, &$form_state) {
  500. }
  501. /**
  502. * Handle any special handling on the validate form.
  503. */
  504. public function options_submit(&$form, &$form_state) {
  505. }
  506. /**
  507. * Add anything to the query that we might need to.
  508. */
  509. public function query() {
  510. }
  511. /**
  512. * Provide a full list of possible theme templates used by this style.
  513. */
  514. public function theme_functions() {
  515. if (empty($this->definition['theme'])) {
  516. $this->definition['theme'] = 'views_view';
  517. }
  518. return views_theme_functions($this->definition['theme'], $this->view, $this->display);
  519. }
  520. /**
  521. * Provide a list of additional theme functions for the theme info page.
  522. */
  523. public function additional_theme_functions() {
  524. $funcs = array();
  525. if (!empty($this->definition['additional themes'])) {
  526. foreach ($this->definition['additional themes'] as $theme => $type) {
  527. $funcs[] = views_theme_functions($theme, $this->view, $this->display);
  528. }
  529. }
  530. return $funcs;
  531. }
  532. /**
  533. * Validate that the plugin is correct and can be saved.
  534. *
  535. * @return array
  536. * An array of error strings to tell the user what is wrong with this
  537. * plugin.
  538. */
  539. public function validate() {
  540. return array();
  541. }
  542. /**
  543. * Returns the summary of the settings in the display.
  544. */
  545. public function summary_title() {
  546. return t('Settings');
  547. }
  548. /**
  549. * Return the human readable name of the display.
  550. *
  551. * This appears on the ui beside each plugin and beside the settings link.
  552. */
  553. public function plugin_title() {
  554. if (isset($this->definition['short title'])) {
  555. return check_plain($this->definition['short title']);
  556. }
  557. return check_plain($this->definition['title']);
  558. }
  559. }
  560. /**
  561. * Get enabled display extenders.
  562. */
  563. function views_get_enabled_display_extenders() {
  564. $enabled = array_filter(variable_get('views_display_extenders', array()));
  565. $options = views_fetch_plugin_names('display_extender');
  566. foreach ($options as $name => $plugin) {
  567. $enabled[$name] = $name;
  568. }
  569. return $enabled;
  570. }