summaryrefslogtreecommitdiffstats
path: root/theming_example/theming_example.module
blob: b888033d11e1d6534a4f48de5b6f1216dce19da6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
<?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".
 */