theming_example.module 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. <?php
  2. /**
  3. * @file
  4. * Explains how a module declares theme functions, preprocess functions, and
  5. * templates.
  6. *
  7. * The underlying approach is that a module should allow themes to do all
  8. * rendering, but provide default implementations where appropriate.
  9. *
  10. * Modules are also expected to leave data as render arrays as long as possible,
  11. * leaving rendering to theme functions and templates.
  12. */
  13. /**
  14. * @defgroup theming_example Example: Theming
  15. * @ingroup examples
  16. * @{
  17. * Example of Drupal theming.
  18. *
  19. * The theming_example module attempts to show how module developers can add
  20. * theme functions to their projects so that themes can modify output.
  21. *
  22. * Module developers should to strive to avoid hard-wiring any HTML into the
  23. * output of their code, this should all be done in theme functions.
  24. *
  25. * Starting with the first example, function 'theming_example_page()':
  26. * the output is put into an array $content which is then fed to a theming
  27. * function 'theme_theming_example_page()' which loops over the content,
  28. * wrapping it in html in the process.
  29. *
  30. * In order to get function 'theme_theming_example_page()' recognized it needs
  31. * to be registered with the module theme register function of the
  32. * type 'hook_theme'.
  33. *
  34. * function 'theming_example_theme()' does this for this module.
  35. * for details of what can be done in this hook see the link to api.drupal.org
  36. *
  37. * The functions 'theming_example_list_page()' and theming_example_order_form()
  38. * work in the same way.
  39. *
  40. * In 'theme_theming_example_list_page()' the content is themed as an
  41. * ordered list and given a class attribute 'theming_example_mylist' which
  42. * is defined in theming_example.css
  43. *
  44. * In function 'theme_theming_example_order_form()' the title is loaded into a
  45. * temporary variable '$title', deleted from the $form array and output
  46. * wrapped in html. The rest of the form is wrapped in a div using '#prefix'
  47. * and '#suffix'
  48. *
  49. * The theming functions can be copied to a theme's template.php, renaming
  50. * appropriately, so if you theme is called 'mytheme' you would copy
  51. * function 'theme_theming_example_page()'
  52. * to
  53. * function 'mytheme_theming_example_page()' in template.php and it will be
  54. * used instead of the original.
  55. *
  56. * The fourth example shows the use of a template file
  57. * 'theming_example_text_form.tpl.php'
  58. * This file can be copied to a theme's folder and it will be used instead.
  59. *
  60. * This example also shows what can be done using Drupal's
  61. * template_preprocess_HOOK method. In this case it modifies the output so
  62. * that a themer can output the whole form or gain control over some of its
  63. * parts in the template file.
  64. */
  65. /**
  66. * Implements hook_menu().
  67. *
  68. * The @link menu_example.module Menu Example @endlink provides extensive
  69. * examples for hook_menu().
  70. */
  71. function theming_example_menu() {
  72. $items['examples/theming_example'] = array(
  73. 'title' => 'Theming Example',
  74. 'description' => 'Some theming examples.',
  75. 'page callback' => 'theming_example_page',
  76. 'access callback' => TRUE,
  77. 'access arguments' => array('access content'),
  78. );
  79. $items['examples/theming_example/theming_example_list_page'] = array(
  80. 'title' => 'Theming a list',
  81. 'page callback' => 'theming_example_list_page',
  82. 'access arguments' => array('access content'),
  83. 'weight' => 1,
  84. );
  85. $items['examples/theming_example/theming_example_select_form'] = array(
  86. 'title' => 'Theming a form (select form)',
  87. 'page callback' => 'drupal_get_form',
  88. 'page arguments' => array('theming_example_select_form'),
  89. 'access arguments' => array('access content'),
  90. 'weight' => 2,
  91. );
  92. $items['examples/theming_example/theming_example_text_form'] = array(
  93. 'title' => 'Theming a form (text form)',
  94. 'page callback' => 'drupal_get_form',
  95. 'page arguments' => array('theming_example_text_form'),
  96. 'access arguments' => array('access content'),
  97. 'weight' => 3,
  98. );
  99. return $items;
  100. }
  101. /**
  102. * Implements hook_theme().
  103. *
  104. * Defines the theming capabilities provided by this module.
  105. */
  106. function theming_example_theme() {
  107. return array(
  108. 'theming_example_content_array' => array(
  109. // We use 'render element' when the item to be passed is a self-describing
  110. // render array (it will have #theme_wrappers)
  111. 'render element' => 'element',
  112. ),
  113. 'theming_example_list' => array(
  114. // We use 'variables' when the item to be passed is an array whose
  115. // structure must be described here.
  116. 'variables' => array(
  117. 'title' => NULL,
  118. 'items' => NULL,
  119. ),
  120. ),
  121. 'theming_example_select_form' => array(
  122. 'render element' => 'form',
  123. ),
  124. 'theming_example_text_form' => array(
  125. 'render element' => 'form',
  126. // In this one the rendering will be done by a template file
  127. // (theming-example-text-form.tpl.php) instead of being rendered by a
  128. // function. Note the use of dashes to separate words in place of
  129. // underscores. The template file's extension is also left out so that
  130. // it may be determined automatically depending on the template engine
  131. // the site is using.
  132. 'template' => 'theming-example-text-form',
  133. ),
  134. );
  135. }
  136. /**
  137. * Initial landing page explaining the use of the module.
  138. *
  139. * We create a render array and specify the theme to be used through the use
  140. * of #theme_wrappers. With all output, we aim to leave the content as a
  141. * render array just as long as possible, so that other modules (or the theme)
  142. * can alter it.
  143. *
  144. * @see render_example.module
  145. * @see form_example_elements.inc
  146. */
  147. function theming_example_page() {
  148. $content[] = t('Some examples of pages and forms that are run through theme functions.');
  149. $content[] = l(t('Simple page with a list'), 'examples/theming_example/theming_example_list_page');
  150. $content[] = l(t('Simple form 1'), 'examples/theming_example/theming_example_select_form');
  151. $content[] = l(t('Simple form 2'), 'examples/theming_example/theming_example_text_form');
  152. $content['#theme_wrappers'] = array('theming_example_content_array');
  153. return $content;
  154. }
  155. /**
  156. * The list page callback.
  157. *
  158. * An example page where the output is supplied as an array which is themed
  159. * into a list and styled with css.
  160. *
  161. * In this case we'll use the core-provided theme_item_list as a #theme_wrapper.
  162. * Any theme need only override theme_item_list to change the behavior.
  163. */
  164. function theming_example_list_page() {
  165. $items = array(
  166. t('First item'),
  167. t('Second item'),
  168. t('Third item'),
  169. t('Fourth item'),
  170. );
  171. // First we'll create a render array that simply uses theme_item_list.
  172. $title = t("A list returned to be rendered using theme('item_list')");
  173. $build['render_version'] = array(
  174. // We use #theme here instead of #theme_wrappers because theme_item_list()
  175. // is the classic type of theme function that does not just assume a
  176. // render array, but instead has its own properties (#type, #title, #items).
  177. '#theme' => 'item_list',
  178. // '#type' => 'ul', // The default type is 'ul'
  179. // We can easily make sure that a css or js file is present using #attached.
  180. '#attached' => array('css' => array(drupal_get_path('module', 'theming_example') . '/theming_example.css')),
  181. '#title' => $title,
  182. '#items' => $items,
  183. '#attributes' => array('class' => array('render-version-list')),
  184. );
  185. // Now we'll create a render array which uses our own list formatter,
  186. // theme('theming_example_list').
  187. $title = t("The same list rendered by theme('theming_example_list')");
  188. $build['our_theme_function'] = array(
  189. '#theme' => 'theming_example_list',
  190. '#attached' => array('css' => array(drupal_get_path('module', 'theming_example') . '/theming_example.css')),
  191. '#title' => $title,
  192. '#items' => $items,
  193. );
  194. return $build;
  195. }
  196. /**
  197. * A simple form that displays a select box and submit button.
  198. *
  199. * This form will be be themed by the 'theming_example_select_form' theme
  200. * handler.
  201. */
  202. function theming_example_select_form($form, &$form_state) {
  203. $options = array(
  204. 'newest_first' => t('Newest first'),
  205. 'newest_last' => t('Newest last'),
  206. 'edited_first' => t('Edited first'),
  207. 'edited_last' => t('Edited last'),
  208. 'by_name' => t('By name'),
  209. );
  210. $form['choice'] = array(
  211. '#type' => 'select',
  212. '#options' => $options,
  213. '#title' => t('Choose which ordering you want'),
  214. );
  215. $form['submit'] = array(
  216. '#type' => 'submit',
  217. '#value' => t('Go'),
  218. );
  219. return $form;
  220. }
  221. /**
  222. * Submit handler for the select form.
  223. *
  224. * @param array $form
  225. * Form API form array.
  226. * @param array $form_state
  227. * Form API form state array.
  228. */
  229. function theming_example_select_form_submit($form, &$form_state) {
  230. drupal_set_message(t('You chose %input', array('%input' => $form_state['values']['choice'])));
  231. }
  232. /**
  233. * A simple form that displays a textfield and submit button.
  234. *
  235. * This form will be rendered by theme('form') (theme_form() by default)
  236. * because we do not provide a theme function for it here.
  237. */
  238. function theming_example_text_form($form, &$form_state) {
  239. $form['text'] = array(
  240. '#type' => 'textfield',
  241. '#title' => t('Please input something!'),
  242. '#required' => TRUE,
  243. );
  244. $form['submit'] = array(
  245. '#type' => 'submit',
  246. '#value' => t('Go'),
  247. );
  248. return $form;
  249. }
  250. /**
  251. * Submit handler for the text form.
  252. *
  253. * @param array $form
  254. * Form API form array.
  255. * @param array $form_state
  256. * Form API form state array.
  257. */
  258. function theming_example_text_form_submit($form, &$form_state) {
  259. drupal_set_message(t('You entered %input', array('%input' => $form_state['values']['text'])));
  260. }
  261. /**
  262. * Theme a simple content array.
  263. *
  264. * This theme function uses the newer recommended format where a single
  265. * render array is provided to the theme function.
  266. */
  267. function theme_theming_example_content_array($variables) {
  268. $element = $variables['element'];
  269. $output = '';
  270. foreach (element_children($element) as $count) {
  271. if (!$count) {
  272. // The first paragraph is bolded.
  273. $output .= '<p><strong>' . $element[$count] . '</strong></p>';
  274. }
  275. else {
  276. // Following paragraphs are just output as routine paragraphs.
  277. $output .= '<p>' . $element[$count] . '</p>';
  278. }
  279. }
  280. return $output;
  281. }
  282. /**
  283. * Theming a simple list.
  284. *
  285. * This is just a simple wrapper around theme('item_list') but it's worth
  286. * showing how a custom theme function can be implemented.
  287. *
  288. * @see theme_item_list()
  289. */
  290. function theme_theming_example_list($variables) {
  291. $title = $variables['title'];
  292. $items = $variables['items'];
  293. // Add the title to the list theme and
  294. // state the list type. This defaults to 'ul'.
  295. // Add a css class so that you can modify the list styling.
  296. // We'll just call theme('item_list') to render.
  297. $variables = array(
  298. 'items' => $items,
  299. 'title' => $title,
  300. 'type' => 'ol',
  301. 'attributes' => array('class' => 'theming-example-list'),
  302. );
  303. $output = theme('item_list', $variables);
  304. return $output;
  305. }
  306. /**
  307. * Theming a simple form.
  308. *
  309. * Since our form is named theming_example_select_form(), the default
  310. * #theme function applied to is will be 'theming_example_select_form'
  311. * if it exists. The form could also have specified a different
  312. * #theme.
  313. *
  314. * Here we collect the title, theme it manually and
  315. * empty the form title. We also wrap the form in a div.
  316. */
  317. function theme_theming_example_select_form($variables) {
  318. $form = $variables['form'];
  319. $title = $form['choice']['#title'];
  320. $form['choice']['#title'] = '';
  321. $output = '<strong>' . $title . '</strong>';
  322. $form['choice']['#prefix'] = '<div class="container-inline">';
  323. $form['submit']['#suffix'] = '</div>';
  324. $output .= drupal_render_children($form);
  325. return $output;
  326. }
  327. /**
  328. * Implements template_preprocess().
  329. *
  330. * We prepare variables for use inside the theming-example-text-form.tpl.php
  331. * template file.
  332. *
  333. * In this example, we create a couple new variables, 'text_form' and
  334. * 'text_form_content', that clean up the form output. Drupal will turn the
  335. * array keys in the $variables array into variables for use in the template.
  336. *
  337. * So $variables['text_form'] becomes available as $text_form in the template.
  338. *
  339. * @see theming-example-text-form.tpl.php
  340. */
  341. function template_preprocess_theming_example_text_form(&$variables) {
  342. $variables['text_form_content'] = array();
  343. $text_form_hidden = array();
  344. // Each form element is rendered and saved as a key in $text_form_content, to
  345. // give the themer the power to print each element independently in the
  346. // template file. Hidden form elements have no value in the theme, so they
  347. // are grouped into a single element.
  348. foreach (element_children($variables['form']) as $key) {
  349. $type = $variables['form'][$key]['#type'];
  350. if ($type == 'hidden' || $type == 'token') {
  351. $text_form_hidden[] = drupal_render($variables['form'][$key]);
  352. }
  353. else {
  354. $variables['text_form_content'][$key] = drupal_render($variables['form'][$key]);
  355. }
  356. }
  357. $variables['text_form_content']['hidden'] = implode($text_form_hidden);
  358. // The entire form is then saved in the $text_form variable, to make it easy
  359. // for the themer to print the whole form.
  360. $variables['text_form'] = implode($variables['text_form_content']);
  361. }
  362. /**
  363. * @} End of "defgroup theming_example".
  364. */