<?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_page()' which loops over the content,
 * wrapping it in html in the process.
 *
 * In order to get function 'theme_theming_example_page()' 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 you theme is called 'mytheme' you would copy
 * function 'theme_theming_example_page()'
 * 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() {
  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[] = t('Some examples of pages and forms that are run through theme functions.');
  $content[] = l(t('Simple page with a list'), 'examples/theming_example/theming_example_list_page');
  $content[] = l(t('Simple form 1'), 'examples/theming_example/theming_example_select_form');
  $content[] = 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] . '</strong></p>';
    }
    else {
      // Following paragraphs are just output as routine paragraphs.
      $output .= '<p>' . $element[$count] . '</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".
 */
