theming_example.module

Tracking 7.x-1.x branch
  1. drupal
    1. 6 contributions/examples/theming_example/theming_example.module
    2. 7 contributions/examples/theming_example/theming_example.module
    3. 8 contributions/examples/theming_example/theming_example.module

Explains how a module declares theme functions, preprocess functions, and templates.

The underlying approach is that a module should allow themes to do all rendering, but provide default implementations where appropriate.

Modules are also expected to leave data as render arrays as long as possible, leaving rendering to theme functions and templates.

Functions & methods

NameDescription
template_preprocess_theming_example_text_formImplements template_preprocess() to prepare variables for use inside the theming-example-text-form.tpl.php template file.
theme_theming_example_content_arrayTheme a simple content array.
theme_theming_example_listTheming a simple list.
theme_theming_example_select_formTheming a simple form.
theming_example_list_pageAn example page where the output is supplied as an array which is themed into a list and styled with css.
theming_example_menuImplements hook_menu().
theming_example_pageInitial landing page explaining the use of the module.
theming_example_select_formA simple form that displays a select box and submit button.
theming_example_select_form_submit
theming_example_text_formA simple form that displays a textfield and submit button.
theming_example_text_form_submit
theming_example_themeImplements hook_theme().

File

View source
  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. * An example page where the output is supplied as an array which
  157. * is themed into a list and styled with css.
  158. *
  159. * In this case we'll use the core-provided theme_item_list as a #theme_wrapper.
  160. * Any theme need only override theme_item_list to change the behavior.
  161. */
  162. function theming_example_list_page() {
  163. $items = array(
  164. t('First item'),
  165. t('Second item'),
  166. t('Third item'),
  167. t('Fourth item'),
  168. );
  169. // First we'll create a render array that simply uses theme_item_list.
  170. $title = t("A list returned to be rendered using theme('item_list')");
  171. $build['render_version'] = array(
  172. // We use #theme here instead of #theme_wrappers because theme_item_list()
  173. // is the classic type of theme function that does not just assume a
  174. // render array, but instead has its own properties (#type, #title, #items).
  175. '#theme' => 'item_list',
  176. // '#type' => 'ul', // The default type is 'ul'
  177. // We can easily make sure that a css or js file is present using #attached.
  178. '#attached' => array('css' => array(drupal_get_path('module', 'theming_example') . '/theming_example.css')),
  179. '#title' => $title,
  180. '#items' => $items,
  181. '#attributes' => array('class' => array('render-version-list'))
  182. );
  183. // Now we'll create a render array which uses our own list formatter,
  184. // theme('theming_example_list').
  185. $title = t("The same list rendered by theme('theming_example_list')");
  186. $build['our_theme_function'] = array(
  187. '#theme' => 'theming_example_list',
  188. '#attached' => array('css' => array(drupal_get_path('module', 'theming_example') . '/theming_example.css')),
  189. '#title' => $title,
  190. '#items' => $items,
  191. );
  192. return $build;
  193. }
  194. /**
  195. * A simple form that displays a select box and submit button.
  196. *
  197. * This form will be be themed by the 'theming_example_select_form' theme
  198. * handler.
  199. */
  200. function theming_example_select_form($form, &$form_state) {
  201. $options = array(
  202. 'newest_first' => t('Newest first'),
  203. 'newest_last' => t('Newest last'),
  204. 'edited_first' => t('Edited first'),
  205. 'edited_last' => t('Edited last'),
  206. 'by_name' => t('By name'),
  207. );
  208. $form['choice'] = array(
  209. '#type' => 'select',
  210. '#options' => $options,
  211. '#title' => t('Choose which ordering you want'),
  212. );
  213. $form['submit'] = array(
  214. '#type' => 'submit',
  215. '#value' => t('Go'),
  216. );
  217. return $form;
  218. }
  219. function theming_example_select_form_submit($form, &$form_state) {
  220. drupal_set_message(t('You chose %input', array('%input' => $form_state['values']['choice'])));
  221. }
  222. /**
  223. * A simple form that displays a textfield and submit button.
  224. *
  225. * This form will be rendered by theme('form') (theme_form() by default)
  226. * because we do not provide a theme function for it here.
  227. */
  228. function theming_example_text_form($form, &$form_state) {
  229. $form['text'] = array(
  230. '#type' => 'textfield',
  231. '#title' => t('Please input something!'),
  232. '#required' => TRUE,
  233. );
  234. $form['submit'] = array(
  235. '#type' => 'submit',
  236. '#value' => t('Go'),
  237. );
  238. return $form;
  239. }
  240. function theming_example_text_form_submit($form, &$form_state) {
  241. drupal_set_message(t('You entered %input', array('%input' => $form_state['values']['text'])));
  242. }
  243. /**
  244. * Theme a simple content array.
  245. *
  246. * This theme function uses the newer recommended format where a single
  247. * render array is provided to the theme function.
  248. */
  249. function theme_theming_example_content_array($variables) {
  250. $element = $variables['element'];
  251. $output = '';
  252. foreach (element_children($element) AS $count) {
  253. if (! $count) {
  254. // The first paragraph is bolded.
  255. $output .= '<p><strong>' . $element[$count] . '</strong></p>';
  256. }
  257. else {
  258. // Following paragraphs are just output as routine paragraphs.
  259. $output .= '<p>' . $element[$count] . '</p>';
  260. }
  261. }
  262. return $output;
  263. }
  264. /**
  265. * Theming a simple list.
  266. *
  267. * This is just a simple wrapper around theme('item_list') but it's worth
  268. * showing how a custom theme function can be implemented.
  269. *
  270. * @see theme_item_list()
  271. */
  272. function theme_theming_example_list($variables) {
  273. $title = $variables['title'];
  274. $items = $variables['items'];
  275. // Add the title to the list theme and
  276. // state the list type. This defaults to 'ul'.
  277. // Add a css class so that you can modify the list styling.
  278. // We'll just call theme('item_list') to render.
  279. $variables = array(
  280. 'items' => $items,
  281. 'title' => $title,
  282. 'type' => 'ol',
  283. 'attributes' => array('class' => 'theming-example-list'),
  284. );
  285. $output = theme('item_list', $variables);
  286. return $output;
  287. }
  288. /**
  289. * Theming a simple form.
  290. *
  291. * Since our form is named theming_example_select_form(), the default
  292. * #theme function applied to is will be 'theming_example_select_form'
  293. * if it exists. The form could also have specified a different
  294. * #theme.
  295. *
  296. * Here we collect the title, theme it manually and
  297. * empty the form title. We also wrap the form in a div.
  298. */
  299. function theme_theming_example_select_form($variables) {
  300. $form = $variables['form'];
  301. $title = $form['choice']['#title'];
  302. $form['choice']['#title'] = '';
  303. $output = '<strong>' . $title . '</strong>';
  304. $form['choice']['#prefix'] = '<div class="container-inline">';
  305. $form['submit']['#suffix'] = '</div>';
  306. $output .= drupal_render_children($form);
  307. return $output;
  308. }
  309. /**
  310. * Implements template_preprocess() to prepare variables for use inside the
  311. * theming-example-text-form.tpl.php template file.
  312. *
  313. * In this example, we create a couple new variables, 'text_form' and
  314. * 'text_form_content', that clean up the form output. Drupal will turn the
  315. * array keys in the $variables array into variables for use in the template.
  316. *
  317. * So $variables['text_form'] becomes available as $text_form in the template.
  318. *
  319. * @see theming-example-text-form.tpl.php
  320. */
  321. function template_preprocess_theming_example_text_form(&$variables) {
  322. $variables['text_form_content'] = array();
  323. $text_form_hidden = array();
  324. // Each form element is rendered and saved as a key in $text_form_content, to
  325. // give the themer the power to print each element independently in the
  326. // template file. Hidden form elements have no value in the theme, so they
  327. // are grouped into a single element.
  328. foreach (element_children($variables['form']) as $key) {
  329. $type = $variables['form'][$key]['#type'];
  330. if ($type == 'hidden' || $type == 'token') {
  331. $text_form_hidden[] = drupal_render($variables['form'][$key]);
  332. }
  333. else {
  334. $variables['text_form_content'][$key] = drupal_render($variables['form'][$key]);
  335. }
  336. }
  337. $variables['text_form_content']['hidden'] = implode($text_form_hidden);
  338. // The entire form is then saved in the $text_form variable, to make it easy
  339. // for the themer to print the whole form.
  340. $variables['text_form'] = implode($variables['text_form_content']);
  341. }
  342. /**
  343. * @} End of "defgroup theming_example".
  344. */