Projet

Général

Profil

Paste
Télécharger (18,3 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / ds / modules / ds_ui / includes / ds.fields.inc @ 7fe061e8

1 85ad3d82 Assos Assos
<?php
2
3
/**
4
 * @file
5
 * Administrative functions for managing custom fields for every entity.
6
 */
7
8
/**
9
 * Shows the list of custom fields.
10
 */
11
function ds_custom_fields_list() {
12
  $output = '';
13
14
  ctools_include('export');
15
  $custom_fields = ctools_export_crud_load_all('ds_fields');
16
  if (!empty($custom_fields)) {
17
18
    $rows = array();
19
    foreach ($custom_fields as $field_key => $field_value) {
20
      $row = array();
21
      $row[] = check_plain($field_value->label);
22
      $row[] = ds_field_human_name($field_value->field_type);
23
      $row[] = $field_key;
24
      $row[] = ucwords(str_replace('_', ' ', implode(', ', $field_value->entities)));
25
      $operations = l(t('Edit'), 'admin/structure/ds/fields/manage/' . $field_key, array('alias' => TRUE));
26
27
      if ($field_value->export_type == 3) {
28
        $operations .= ' - ' . l(t('Revert'), 'admin/structure/ds/fields/revert/' . $field_key, array('alias' => TRUE));
29
      }
30
      elseif ($field_value->export_type == 1) {
31
        $operations .= ' - ' . l(t('Delete'), 'admin/structure/ds/fields/delete/' . $field_key, array('alias' => TRUE));
32
      }
33
      $row[] = $operations;
34
      $rows[] = $row;
35
    }
36
37
    $table = array(
38
      'header' => array(
39
        'Label',
40
        'Type',
41
        'Machine name',
42
        'Entities',
43
        'Operations',
44
      ),
45
      'rows' => $rows,
46
    );
47
48
    $output = theme('table', $table);
49
  }
50
  else {
51
    $output = t('No custom fields have been defined.');
52
  }
53
54
  return $output;
55
}
56
57
/**
58
 * Return the human name of a field.
59
 *
60
 * @return $human_name
61
 *   The human name of a field.
62
 */
63
function ds_field_human_name($type) {
64
65
  switch ($type) {
66
    case DS_FIELD_TYPE_CODE:
67
      return t('Code field');
68
    case DS_FIELD_TYPE_BLOCK:
69
      return t('Block field');
70
    case DS_FIELD_TYPE_CTOOLS:
71
      return t('Dynamic field');
72
    case DS_FIELD_TYPE_PREPROCESS:
73
      return t('Preprocess field');
74
  }
75
76
  // Fallback
77
  return t('Unknown');
78
}
79
80
/**
81
 * Manage a field. This will redirect to the exact form.
82
 */
83
function ds_custom_manage($field_key = '') {
84
  $redirect = '';
85
  ctools_include('export');
86
  $custom_fields = ctools_export_crud_load_all('ds_fields');
87
  if (isset($custom_fields[$field_key])) {
88
    $field = $custom_fields[$field_key];
89
    switch ($field->field_type) {
90
      case DS_FIELD_TYPE_CODE:
91
        $redirect = 'admin/structure/ds/fields/manage_custom/' . $field_key;
92
        break;
93
94
      case DS_FIELD_TYPE_BLOCK:
95
        $redirect = 'admin/structure/ds/fields/manage_block/' . $field_key;
96
        break;
97
98
      case DS_FIELD_TYPE_CTOOLS:
99
        $redirect = 'admin/structure/ds/fields/manage_ctools/' . $field_key;
100
        break;
101
102
      case DS_FIELD_TYPE_PREPROCESS:
103
        $redirect = 'admin/structure/ds/fields/manage_preprocess/' . $field_key;
104
        break;
105
106
      default:
107
        drupal_set_message(t('Field not found'));
108
        $redirect = 'admin/structure/ds/fields';
109
        break;
110
    }
111
  }
112
113
  drupal_goto($redirect);
114
}
115
116
/**
117 7fe061e8 Assos Assos
 * Shared form for all fields.
118 85ad3d82 Assos Assos
 */
119
function ds_shared_form(&$form, $field) {
120
  ctools_include('export');
121
  $custom_fields = ctools_export_crud_load_all('ds_fields');
122
  if (isset($custom_fields[$field])) {
123
    $field = $custom_fields[$field];
124
    if (!isset($field->ui_limit)) {
125
      $field->ui_limit = '';
126
    }
127
  }
128
  else {
129
    $field = new stdClass;
130
    $field->label = '';
131
    $field->field = '';
132
    $field->ui_limit = '';
133
    $field->entities = array();
134
    $field->properties = array();
135
  }
136
137
  $form['name'] = array(
138
    '#title' => t('Label'),
139
    '#type' => 'textfield',
140
    '#default_value' => $field->label,
141
    '#description' => t('The human-readable label of the field.'),
142
    '#maxlength' => 128,
143
    '#required' => TRUE,
144
    '#size' => 30,
145
  );
146
147
  $form['field'] = array(
148
    '#type' => 'machine_name',
149
    '#default_value' => $field->field,
150
    '#maxlength' => 32,
151
    '#description' => t('The machine-readable name of this field. This name must contain only lowercase letters and underscores. This name must be unique.'),
152
    '#disabled' => !empty($field->field),
153
    '#machine_name' => array(
154
      'exists' => 'ds_field_unique',
155
    ),
156
  );
157
158
  $entity_options = array();
159
  $entities = entity_get_info();
160
  foreach ($entities as $entity_type => $entity_info) {
161
    if ((isset($entity_info['fieldable']) && $entity_info['fieldable']) || $entity_type == 'ds_views') {
162
      $entity_options[$entity_type] = drupal_ucfirst(str_replace('_', ' ', $entity_type));
163
    }
164
  }
165
  $form['entities'] = array(
166
    '#title' => t('Entities'),
167
    '#description' => t('Select the entities for which this field will be made available.'),
168
    '#type' => 'checkboxes',
169
    '#required' => TRUE,
170
    '#options' => $entity_options,
171
    '#default_value' => $field->entities,
172
  );
173
174
  $form['ui_limit'] = array(
175
    '#title' => t('Limit field'),
176
    '#description' => t('Limit this field on field UI per bundles and/or view modes. The values are in the form of $bundle|$view_mode, where $view_mode may be either a view mode set to use custom settings, or \'default\'. You may use * to select all, e.g article|*, *|full or *|*. Enter one value per line.'),
177
    '#type' => 'textarea',
178
    '#default_value' => $field->ui_limit,
179 7fe061e8 Assos Assos
    '#element_validate' => array('ds_ui_limit_validate'),
180 85ad3d82 Assos Assos
  );
181
182
  $form['submit'] = array(
183
    '#type' => 'submit',
184
    '#value' => t('Save'),
185
    '#weight' => 100,
186
  );
187
188
  // Validate & submit are also the same.
189
  $form['#validate'][] = 'ds_shared_form_validate';
190
  $form['#submit'][] = 'ds_shared_form_submit';
191
192
  return $field;
193
}
194
195 7fe061e8 Assos Assos
/**
196
 * Element validation function for ui limit field.
197
 */
198
function ds_ui_limit_validate($element, &$form_state, $form) {
199
  // Get all enabled entity types.
200
  $entity_types = array_filter($form_state['values']['entities']);
201
202
  if (!empty($element['#value'])) {
203
    $ui_limit = $element['#value'];
204
205
    $lines = explode("\n", str_replace("\r", "\n", $ui_limit));
206
    // Ensure that all strings are trimmed and filter out empty lines.
207
    $lines = array_filter(array_map('trim', $lines));
208
209
    $error = FALSE;
210
    foreach ($lines as $line) {
211
      // Each line should hold a pipe character to seperate bundle and view_mode.
212
      if (strpos($line, '|') === FALSE) {
213
        $error = TRUE;
214
        continue;
215
      }
216
217
      list($bundle, $view_mode) = explode('|', $line);
218
219
      if (empty($bundle) || empty($view_mode) || !_ds_check_existing_ui_limit($entity_types, $bundle, $view_mode)) {
220
        $error = TRUE;
221
      }
222
    }
223
    if ($error) {
224
      form_error($element, t('The values are in the form of $bundle|$view_mode, where $view_mode may be either a view mode set to use custom settings, or \'default\'.'));
225
    }
226
227
    // Set trimmed and validated entry back as value.
228
    form_set_value($element, implode("\n", $lines), $form_state);
229
  }
230
}
231
232
/**
233
 * Helper function to check if bundle + view_mode combination exists.
234
 */
235
function _ds_check_existing_ui_limit($entity_types, $bundle, $view_mode) {
236
  $exists = FALSE;
237
  foreach ($entity_types as $entity_type) {
238
    $info = entity_get_info($entity_type);
239
240
    // Combine allowed bundles and entity specific ones.
241
    $bundle_allowed = array('*');
242
    $bundles = array_merge($bundle_allowed, array_keys($info['bundles']));
243
244
    // Combine allowed view_modes and entity specific ones.
245
    $view_mode_allowed = array('*', 'default');
246
    $view_modes = array_merge($view_mode_allowed, array_keys($info['view modes']));
247
248
    if (in_array($bundle, $bundles) &&
249
      in_array($view_mode, $view_modes)) {
250
251
      $exists = TRUE;
252
      break;
253
    }
254
  }
255
  if (!$exists) {
256
    drupal_set_message(t('Incorrect field limit combination: @bundle|@view_mode', array('@bundle' => $bundle, '@view_mode' => $view_mode)), 'error');
257
  }
258
259
  return $exists;
260
}
261
262 85ad3d82 Assos Assos
/**
263
 * Return whether a field machine name is unique.
264
 */
265
function ds_field_unique($name) {
266
  ctools_include('export');
267
  $custom_fields = ctools_export_crud_load_all('ds_fields');
268
  $value = strtr($name, array('-' => '_'));
269
  return isset($custom_fields[$value]) ? TRUE : FALSE;
270
}
271
272
/**
273
 * Shared field form validation.
274
 */
275
function ds_shared_form_validate($form, &$form_state) {
276
  $field = new stdClass;
277
  $field->properties = array();
278
  $field->field = $form_state['values']['field'];
279
  $field->label = $form_state['values']['name'];
280 7fe061e8 Assos Assos
  $field->ui_limit = $form_state['values']['ui_limit'];
281 85ad3d82 Assos Assos
282
  $entities = $form_state['values']['entities'];
283
  foreach ($entities as $key => $value) {
284
    if ($key !== $value) {
285
      unset($entities[$key]);
286
    }
287
  }
288
  $field->entities = $entities;
289
  $form_state['field'] = $field;
290
}
291
292
/**
293
 * Save any field.
294
 */
295
function ds_shared_form_submit($form, &$form_state) {
296
  $field = $form_state['field'];
297
298
  // Delete previous field configuration.
299
  db_delete('ds_fields')
300
    ->condition('field', $field->field)
301
    ->execute();
302
303
  // Save field and clear ds_fields.
304
  drupal_write_record('ds_fields', $field);
305
  cache_clear_all('ds_fields:', 'cache', TRUE);
306
307
  // Redirect.
308
  $form_state['redirect'] = 'admin/structure/ds/fields';
309
  drupal_set_message(t('The field %field has been saved', array('%field' => $field->label)));
310
}
311
312
/**
313
 * Manage a custom field.
314
 */
315
function ds_edit_custom_field_form($form, &$form_state, $custom_field = '') {
316
  drupal_set_title(empty($custom_field) ? t('Add a code field') : t('Edit code field'));
317
318
  $custom_field = ds_shared_form($form, $custom_field);
319
320
  $form['code'] = array(
321
    '#type' => 'text_format',
322
    '#title' => t('Field code'),
323
    '#default_value' => isset($custom_field->properties['code']['value']) ? $custom_field->properties['code']['value'] : '',
324
    '#format' => isset($custom_field->properties['code']['format']) ? $custom_field->properties['code']['format'] : 'ds_code',
325
    '#base_type' => 'textarea',
326
    '#required' => TRUE,
327
  );
328
329
  $form['use_token'] = array(
330
    '#type' => 'checkbox',
331
    '#title' => t('Token'),
332
    '#description' => t('Toggle this checkbox if you are using tokens in this field.'),
333
    '#default_value' => isset($custom_field->properties['use_token']) ? $custom_field->properties['use_token'] : '',
334
  );
335
336
  // Token support.
337
  if (module_exists('token')) {
338
339
    $form['tokens'] = array(
340
      '#title' => t('Tokens'),
341
      '#type' => 'container',
342
      '#states' => array(
343
        'invisible' => array(
344
          'input[name="use_token"]' => array('checked' => FALSE),
345
        ),
346
      ),
347
    );
348
    $form['tokens']['help'] = array(
349
      '#theme' => 'token_tree',
350
      '#token_types' => 'all',
351
      '#global_types' => FALSE,
352
      '#dialog' => TRUE,
353
    );
354
  }
355
  else {
356
    $form['use_token']['#description'] = t('Toggle this checkbox if you are using tokens in this field. If the token module is installed, you get a nice list of all tokens available in your site.');
357
  }
358
359
  $form['#validate'][] = 'ds_custom_field_form_validate';
360
361
  return $form;
362
}
363
364
/**
365
 * Custom field form validation.
366
 */
367
function ds_custom_field_form_validate($form, &$form_state) {
368
  $form_state['field']->field_type = DS_FIELD_TYPE_CODE;
369
  $form_state['field']->properties['code'] = $form_state['values']['code'];
370
  $form_state['field']->properties['use_token'] = $form_state['values']['use_token'];
371
}
372
373
/**
374
 * Manage a CTools field.
375
 */
376
function ds_edit_ctools_field_form($form, &$form_state, $ctools_field = '') {
377
  drupal_set_title(empty($ctools_field) ? t('Add a dynamic field') : t('Edit dynamic field'));
378
379
  $custom_field = ds_shared_form($form, $ctools_field);
380
  $form['info'] = array(
381
    '#markup' => t('The content of this field is configurable on the "Manage display" screens.'),
382
    '#weight' => -10,
383
  );
384
  $form['#validate'][] = 'ds_ctools_field_form_validate';
385
  return $form;
386
}
387
388
/**
389
 * CTools field form validation.
390
 */
391
function ds_ctools_field_form_validate($form, &$form_state) {
392
  $form_state['field']->field_type = DS_FIELD_TYPE_CTOOLS;
393
  $form_state['field']->properties['default'] = array();
394
  $form_state['field']->properties['settings'] = array('show_title' => array('type' => 'checkbox'), 'title_wrapper' => array('type' => 'textfield', 'description' => t('Eg: h1, h2, p')), 'ctools' => array('type' => 'ctools'));
395
}
396
397
/**
398
 * Manage a Preprocess field.
399
 */
400
function ds_edit_preprocess_field_form($form, &$form_state, $preprocess_field = '') {
401
  drupal_set_title(empty($preprocess_field) ? t('Add a preprocess field') : t('Edit preprocess field'));
402
403
  $custom_field = ds_shared_form($form, $preprocess_field);
404
  $form['info'] = array(
405
    '#markup' => t('The machine name of this field must reflect the key in the variables, e.g. "submitted". So in most cases, it is very likely you will have to manually edit the machine name as well, which can not be changed anymore after saving. Note that this field type works best on Nodes.'),
406
    '#weight' => -10,
407
  );
408
  $form['#validate'][] = 'ds_preprocess_field_form_validate';
409
  return $form;
410
}
411
412
/**
413
 * CTools field form validation.
414
 */
415
function ds_preprocess_field_form_validate($form, &$form_state) {
416
  $form_state['field']->field_type = DS_FIELD_TYPE_PREPROCESS;
417
}
418
419
/**
420
 * Manage a custom block.
421
 */
422
function ds_edit_block_field_form($form, &$form_state, $custom_block = '') {
423
  drupal_set_title(empty($custom_block) ? t('Add a block field') : t('Edit block field'));
424
425
  $custom_block = ds_shared_form($form, $custom_block);
426
427
  $blocks = array();
428
  foreach (module_implements('block_info') as $module) {
429
    $module_blocks = module_invoke($module, 'block_info');
430
    if ($module_blocks) {
431
      foreach ($module_blocks as $module_key => $info) {
432
        $blocks[drupal_ucfirst($module)][$module . '|' . $module_key] = $info['info'];
433
      }
434
    }
435
  }
436
  ksort($blocks);
437
  foreach($blocks as &$subarray) {
438
    asort($subarray);
439
  }
440
441
  $form['block_identity']['block'] = array(
442
    '#type' => 'select',
443
    '#options' => $blocks,
444
    '#title' => t('Block'),
445
    '#required' => TRUE,
446
    '#default_value' => isset($custom_block->properties['block']) ? $custom_block->properties['block'] : '',
447
  );
448
  $form['block_identity']['block_render'] = array(
449
    '#type' => 'select',
450
    '#options' => array(
451
      DS_BLOCK_TEMPLATE => t('Default'),
452
      DS_BLOCK_TITLE_CONTENT => t('Show block title + content'),
453
      DS_BLOCK_CONTENT => t('Show only block content'),
454
    ),
455
    '#title' => t('Layout'),
456
    '#required' => TRUE,
457
    '#default_value' => isset($custom_block->properties['block_render']) ? $custom_block->properties['block_render'] : '',
458
  );
459
460
  $form['#validate'][] = 'ds_block_field_form_validate';
461
462
  return $form;
463
}
464
465
/**
466
 * Custom field form validation.
467
 */
468
function ds_block_field_form_validate($form, &$form_state) {
469
  $form_state['field']->field_type = DS_FIELD_TYPE_BLOCK;
470
  $form_state['field']->properties = array();
471
  $form_state['field']->properties['block'] = $form_state['values']['block'];
472
  $form_state['field']->properties['block_render'] = $form_state['values']['block_render'];
473
}
474
475
/**
476
 * Menu callback: Confirmation custom field delete form.
477
 */
478
function ds_delete_field_confirm($form, &$form_state, $field = '') {
479
  return ds_remove_fields_form($form, $form_state, $field, 'delete');
480
}
481
482
/**
483
 * Menu callback: Confirmation custom field delete form.
484
 */
485
function ds_revert_field_confirm($form, &$form_state, $field = '') {
486
  return ds_remove_fields_form($form, $form_state, $field, 'revert');
487
}
488
489
/**
490
 * Confirmation delete or revert form.
491
 */
492
function ds_remove_fields_form($form, &$form_state, $field = '', $action = 'delete') {
493
  ctools_include('export');
494
  $custom_fields = ctools_export_crud_load_all('ds_fields');
495
  if (isset($custom_fields[$field])) {
496
    $field = $custom_fields[$field];
497
    $form['#ds_field'] = $field;
498
    return confirm_form($form,
499
      t('Are you sure you want to ' . $action . ' %field?', array('%field' => $field->label)),
500
      'admin/structure/ds/fields',
501
      t('This action cannot be undone.'),
502
      t(drupal_ucfirst($action)),
503
      t('Cancel')
504
    );
505
  }
506
  else {
507
    drupal_set_message(t('Unknown field'));
508
    drupal_goto('admin/structure/ds/fields');
509
  }
510
}
511
512
/**
513
 * Submit callback: confirmed delete submit.
514
 */
515
function ds_delete_field_confirm_submit($form, &$form_state) {
516
  ds_remove_field_confirm_submit($form, $form_state, 'deleted');
517
}
518
519
/**
520
 * Submit callback: confirmed revert submit.
521
 */
522
function ds_revert_field_confirm_submit($form, &$form_state) {
523
  ds_remove_field_confirm_submit($form, $form_state, 'reverted');
524
}
525
526
/**
527
 * Confirmed field delete or revert submit callback.
528
 */
529
function ds_remove_field_confirm_submit($form, &$form_state, $action = 'deleted') {
530
531
  $field = $form['#ds_field'];
532
533
  // Remove field.
534
  db_delete('ds_fields')
535
    ->condition('field', $field->field)
536
    ->execute();
537
538
  // Clear cache.
539
  cache_clear_all('ds_fields:', 'cache', TRUE);
540
541
  // Redirect.
542
  $form_state['redirect'] = 'admin/structure/ds/fields';
543
  drupal_set_message(t('The field %field has been ' . $action, array('%field' => $field->label)));
544
}
545
546
/**
547
 * Handles ctools modal Add field
548
 *
549
 * @param $js
550
 *  Whether js is used or not.
551
 * @param $field_type
552
 *   The name of the field type.
553
 */
554
function ds_ajax_add_field($js, $field_type) {
555
556
  if (!$js) {
557
    // We don't support degrading this from js because we're not
558
    // using the server to remember the state of the table.
559
    drupal_goto("admin/structure/ds/fields/" . $field_type);
560
    return;
561
  }
562
563
  ctools_include('ajax');
564
  ctools_include('modal');
565
566
  switch ($field_type) {
567
568
    case "manage_ctools":
569
      $title = t('Add a dynamic field');
570
      $form_name = "ds_edit_ctools_field_form";
571
      break;
572
573
    case "manage_preprocess":
574
      $title = t('Add a preprocess field');
575
      $form_name = "ds_edit_preprocess_field_form";
576
      break;
577
578
    case "manage_block":
579
      $title = t('Add a block field');
580
      $form_name = "ds_edit_block_field_form";
581
      break;
582
583
    default:
584
      $title = t('Add a code field');
585
      $form_name = "ds_edit_custom_field_form";
586
      $field_type = 'manage_custom';
587
      break;
588
  }
589
590
  $form_state = array();
591
  $form_state['build_info']['args'] = array();
592
  $form_state += array(
593
    'title' => $title,
594
    'ajax' => TRUE,
595
    're_render' => FALSE,
596
  );
597
598
  $output = NULL;
599
  form_load_include($form_state, 'inc', 'ds_ui', 'includes/ds.fields');
600
601
  $output = ctools_modal_form_wrapper($form_name, $form_state);
602
603
  // Field is saved.
604
  if ($form_state['executed']) {
605
606
    $output = array();
607
608
    // Do not print messages on screen.
609
    if ($messages = theme('status_messages')) {
610
      $output[] = ajax_command_append('#console', $messages);
611
    }
612
613
    // Close the modal.
614
    $output[] = ctools_modal_command_dismiss();
615
616
    // Call our own javascript function which will trigger a refresh of the table.
617
    $output[] = ajax_command_invoke('#field-display-overview', 'dsRefreshDisplayTable');
618
  }
619
620
  drupal_add_http_header('Content-Type', 'application/json');
621
  print ajax_render($output);
622
  exit;
623
}