| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385 | <?php/** * @file * 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. *//** * @defgroup theming_example Example: Theming * @ingroup examples * @{ * Example of Drupal theming. * * The theming_example module attempts to show how module developers can add * theme functions to their projects so that themes can modify output. * * Module developers should to strive to avoid hard-wiring any HTML into the * output of their code, this should all be done in theme functions. * * Starting with the first example, function 'theming_example_page()': * the output is put into an array $content which is then fed to a theming * function 'theme_theming_example_content_array()' which loops over the * content, wrapping it in html in the process. * * In order to get function 'theme_theming_example_content_array()' recognized * it needs to be registered with the module theme register function of the type * 'hook_theme'. * * function 'theming_example_theme()' does this for this module. * for details of what can be done in this hook see the link to api.drupal.org * * The functions 'theming_example_list_page()' and theming_example_order_form() * work in the same way. * * In 'theme_theming_example_list_page()' the content is themed as an * ordered list and given a class attribute 'theming_example_mylist' which * is defined in theming_example.css * * In function 'theme_theming_example_order_form()' the title is loaded into a * temporary variable '$title', deleted from the $form array and output * wrapped in html. The rest of the form is wrapped in a div using '#prefix' * and '#suffix' * * The theming functions can be copied to a theme's template.php, renaming * appropriately, so if your theme is called 'mytheme' you would copy function * 'theme_theming_example_content_array()' to function * 'mytheme_theming_example_page()' in template.php and it will be used instead * of the original. * * The fourth example shows the use of a template file * 'theming_example_text_form.tpl.php' * This file can be copied to a theme's folder and it will be used instead. * * This example also shows what can be done using Drupal's * template_preprocess_HOOK method. In this case it modifies the output so * that a themer can output the whole form or gain control over some of its * parts in the template file. *//** * Implements hook_menu(). * * The @link menu_example.module Menu Example @endlink provides extensive * examples for hook_menu(). */function theming_example_menu() {  $items['examples/theming_example'] = array(    'title' => 'Theming Example',    'description' => 'Some theming examples.',    'page callback' => 'theming_example_page',    'access callback' => TRUE,    'access arguments' => array('access content'),  );  $items['examples/theming_example/theming_example_list_page'] = array(    'title' => 'Theming a list',    'page callback' => 'theming_example_list_page',    'access arguments' => array('access content'),    'weight' => 1,  );  $items['examples/theming_example/theming_example_select_form'] = array(    'title' => 'Theming a form (select form)',    'page callback'    => 'drupal_get_form',    'page arguments'   => array('theming_example_select_form'),    'access arguments' => array('access content'),    'weight' => 2,  );  $items['examples/theming_example/theming_example_text_form'] = array(    'title' => 'Theming a form (text form)',    'page callback'    => 'drupal_get_form',    'page arguments'   => array('theming_example_text_form'),    'access arguments' => array('access content'),    'weight' => 3,  );  return $items;}/** * Implements hook_theme(). * * Defines the theming capabilities provided by this module. */function theming_example_theme($existing, $type, $theme, $path) {  return array(    'theming_example_content_array' => array(      // We use 'render element' when the item to be passed is a self-describing      // render array (it will have #theme_wrappers)      'render element' => 'element',    ),    'theming_example_list' => array(      // We use 'variables' when the item to be passed is an array whose      // structure must be described here.      'variables' => array(        'title' => NULL,        'items' => NULL,      ),    ),    'theming_example_select_form'  => array(      'render element' => 'form',    ),    'theming_example_text_form'  => array(      'render element' => 'form',      // In this one the rendering will be done by a template file      // (theming-example-text-form.tpl.php) instead of being rendered by a      // function. Note the use of dashes to separate words in place of      // underscores. The template file's extension is also left out so that      // it may be determined automatically depending on the template engine      // the site is using.      'template' => 'theming-example-text-form',    ),  );}/** * Initial landing page explaining the use of the module. * * We create a render array and specify the theme to be used through the use * of #theme_wrappers. With all output, we aim to leave the content as a * render array just as long as possible, so that other modules (or the theme) * can alter it. * * @see render_example.module * @see form_example_elements.inc */function theming_example_page() {  $content[]['#markup']  = t('Some examples of pages and forms that are run through theme functions.');  $content[]['#markup']  = l(t('Simple page with a list'), 'examples/theming_example/theming_example_list_page');  $content[]['#markup']  = l(t('Simple form 1'), 'examples/theming_example/theming_example_select_form');  $content[]['#markup']  = l(t('Simple form 2'), 'examples/theming_example/theming_example_text_form');  $content['#theme_wrappers'] = array('theming_example_content_array');  return $content;}/** * The list page callback. * * An example page where the output is supplied as an array which is themed * into a list and styled with css. * * In this case we'll use the core-provided theme_item_list as a #theme_wrapper. * Any theme need only override theme_item_list to change the behavior. */function theming_example_list_page() {  $items = array(    t('First item'),    t('Second item'),    t('Third item'),    t('Fourth item'),  );  // First we'll create a render array that simply uses theme_item_list.  $title = t("A list returned to be rendered using theme('item_list')");  $build['render_version'] = array(    // We use #theme here instead of #theme_wrappers because theme_item_list()    // is the classic type of theme function that does not just assume a    // render array, but instead has its own properties (#type, #title, #items).    '#theme' => 'item_list',    // '#type' => 'ul',  // The default type is 'ul'    // We can easily make sure that a css or js file is present using #attached.    '#attached' => array('css' => array(drupal_get_path('module', 'theming_example') . '/theming_example.css')),    '#title' => $title,    '#items' => $items,    '#attributes' => array('class' => array('render-version-list')),  );  // Now we'll create a render array which uses our own list formatter,  // theme('theming_example_list').  $title = t("The same list rendered by theme('theming_example_list')");  $build['our_theme_function'] = array(    '#theme' => 'theming_example_list',    '#attached' => array('css' => array(drupal_get_path('module', 'theming_example') . '/theming_example.css')),    '#title' => $title,    '#items' => $items,  );  return $build;}/** * A simple form that displays a select box and submit button. * * This form will be be themed by the 'theming_example_select_form' theme * handler. */function theming_example_select_form($form, &$form_state) {  $options = array(    'newest_first' => t('Newest first'),    'newest_last' => t('Newest last'),    'edited_first' => t('Edited first'),    'edited_last' => t('Edited last'),    'by_name' => t('By name'),  );  $form['choice'] = array(    '#type' => 'select',    '#options' => $options,    '#title' => t('Choose which ordering you want'),  );  $form['submit'] = array(    '#type' => 'submit',    '#value' => t('Go'),  );  return $form;}/** * Submit handler for the select form. * * @param array $form *   Form API form array. * @param array $form_state *   Form API form state array. */function theming_example_select_form_submit($form, &$form_state) {  drupal_set_message(t('You chose %input', array('%input' => $form_state['values']['choice'])));}/** * A simple form that displays a textfield and submit button. * * This form will be rendered by theme('form') (theme_form() by default) * because we do not provide a theme function for it here. */function theming_example_text_form($form, &$form_state) {  $form['text'] = array(    '#type' => 'textfield',    '#title' => t('Please input something!'),    '#required' => TRUE,  );  $form['submit'] = array(    '#type' => 'submit',    '#value' => t('Go'),  );  return $form;}/** * Submit handler for the text form. * * @param array $form *   Form API form array. * @param array $form_state *   Form API form state array. */function theming_example_text_form_submit($form, &$form_state) {  drupal_set_message(t('You entered %input', array('%input' => $form_state['values']['text'])));}/** * Theme a simple content array. * * This theme function uses the newer recommended format where a single * render array is provided to the theme function. */function theme_theming_example_content_array($variables) {  $element = $variables['element'];  $output = '';  foreach (element_children($element) as $count) {    if (!$count) {      // The first paragraph is bolded.      $output .= '<p><strong>' . $element[$count]['#children'] . '</strong></p>';    }    else {      // Following paragraphs are just output as routine paragraphs.      $output .= '<p>' . $element[$count]['#children'] . '</p>';    }  }  return $output;}/** * Theming a simple list. * * This is just a simple wrapper around theme('item_list') but it's worth * showing how a custom theme function can be implemented. * * @see theme_item_list() */function theme_theming_example_list($variables) {  $title = $variables['title'];  $items = $variables['items'];  // Add the title to the list theme and  // state the list type. This defaults to 'ul'.  // Add a css class so that you can modify the list styling.  // We'll just call theme('item_list') to render.  $variables = array(    'items' => $items,    'title' => $title,    'type' => 'ol',    'attributes' => array('class' => 'theming-example-list'),  );  $output = theme('item_list', $variables);  return $output;}/** * Theming a simple form. * * Since our form is named theming_example_select_form(), the default * #theme function applied to is will be 'theming_example_select_form' * if it exists. The form could also have specified a different * #theme. * * Here we collect the title, theme it manually and * empty the form title. We also wrap the form in a div. */function theme_theming_example_select_form($variables) {  $form = $variables['form'];  $title = $form['choice']['#title'];  $form['choice']['#title'] = '';  $output = '<strong>' . $title . '</strong>';  $form['choice']['#prefix'] = '<div class="container-inline">';  $form['submit']['#suffix'] = '</div>';  $output .= drupal_render_children($form);  return $output;}/** * Implements template_preprocess(). * * We prepare variables for use inside the theming-example-text-form.tpl.php * template file. * * In this example, we create a couple new variables, 'text_form' and * 'text_form_content', that clean up the form output.  Drupal will turn the * array keys in the $variables array into variables for use in the template. * * So $variables['text_form'] becomes available as $text_form in the template. * * @see theming-example-text-form.tpl.php */function template_preprocess_theming_example_text_form(&$variables) {  $variables['text_form_content'] = array();  $text_form_hidden = array();  // Each form element is rendered and saved as a key in $text_form_content, to  // give the themer the power to print each element independently in the  // template file.  Hidden form elements have no value in the theme, so they  // are grouped into a single element.  foreach (element_children($variables['form']) as $key) {    $type = $variables['form'][$key]['#type'];    if ($type == 'hidden' || $type == 'token') {      $text_form_hidden[] = drupal_render($variables['form'][$key]);    }    else {      $variables['text_form_content'][$key] = drupal_render($variables['form'][$key]);    }  }  $variables['text_form_content']['hidden'] = implode($text_form_hidden);  // The entire form is then saved in the $text_form variable, to make it easy  // for the themer to print the whole form.  $variables['text_form'] = implode($variables['text_form_content']);}/** * @} End of "defgroup theming_example". */
 |