taxonomy_display.module 21.4 KB
Newer Older
Cody Craven's avatar
Cody Craven committed
1
2
3
4
5
6
7
8
<?php
// $Id$

/**
 * @file
 * Hooks for the taxonomy display module.
 */

9
10
11
12
13
14
15
16
17
/**
 * Return just the term display sub-form.
 *
 * @return renderable array
 */
function taxonomy_display_ajax_associated_display_callback($form, $form_state) {
  return $form['additional_settings']['taxonomy_display']['associated_display_form'];
}

Cody Craven's avatar
Cody Craven committed
18
19
20
21
22
23
24
25
26
/**
 * Return just the term display sub-form.
 *
 * @return renderable array
 */
function taxonomy_display_ajax_term_display_callback($form, $form_state) {
  return $form['additional_settings']['taxonomy_display']['term_display_form'];
}

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/**
 * Helper function; delete taxonomy display data.
 *
 * @param string $machine_name
 *   The machine name of the vocabulary's taxonomy display data to remove.
 * @param string|NULL|FALSE $watchdog_message
 *   Provide a watchdog message as a string. If null then a generic default
 *   message will be used. If false then no watchdog message will be recorded.
 * @param array $watchdog_variables
 *   Variables for substitution in the watchdog message.
 * @param int $watchdog_severity
 *   One of the defined watchdog constant severities: WATCHDOG_EMERGENCY,
 *   WATCHDOG_ALERT, WATCHDOG_CRITICAL, WATCHDOG_ERROR, WATCHDOG_WARNING,
 *   WATCHDOG_NOTICE, WATCHDOG_INFO, WATCHDOG_DEBUG. Defaults to
 *   WATCHDOG_NOTICE.
 *
 * @return void
44
45
 *
 * @todo test this works
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
 */
function taxonomy_display_delete_taxonomy_dislpay($machine_name, $watchdog_message = NULL, $watchdog_variables = array(), $watchdog_severity = WATCHDOG_NOTICE) {
  // Delete our display record for the term being removed.
  $count = (bool) db_delete('taxonomy_display')
    ->condition('machine_name', $machine_name)
    ->execute();

  // If a record was deleted then log it in watchdog.
  if ($count && $watchdog_message !== FALSE) {
    if (empty($watchdog_message)) {
      $watchdog_message = 'Taxonomy display settings deleted for %name.';
      $watchdog_variables = array('%name' => $machine_name);
    }
    watchdog('taxonomy_display', $watchdog_message, $watchdog_variables, $watchdog_severity);
  }
}

/**
 * Helper function; retrieve taxonomy display settings from the database.
 *
 * @param string $machine_name
 *   The machine name of the vocabulary's taxonomy display data to fetch.
 *
 * @return array|FALSE
 *   Return associated array if a record is found, else false.
 */
function taxonomy_display_fetch_taxonomy_display($machine_name) {
  return db_select('taxonomy_display', 'td')
    ->fields('td')
    ->condition('machine_name', $machine_name)
    ->execute()
    ->fetchAssoc();
}

Cody Craven's avatar
Cody Craven committed
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
/**
 * Implements hook_form_FORM_ID_alter().
 */
function taxonomy_display_form_field_ui_display_overview_form_alter(&$form, &$form_state) {
  // Only proceed if we are on taxonomy_term entity type and the user has admin
  // taxonomy display.
  if ($form['#entity_type'] != 'taxonomy_term' || !user_access('administer taxonomy display')) {
    return;
  }

  // Make things easy on users getting started with the module.
  // We require the 'full' #view_mode to configure the taxonomy term page.
  if ($form['#view_mode'] == 'default') {
    $field = array(
      '#title' => 'Term page display',
      '#type' => 'fieldset',
    );
    // TODO: There's got to be a better way to find out if 'full' is enabled,
    // need to look.
    foreach ($form['additional_settings']['modes']['view_modes_custom']['#default_value'] as $value) {
      if ($value == 'full') {
        $field['#description'] = 'To alter the term page display you need to go to the <em>Taxonomy term page</em> view mode.';
        break;
      }
    }
    if (!isset($field['#description'])) {
      $field['#description'] = 'Enable the <em>Taxonomy term page</em> view mode under the <em>Custom display settings</em> tab to alter the term page display.';
    }
    $form['additional_settings']['taxonomy_display'] = $field;
  }

  // Only proceed if we are on the full display mode.
  if ($form['#view_mode'] != 'full') {
    return;
  }

116
  $stored_settings = taxonomy_display_fetch_taxonomy_display($form['#bundle']);
Cody Craven's avatar
Cody Craven committed
117
118
119
120
121
122
123
124

  $form['additional_settings']['taxonomy_display'] = array(
    '#description' => 'Configure how the taxonomy term display page should be presented when viewed for this vocabulary.',
    '#title' => 'Term page display',
    '#type' => 'fieldset',
  );
  $fieldset =& $form['additional_settings']['taxonomy_display'];
  if (isset($form_state['values']['additional_settings']['taxonomy_display'])) {
125
    $values =& $form_state['values']['additional_settings']['taxonomy_display'];
Cody Craven's avatar
Cody Craven committed
126
127
128
129
  }

  // Populate $options with plugins that are available.
  $options = taxonomy_display_plugins('term');
130
131
132
133

  // TODO: Rewrite the term and associated fieldsets to use a helper function.

  // Term display fieldset
Cody Craven's avatar
Cody Craven committed
134
135
  // TODO: Rewrite supporting missing plugins.
  // Discover which option should be selected from term display plugins.
136
137
138
  if (isset($values) && isset($values['term_display_select']) &&
      array_key_exists($values['term_display_select'], $options)) {
    $selected = $values['term_display_select'];
Cody Craven's avatar
Cody Craven committed
139
140
141
142
143
144
145
146
147
148
149
  }
  elseif (isset($stored_settings['term_display_plugin']) &&
      array_key_exists($stored_settings['term_display_plugin'], $options)) {
    $selected = $stored_settings['term_display_plugin'];
  }
  else {
    $selected = 'TaxonomyDisplayTermDisplayHandlerCore';
  }
  $fieldset['term_display_select'] = array(
    '#ajax' => array(
      'callback' => 'taxonomy_display_ajax_term_display_callback',
150
      'wrapper' => 'replace-term-display-form',
Cody Craven's avatar
Cody Craven committed
151
152
153
154
155
156
157
158
    ),
    '#default_value' => $selected,
    '#description' => t('Select which plugin you would like to display the term\'s content.'),
    '#options' => $options,
    '#title' => t('Term display'),
    '#type' => 'select',
  );

159
160
  if (isset($form_state['taxonomy_display']['term_display_handler'])) {
    $last_handler = $form_state['taxonomy_display']['term_display_handler'];
Cody Craven's avatar
Cody Craven committed
161
  }
162
  $form_state['taxonomy_display']['term_display_handler'] = $selected;
Cody Craven's avatar
Cody Craven committed
163
164

  $fieldset['term_display_form'] = array(
165
    '#prefix' => '<div id="replace-term-display-form">',
Cody Craven's avatar
Cody Craven committed
166
167
168
169
    '#suffix' => '</div>',
    '#title' => t('!label term display options', array('!label' => $options[$selected])),
    '#type' => 'fieldset',
  );
170
171
172
173

  // Get the fieldset from the selected handler.
  $term_display = new $selected;
  // Set $options as null
174
  $term_display_options = NULL;
175
  if ($stored_settings) {
176
    $term_display_options = unserialize($stored_settings['term_display_options']);
Cody Craven's avatar
Cody Craven committed
177
  }
178
179
180
181
  // If the handler wasn't the one used on the last form build then reset the
  // $form_state values for it.
  if (!isset($last_handler) || $last_handler != $selected) {
    $values['term_display_form'] = array();
Cody Craven's avatar
Cody Craven committed
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
  $term_display->formFieldset($fieldset['term_display_form'], $values['term_display_form'], $term_display_options);

  // Populate $options with plugins that are available.
  $options = taxonomy_display_plugins('associated');

  // Associated content fieldset
  // TODO: Rewrite supporting missing plugins.
  // Discover which option should be selected from term display plugins.
  if (isset($values) && isset($values['associated_display_select']) &&
      array_key_exists($values['associated_display_select'], $options)) {
    $selected = $values['associated_display_select'];
  }
  elseif (isset($stored_settings['associated_display_plugin']) &&
      array_key_exists($stored_settings['associated_display_plugin'], $options)) {
    $selected = $stored_settings['associated_display_plugin'];
  }
  else {
    $selected = 'TaxonomyDisplayAssociatedDisplayHandlerCore';
  }
  $fieldset['associated_display_select'] = array(
    '#ajax' => array(
      'callback' => 'taxonomy_display_ajax_associated_display_callback',
      'wrapper' => 'replace-associated-display-form',
    ),
    '#default_value' => $selected,
    '#description' => t('Select which plugin you would like to display the term\'s associated content.'),
    '#options' => $options,
    '#title' => t('Associated content display'),
    '#type' => 'select',
  );

  if (isset($form_state['taxonomy_display']['associated_display_handler'])) {
    $last_handler = $form_state['taxonomy_display']['associated_display_handler'];
  }
  $form_state['taxonomy_display']['associated_display_handler'] = $selected;

  $fieldset['associated_display_form'] = array(
    '#prefix' => '<div id="replace-associated-display-form">',
    '#suffix' => '</div>',
    '#title' => t('!label associated content display options', array('!label' => $options[$selected])),
    '#type' => 'fieldset',
  );

  // Get the fieldset from the selected handler.
  $associated_display = new $selected;
  // Set $options as null
  $associated_display_options = NULL;
  if ($stored_settings) {
    $associated_display_options = unserialize($stored_settings['associated_display_options']);
  }
  // If the handler wasn't the one used on the last form build then reset the
  // $form_state values for it.
  if (!isset($last_handler) || $last_handler != $selected) {
    $values['associated_display_form'] = array();
  }
  $associated_display->formFieldset($fieldset['associated_display_form'], $values['associated_display_form'], $associated_display_options);
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255

  // Add our #validate and #submit callback which will call plugins' methods.
  $form['#validate'][] = 'taxonomy_display_form_field_ui_display_overview_validate';
  $form['#submit'][] = 'taxonomy_display_form_field_ui_display_overview_submit';
}

/**
 * Form submit callback; save Taxonomy Display settings for term pages.
 */
function taxonomy_display_form_field_ui_display_overview_submit($form, &$form_state) {
  $values =& $form_state['values']['additional_settings']['taxonomy_display'];
  $td_form =& $form['additional_settings']['taxonomy_display'];

  // Perform submit functions for our term display handler.
  $term_display = new $values['term_display_select'];
  $term_display_options = $term_display->formSubmit($td_form['term_display_form'], $values['term_display_form']);

256
257
258
  // Perform submit functions for our associated content handler.
  $associated_display = new $values['associated_display_select'];
  $associated_display_options = $associated_display->formSubmit($td_form['associated_display_form'], $values['associated_display_form']);
259
260
261
262
263

  // Save data
  taxonomy_display_save_taxonomy_display($form['#bundle'], array(
    'term_display_plugin' => $values['term_display_select'],
    'term_display_options' => $term_display_options,
264
265
    'associated_display_plugin' => $values['associated_display_select'],
    'associated_display_options' => $associated_display_options,
266
267
268
269
270
271
272
273
274
275
276
277
278
279
  ));
}

/**
 * Form validate callback; validate Taxonomy Display settings for term pages.
 */
function taxonomy_display_form_field_ui_display_overview_validate($form, &$form_state) {
  $values =& $form_state['values']['additional_settings']['taxonomy_display'];
  $td_form =& $form['additional_settings']['taxonomy_display'];

  // Perform validation functions for our term display handler.
  $term_display = new $values['term_display_select'];
  $term_display->formValidate($td_form['term_display_form'], $values['term_display_form']);

280
281
282
  // Perform validation functions for our associated content display handler.
  $associated_display = new $values['associated_display_select'];
  $associated_display->formValidate($td_form['associated_display_form'], $values['associated_display_form']);
Cody Craven's avatar
Cody Craven committed
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
}

/**
 * Implements of hook_menu_alter().
 */
function taxonomy_display_menu_alter(&$items) {
  $items['taxonomy/term/%taxonomy_term']['page callback'] = 'taxonomy_display_taxonomy_term_page';
  $items['taxonomy/term/%taxonomy_term']['title callback'] = 'taxonomy_display_taxonomy_term_title';
  $items['taxonomy/term/%taxonomy_term']['file'] = 'taxonomy_display.module';
  $items['taxonomy/term/%taxonomy_term']['module'] = 'taxonomy_display';
}

/**
 * Implements hook_permission().
 */
function taxonomy_display_permission() {
  $permissions = array(
    'administer taxonomy display' => array(
      'title' => t('Administer taxonomy display'),
      'description' => t('Change the display settings for taxonomy term pages in each vocabulary.'),
    ),
  );
  return $permissions;
}

/**
 * Retrieve an array of Taxonomy Display plugins.
 * 
 * @param null|string $type
 *   Only retrieve plugins of a specific type, expected values 'term' and 
 *   'associated'. By default, NULL, this will return an array with both.
 * 
 * @return array|void
 *   If an expected value is provided for $type, or no value is provided, an
 *   array will be returned. If an unexpected value is provided nothing will be
 *   returned.
 */
function taxonomy_display_plugins($type = NULL) {
  // TODO: Add caching, likely not a big issue as this is only called in admin
  // areas, but still.

  $plugins = module_invoke_all('taxonomy_display_plugins');

  // Expose our retrieved plugins to altering.
  drupal_alter('taxonomy_display_plugins', $plugins);

  if (is_null($type)) {
    return $plugins;
  }

  if (array_key_exists($type, $plugins)) {
    return $plugins[$type];
  }
}

/**
 * Implements hook_taxonomy_display_plugins().
 *
 * Taxonomy Display invokes this hook when looking for plugins for displaying
 * taxonomy term and taxonomy term's associated content.
 */
function taxonomy_display_taxonomy_display_plugins() {
  // To add custom plugins in your own hook implementation return an array with
  // the format below:
  return array(
    // In the two arrays 'associated' and 'term', provide the implementing class
    // name of your handler as the keys and the text to be displayed to the user
    // for display as the value.
351
352
353
    // 
    // Note: All of the class's files are in our module's .info files array so
    //   that auto loading works.
Cody Craven's avatar
Cody Craven committed
354
355
    'associated' => array(
      // TODO: Add core, hidden, views
356
357
      'TaxonomyDisplayAssociatedDisplayHandlerCore' => t('Core'),
      'TaxonomyDisplayAssociatedDisplayHandlerHidden' => t('Hidden'),
Cody Craven's avatar
Cody Craven committed
358
359
360
361
362
363
364
365
    ),
    'term' => array(
      'TaxonomyDisplayTermDisplayHandlerCore' => t('Core'),
      'TaxonomyDisplayTermDisplayHandlerHidden' => t('Hidden'),
    ),
  );
}

366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
/**
 * Helper function; save a taxonomy display record in the database.
 *
 * @param string $machine_name
 *   The machine name of the vocabulary's taxonomy display data to save.
 * @param array $save_data
 *
 * @param string|NULL|FALSE $watchdog_message
 *   Provide a watchdog message as a string. If null then a generic default
 *   message will be used. If false then no watchdog message will be recorded.
 * @param array $watchdog_variables
 *   Variables for substitution in the watchdog message.
 * @param int $watchdog_severity
 *   One of the defined watchdog constant severities: WATCHDOG_EMERGENCY,
 *   WATCHDOG_ALERT, WATCHDOG_CRITICAL, WATCHDOG_ERROR, WATCHDOG_WARNING,
 *   WATCHDOG_NOTICE, WATCHDOG_INFO, WATCHDOG_DEBUG. Defaults to
 *   WATCHDOG_NOTICE.
 *
 * @return void
 */
function taxonomy_display_save_taxonomy_display($machine_name, $save_data = array(), $watchdog_message = NULL, $watchdog_variables = array(), $watchdog_severity = WATCHDOG_NOTICE) {
  // Prepare the fields to be used for the insert or update query.
  $query_fields = array();
  foreach($save_data as $k => $v) {
    switch ($k) {
      case 'machine_name':
      case 'term_display_plugin':
      case 'associated_display_plugin':
        $query_fields[$k] = $v;
        break;
      case 'term_display_options':
      case 'associated_display_options':
        $query_fields[$k] = serialize($v);
        break;
      default:
        break;
    }
  }
  // Allow other modules to alter our fields before they are inserted/updated.
  drupal_alter('taxonomy_display_save_fields', $query_fields, $save_data);

  // Retrieve the machine name, tells us whether to insert or update.
  $update = taxonomy_display_fetch_taxonomy_display($machine_name);

  // Perform our save
  try {
    // If update
    if ($update) {
      // Do not proceed if there are no fields to update.
      if (empty($query_fields)) {
        return;
      }

      // Query
      $count = (bool) db_update('taxonomy_display')
        ->fields($query_fields)
        ->condition('machine_name', $machine_name)
        ->execute();

      if ($count && $watchdog_message !== FALSE) {
        if (empty($watchdog_message)) {
          $watchdog_message = 'Taxonomy display vocabulary data updated for %machine_name.';
          $watchdog_variables = array('%machine_name' => $machine_name);
        }
        watchdog('taxonomy_display', $watchdog_message, $watchdog_variables, $watchdog_severity);
      }
    }
    // Else insert
    else {
      // If the record is being inserted we do not want to force the user to
      // supply machine_name twice for no reason, if they know it is an insert.
      if (!isset($query_fields['machine_name'])) {
        $query_fields['machine_name'] = $machine_name;
      }

      // Query
      $value = db_insert('taxonomy_display')
        ->fields($query_fields)
        ->execute();

      if ($watchdog_message !== FALSE) {
        if (empty($watchdog_message)) {
          $watchdog_message = 'Taxonomy display vocabulary data created for %machine_name.';
          $watchdog_variables = array('%machine_name' => $machine_name);
        }
        watchdog('taxonomy_display', $watchdog_message, $watchdog_variables, $watchdog_severity);
      }
    }
  }
  catch(Exception $e) {
    drupal_set_message(t('Taxonomy display data save failed. Message = %message, query= %query',
      array('%message' => $e->getMessage(), '%query' => $e->query_string)), 'error');
  }
}

Cody Craven's avatar
Cody Craven committed
461
462
463
464
465
466
467
468
469
470
/**
 * Page callback; displays all nodes associated with a term.
 *
 * @param $term
 *   A term object.
 *
 * @return
 *   The page content.
 */
function taxonomy_display_taxonomy_term_page($term) {
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
  // Build breadcrumb like core does, we could make this alterable in the future
  // especially if something like custom breadcrumbs tells us how they would
  // like to alter this.
  // @see taxonomy_term_page()
  $current = (object) array(
    'tid' => $term->tid,
  );
  $breadcrumb = array();
  while ($parents = taxonomy_get_parents($current->tid)) {
    $current = array_shift($parents);
    $breadcrumb[] = l($current->name, 'taxonomy/term/' . $current->tid);
  }
  $breadcrumb[] = l(t('Home'), NULL);
  $breadcrumb = array_reverse($breadcrumb);
  drupal_set_breadcrumb($breadcrumb);
  drupal_add_feed('taxonomy/term/' . $term->tid . '/feed', 'RSS - ' . $term->name);

  // Build our content
  $build = array();

  $display_settings = taxonomy_display_fetch_taxonomy_display($term->vocabulary_machine_name);

493
  // TODO: Move term display and associated display in to a helper function.
494
495
496
497
498
499
500
501
502
  // Term display
  // Set the default display handler if one is not set or the plugin is missing.
  if (!$display_settings || !class_exists($display_settings['term_display_plugin'], TRUE)) {
    $display_settings = array(
      'term_display_plugin' => 'TaxonomyDisplayTermDisplayHandlerCore',
    );
  }
  // Set the term display options.
  if (!$display_settings || !isset($display_settings['term_display_options'])) {
503
    $display_settings['term_display_options'] = NULL;
504
505
506
507
508
509
510
  }
  else {
    $display_settings['term_display_options'] = unserialize($display_settings['term_display_options']);
  }
  $term_display = new $display_settings['term_display_plugin'];
  $build['term_heading'] = $term_display->displayTerm($term, $display_settings['term_display_options']);

511
512
513
514
515
516
517
518
519
520
521
522
523
  // Associated content display
  // Set the default display handler if one is not set or the plugin is missing.
  if (!$display_settings || !class_exists($display_settings['associated_display_plugin'], TRUE)) {
    $display_settings = array(
      'term_display_plugin' => 'TaxonomyDisplayAssociatedDisplayHandlerCore',
    );
  }
  // Set the associated display options.
  if (!$display_settings || !isset($display_settings['associated_display_options'])) {
    $display_settings['associated_display_options'] = NULL;
  }
  else {
    $display_settings['associated_display_options'] = unserialize($display_settings['associated_display_options']);
524
  }
525
526
  $term_display = new $display_settings['associated_display_plugin'];
  $build = array_merge($build, $term_display->displayAssociated($term, $display_settings['associated_display_options']));
Cody Craven's avatar
Cody Craven committed
527
528
529
530
531
532
533

  return $build;
}

/**
 * Title callback; display title for term pages.
 *
534
535
536
537
 * As of now we do not do anything with this. If we come up with something that
 * would be helpful or requested we can add it. This is simply to make all of
 * the hook_menu_alter functions we changed point to the same module.
 *
Cody Craven's avatar
Cody Craven committed
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
 * @param $term
 *   A term object.
 *
 * @return
 *   The term name to be used as the page title.
 */
function taxonomy_display_taxonomy_term_title($term) {
  return taxonomy_term_title($term);
}

/**
 * Implements taxonomy_vocabulary_delete().
 *
 * @todo test this works
 */
function taxonomy_display_taxonomy_vocabulary_delete($vocabulary) {
554
555
556
557
  // Delete our display record for the vocabulary being removed.
  taxonomy_display_delete_taxonomy_dislpay($vocabulary->machine_name,
      'Taxonomy display settings deleted for %name in response to the vocabulary being deleted.',
      array('%name' => $vocabulary->machine_name));
Cody Craven's avatar
Cody Craven committed
558
559
560
561
562
563
564
565
566
567
}

/**
 * Implements taxonomy_vocabulary_update().
 *
 * @todo test this works
 */
function taxonomy_display_taxonomy_vocabulary_update($vocabulary) {
  // If the machine name is changed update our display table so that the display
  // settings still apply.
568
569
570
571
572
573
  if ($vocabulary->old_machine_name != $vocabulary->machine_name &&
      taxonomy_display_fetch_taxonomy_display($vocabulary->old_machine_name)) {
    taxonomy_display_save_taxonomy_dislpay($vocabulary->old_machine_name,
        array('machine_name' => $vocabulary->machine_name),
        'Taxonomy display vocabulary changed machine name from %old to %new in response to the vocabulary machine name being altered.',
        array('%old' => $vocabulary->old_machine_name, '%new' => $vocabulary->machine_name));
Cody Craven's avatar
Cody Craven committed
574
575
  }
}