Projet

Général

Profil

Paste
Télécharger (89,4 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / ds / includes / ds.field_ui.inc @ 74f6bef0

1
<?php
2

    
3
/**
4
 * @file
5
 * Field UI functions for Display Suite.
6
 */
7

    
8
/**
9
 * Adds the Display Suite fields and layouts to the form.
10
 */
11
function ds_field_ui_fields_layouts(&$form, &$form_state) {
12
  global $base_root, $base_path;
13

    
14
  // Get the entity_type, bundle and view mode.
15
  $entity_type = $form['#entity_type'];
16
  $bundle = $form['#bundle'];
17
  $view_mode = $form['#view_mode'];
18

    
19
  $form['#export_id'] = $entity_type . '|' . $bundle . '|' . $view_mode;
20

    
21
  // Create vertical tabs.
22
  ds_field_ui_create_vertical_tabs($form);
23

    
24
  // Add layout fieldset.
25
  _ds_field_ui_table_layouts($entity_type, $bundle, $view_mode, $form, $form_state);
26

    
27
  // Add/alter fields on the table, but only if a layout is selected.
28
  if ($view_mode != 'form' && !empty($form['#ds_layout'])) {
29
    _ds_field_ui_fields($entity_type, $bundle, $view_mode, $form, $form_state);
30

    
31
    // Also alter core fields
32
    _ds_field_ui_core_fields($entity_type, $bundle, $view_mode, $form, $form_state);
33
  }
34

    
35
  // Add buttons to add fields in overlay.
36
  if (isset($form['#ds_layout']) && user_access('admin_fields') && $view_mode != 'form' && module_exists('ds_ui')) {
37
    _ds_field_ui_custom_fields($entity_type, $bundle, $view_mode, $form, $form_state);
38
  }
39

    
40
  // Special validate function for field group.
41
  if (isset($form_state['no_field_group'])) {
42
    array_unshift($form['#validate'], '_ds_field_group_field_ui_fix_notices');
43
  }
44

    
45
  // Attach js.
46
  $form['#attached']['js'][] = drupal_get_path('module', 'ds') . '/js/ds.admin.js';
47

    
48
  // Attach css.
49
  $form['#attached']['css'][] = drupal_get_path('module', 'ds') . '/css/ds.admin.css';
50

    
51
  // Add process function to add the regions.
52
  $form['#process'][] = 'ds_field_ui_regions';
53

    
54
  // Add a destination so we can get back if layout has been changed.
55
  $form['ds_source'] = array(
56
    '#type' => 'hidden',
57
    '#value' => $base_root . $base_path,
58
  );
59
  $form['ds_destination'] = array(
60
    '#type' => 'hidden',
61
    '#value' => drupal_get_destination(),
62
  );
63
  $form['ds_entity_type'] = array(
64
    '#type' => 'hidden',
65
    '#value' => $entity_type,
66
  );
67
  $form['ds_bundle'] = array(
68
    '#type' => 'hidden',
69
    '#value' => $bundle,
70
  );
71
  $form['ds_view_mode'] = array(
72
    '#type' => 'hidden',
73
    '#value' => $view_mode,
74
  );
75
}
76

    
77
/**
78
 * Create vertical tabs.
79
 */
80
function ds_field_ui_create_vertical_tabs(&$form) {
81

    
82
  // Add additional settings vertical tab.
83
  if (!isset($form['additional_settings'])) {
84
    $form['additional_settings'] = array(
85
      '#type' => 'vertical_tabs',
86
      '#theme_wrappers' => array('vertical_tabs'),
87
      '#prefix' => '<div>',
88
      '#suffix' => '</div>',
89
      '#tree' => TRUE,
90
    );
91
    $form['#attached']['js'][] = 'misc/form.js';
92
    $form['#attached']['js'][] = 'misc/collapse.js';
93
  }
94

    
95
  $view_mode_admin_access = user_access('admin_view_modes') && module_exists('ds_ui');
96
  if (isset($form['modes'])) {
97
    if ($view_mode_admin_access) {
98
      $form['modes']['view_modes_custom']['#description'] = l(t('Manage view modes'), 'admin/structure/ds/view_modes');
99
    }
100
    $form['additional_settings']['modes'] = $form['modes'];
101
    $form['additional_settings']['modes']['#weight'] = -10;
102
    unset($form['modes']);
103
  }
104
  else {
105
    if ($view_mode_admin_access) {
106
      $form['additional_settings']['modes']['view_modes_custom']['#description'] = l(t('Manage view modes'), 'admin/structure/ds/view_modes');
107
    }
108
  }
109
}
110

    
111
/**
112
 * Menu callback: Disable layout and field settings form.
113
 */
114
function ds_disable_layout_field_settings_form($form, &$form_state, $id = '') {
115
  $layout = new stdClass();
116
  ctools_include('export');
117
  $ds_layout_settings = ctools_export_crud_load_all('ds_layout_settings');
118
  if (isset($ds_layout_settings[$id])) {
119
    $layout = $ds_layout_settings[$id];
120
  }
121

    
122
  if (isset($layout) && $layout->export_type != 1 && empty($layout->disable)) {
123
    $form['#layout'] = $layout;
124
    $form['#export_id'] = $id;
125
    return confirm_form($form,
126
      t('Are you sure you want to disable the layout and field settings for %layout?', array('%layout' => implode(', ', explode('|', $layout->id)))),
127
      drupal_get_destination(),
128
      t('This action cannot be undone.'),
129
      t('Disable'),
130
      t('Cancel')
131
    );
132
  }
133
  else {
134
    drupal_set_message(t('This operation is not possible.'));
135
  }
136
}
137

    
138
/**
139
 * Submit callback: disable layout and field settings.
140
 */
141
function ds_disable_layout_field_settings_form_submit(&$form, &$form_state) {
142
  $layout = $form['#layout'];
143

    
144
  ctools_include('export');
145
  ctools_export_crud_disable('ds_layout_settings', $form['#export_id']);
146
  ctools_export_crud_disable('ds_field_settings', $form['#export_id']);
147
  // @todo layout fields
148

    
149
  // Clear the ds_fields cache.
150
  cache_clear_all('ds_fields:', 'cache', TRUE);
151
  cache_clear_all('ds_field_settings', 'cache');
152

    
153
  // Clear entity info cache.
154
  cache_clear_all('entity_info', 'cache', TRUE);
155

    
156
  drupal_set_message(t('Layout has been disabled.'));
157

    
158
  $form_state['redirect'] = isset($_GET['destination']) ? $_GET['destination'] : drupal_get_destination();
159
}
160

    
161
/**
162
 * Menu callback: Enable layout and field settings form.
163
 */
164
function ds_enable_layout_field_settings_form($form, &$form_state, $id = '') {
165
  $layout = new stdClass();
166
  ctools_include('export');
167
  $ds_layout_settings = ctools_export_crud_load_all('ds_layout_settings');
168
  if (isset($ds_layout_settings[$id])) {
169
    $layout = $ds_layout_settings[$id];
170
  }
171

    
172
  if (isset($layout) && $layout->export_type != 1 && !empty($layout->disabled)) {
173
    $form['#layout'] = $layout;
174
    $form['#export_id'] = $id;
175
    return confirm_form($form,
176
      t('Are you sure you want to enable the layout and field settings for %layout?', array('%layout' => implode(', ', explode('|', $layout->id)))),
177
      drupal_get_destination(),
178
      t('This action cannot be undone.'),
179
      t('Enable'),
180
      t('Cancel')
181
    );
182
  }
183
  else {
184
    drupal_set_message(t('This operation is not possible.'));
185
  }
186
}
187

    
188
/**
189
 * Submit callback: enable layout and field settings.
190
 */
191
function ds_enable_layout_field_settings_form_submit(&$form, &$form_state) {
192
  $layout = $form['#layout'];
193

    
194
  ctools_include('export');
195
  ctools_export_crud_enable('ds_layout_settings', $form['#export_id']);
196
  ctools_export_crud_enable('ds_field_settings', $form['#export_id']);
197

    
198
  // Clear the ds_fields cache.
199
  cache_clear_all('ds_fields:', 'cache', TRUE);
200
  cache_clear_all('ds_field_settings', 'cache');
201

    
202
  // Clear entity info cache.
203
  cache_clear_all('entity_info', 'cache', TRUE);
204

    
205
  drupal_set_message(t('Layout has been enabled'));
206

    
207
  $form_state['redirect'] = isset($_GET['destination']) ? $_GET['destination'] : drupal_get_destination();
208
}
209

    
210
/**
211
 * Menu callback: Revert layout and field settings form.
212
 */
213
function ds_revert_layout_field_settings_form($form, &$form_state, $id = '') {
214
  $layout = new stdClass();
215
  ctools_include('export');
216
  $ds_layout_settings = ctools_export_crud_load_all('ds_layout_settings');
217
  if (isset($ds_layout_settings[$id])) {
218
    $layout = $ds_layout_settings[$id];
219
  }
220

    
221
  if (isset($layout) && $layout->export_type == 3) {
222
    $form['#layout'] = $layout;
223
    return confirm_form($form,
224
      t('Are you sure you want to revert the layout for %layout?', array('%layout' => implode(', ', explode('|', $layout->id)))),
225
      drupal_get_destination(),
226
      t('This action cannot be undone.'),
227
      t('Revert'),
228
      t('Cancel')
229
    );
230
  }
231
  else {
232
    drupal_set_message(t('This operation is not possible.'));
233
  }
234
}
235

    
236
/**
237
 * Submit callback: revert layout and field settings.
238
 */
239
function ds_revert_layout_field_settings_form_submit(&$form, &$form_state) {
240
  $layout = $form['#layout'];
241

    
242
  db_delete('ds_field_settings')
243
    ->condition('id', $layout->id)
244
    ->execute();
245

    
246
  db_delete('ds_layout_settings')
247
    ->condition('id', $layout->id)
248
    ->execute();
249

    
250
  // Clear the ds_fields cache.
251
  cache_clear_all('ds_fields:', 'cache', TRUE);
252
  cache_clear_all('ds_field_settings', 'cache');
253

    
254
  // Clear entity info cache.
255
  cache_clear_all('entity_info', 'cache', TRUE);
256

    
257
  drupal_set_message(t('Layout has been reverted'));
258

    
259
  $form_state['redirect'] = isset($_GET['destination']) ? $_GET['destination'] : drupal_get_destination();
260
}
261

    
262
/**
263
 * Add Regions to 'Manage fields' or 'Manage display' screen.
264
 *
265
 * @param $form
266
 *   The form to add layout fieldset and extra Display Suite fields.
267
 * @param $form_state
268
 *   The current form state.
269
 */
270
function ds_field_ui_regions($form, $form_state) {
271

    
272
  // Get the entity_type, bundle and view mode.
273
  $entity_type = $form['#entity_type'];
274
  $bundle = $form['#bundle'];
275
  $view_mode = $form['#view_mode'];
276

    
277
  // Ignore fieldgroup options.
278
  if (isset($form_state['no_field_group'])) {
279
    unset($form['fields']['_add_new_group']);
280
    $form['additional_settings']['field_group']['#access'] = FALSE;
281
  }
282

    
283
  // Check layout.
284
  $layout = isset($form['#ds_layout']) ? $form['#ds_layout'] : FALSE;
285

    
286
  // Change UI to add Region column if we have a layout.
287
  if ($layout) {
288
    $table = &$form['fields'];
289

    
290
    if ($view_mode != 'form') {
291
      $table['#header'] = array(
292
        t('Field'),
293
        t('Weight'),
294
        t('Parent'),
295
        t('Region'),
296
        t('Label'),
297
        array('data' => t('Format'), 'colspan' => 3),
298
      );
299
    }
300
    else {
301
      $table['#header'] = array(
302
        t('Label'),
303
        t('Weight'),
304
        t('Parent'),
305
        t('Region'),
306
        t('Name'),
307
        t('Field'),
308
        t('Widget'),
309
        array('data' => t('Operations'), 'colspan' => 2),
310
      );
311
    }
312

    
313
    // Remove label and format for views.
314
    if ($entity_type == 'ds_views') {
315
      $table['#header'][4] = '';
316
    }
317

    
318
    $table['#regions'] = array();
319
    foreach ($layout->regions as $region_key => $region_title) {
320
      $region_options[$region_key] = $region_title;
321
      $table['#regions'][$region_key] = array(
322
        'title' => $region_title,
323
        'message' => t('No fields are displayed in this region'),
324
      );
325
    }
326

    
327
    // Let other modules alter the regions.
328
    $context = array(
329
      'entity_type' => $entity_type,
330
      'bundle' => $bundle,
331
      'view_mode' => $view_mode
332
    );
333
    $region_info = array(
334
      'region_options' => &$region_options,
335
      'table_regions' => &$table['#regions'],
336
    );
337
    drupal_alter('ds_layout_region', $context, $region_info);
338

    
339
    $region_options['hidden'] = $view_mode != 'form' ? t('Disabled') : t('Hidden');
340
    $table['#regions']['hidden'] = array(
341
      'title' => $view_mode != 'form' ? t('Disabled') : t('Hidden'),
342
      'message' => t('No fields are hidden.')
343
    );
344

    
345
    $region = array(
346
      '#type' => 'select',
347
      '#options' => $region_options,
348
      '#default_value' => 'hidden',
349
      '#attributes' => array(
350
        'class' => array('ds-field-region'),
351
      )
352
    );
353

    
354
    $limit_items = array(
355
      '#type' => 'textfield',
356
      '#size' => 2,
357
      '#default_value' => '',
358
      '#weight' => 10,
359
      '#default_value' => '#',
360
      '#prefix' => '<div class="limit-float">',
361
      '#suffix' => '</div><div class="clearfix"></div>',
362
      '#attributes' => array(
363
        'alt' => t('Enter a number to limit the number of items or \'delta\' to print a specific delta (usually configured in views or found in entity->ds_delta). Leave empty to display them all. Note that depending on the formatter settings, this option might not always work.'),
364
        'title' => t('Enter a number to limit the number of items or \'delta\' to print a specific delta (usually configured in views or found in entity->ds_delta). Leave empty to display them all. Note that depending on the formatter settings, this option might not always work.'),
365
      ),
366
    );
367

    
368
    // Hide this if we formatter_settings_edit is not empty so it doesn't confuse users.
369
    if (!empty($form_state['formatter_settings_edit'])) {
370
      $limit_items['#access'] = FALSE;
371
    }
372

    
373
    // Update existing rows by changing rowHandler and adding regions.
374
    foreach (element_children($table) as $name) {
375
      $row = &$table[$name];
376
      $row['#js_settings'] = array('rowHandler' => 'ds');
377
      $row['#region_callback'] = 'ds_field_ui_row_region';
378

    
379
      // Remove hidden format.
380
      if (isset($row['format']['type']['#options']['hidden'])) {
381
        unset($row['format']['type']['#options']['hidden']);
382
      }
383

    
384
      // Add label class.
385
      if (isset($row['label'])) {
386
        if (isset($form_state['formatter_settings']) && isset($form_state['formatter_settings'][$name]['ft'])) {
387
          if (!empty($form_state['formatter_settings'][$name]['ft']['lb'])) {
388
            $row['human_name']['#markup'] = check_plain($form_state['formatter_settings'][$name]['ft']['lb']) . ' ' . t('(Original: !orig)', array('!orig' => $row['human_name']['#markup']));
389
          }
390
        }
391
      }
392

    
393
      // Limit items.
394
      $field_info = field_info_field($name);
395
      if (isset($field_info['cardinality']) && $field_info['cardinality'] != 1 && $view_mode != 'form') {
396
        $row['format']['type']['#prefix'] = '<div class="limit-float">';
397
        $row['format']['type']['#suffix'] = '</div>';
398
        $row['format']['limit'] = $limit_items;
399
        $row['format']['limit']['#default_value'] = (isset($layout->settings['limit']) && isset($layout->settings['limit'][$name])) ? $layout->settings['limit'][$name] : '#';
400
      }
401

    
402
      // Disable label and format for views.
403
      if ($entity_type == 'ds_views') {
404
        $row['label']['#access'] = FALSE;
405
      }
406

    
407
      // Add region.
408
      $split = ($view_mode != 'form') ? 7 : 6;
409
      if ($row['#row_type'] == 'group' && $view_mode == 'form') {
410
        $split = ($view_mode != 'form') ? 8 : 7;
411
      }
412
      $second = array_splice($row, $split);
413
      $row['region'] = $region;
414
      $row['region']['#default_value'] = (isset($layout->settings['fields'][$name]) && isset($region_options[$layout->settings['fields'][$name]])) ? $layout->settings['fields'][$name] : 'hidden';
415
      $row = array_merge($row, $second);
416
    }
417
  }
418

    
419
  return $form;
420
}
421

    
422
/**
423
 * Returns the region to which a row in the Field UI screen belongs.
424
 *
425
 * @param $row
426
 *   The current row that is being rendered in the Field UI screen.
427
 */
428
function ds_field_ui_row_region($row) {
429
  return isset($row['region']['#value']) ? $row['region']['#value'] : 'hidden';
430
}
431

    
432
/**
433
 * Move the view modes so Field UI can handle them.
434
 */
435
function ds_field_ui_layouts_validate($form, &$form_state) {
436
  if (isset($form_state['values']['additional_settings']['modes']['view_modes_custom'])) {
437
    $form_state['values']['view_modes_custom'] = $form_state['values']['additional_settings']['modes']['view_modes_custom'];
438
  }
439
}
440

    
441
/**
442
 * Change a layout for a given entity.
443
 *
444
 * @param $entity_type
445
 *   The name of the entity.
446
 * @param $bundle
447
 *   The name of the bundle.
448
 * @param $view_mode
449
 *   The name of the view mode.
450
 */
451
function ds_field_ui_layout_change($form, $form_state, $entity_type = '', $bundle = '', $view_mode = '', $new_layout = '') {
452

    
453
  $old_layout = NULL;
454
  $all_layouts = ds_get_layout_info();
455

    
456
  if (!empty($entity_type) && !empty($bundle) && !empty($view_mode)) {
457
    $old_layout = ds_get_layout($entity_type, $bundle, $view_mode, FALSE);
458
  }
459

    
460
  if ($old_layout && isset($all_layouts[$new_layout])) {
461

    
462
    $new_layout_key = $new_layout;
463
    $new_layout = $all_layouts[$new_layout];
464

    
465
    $form['#entity_type'] = $entity_type;
466
    $form['#bundle'] = $bundle;
467
    $form['#view_mode'] = $view_mode;
468
    $form['#old_layout'] = $old_layout;
469
    $form['#new_layout'] = $new_layout;
470
    $form['#new_layout_key'] = $new_layout_key;
471
    $form['#export_id'] = $entity_type . '|' . $bundle . '|' . $view_mode;
472

    
473
    $form['info'] = array(
474
      '#markup' => t('You are changing from %old to %new layout for !bundle in !view_mode view mode.', array('%old' => $old_layout['label'], '%new' => $new_layout['label'], '!bundle' => $bundle, '!view_mode' => $view_mode)),
475
      '#prefix' => "<div class='change_ds_layout_info'>",
476
      '#suffix' => "</div>",
477
    );
478

    
479
    // Old region options.
480
    $regions = array();
481
    foreach ($old_layout['regions'] as $key => $title) {
482
      $regions[$key] = $title;
483
    }
484

    
485
    // Let other modules alter the regions.
486
    // For old regions.
487
    $context = array(
488
      'entity_type' => $entity_type,
489
      'bundle' => $bundle,
490
      'view_mode' => $view_mode,
491
    );
492
    $region_info = array(
493
      'region_options' => $regions,
494
    );
495
    drupal_alter('ds_layout_region', $context, $region_info);
496
    $regions = $region_info['region_options'];
497
    $form['#old_layout']['regions'] = $regions;
498

    
499
    // For new regions.
500
    $region_info = array(
501
      'region_options' => $new_layout['regions'],
502
    );
503
    drupal_alter('ds_layout_region', $context, $region_info);
504
    $new_layout['regions'] = $region_info['region_options'];
505
    $form['#new_layout']['regions'] = $new_layout['regions'];
506

    
507
    // Display the region options
508
    $selectable_regions = array('' => t('- None -')) + $new_layout['regions'];
509
    $form['regions_pre']['#markup'] = '<div class="ds-layout-regions">';
510
    foreach ($regions as $region => $region_title) {
511
      $form['region_' . $region] = array(
512
        '#type' => 'container',
513
      );
514
      $form['region_' . $region]['ds_label_' . $region] = array(
515
        '#markup' => 'Fields in <span class="change_ds_layout_old_region"> ' . $region_title . '</span> go into',
516
      );
517
      $form['region_' . $region]['ds_' . $region] = array(
518
        '#type' => 'select',
519
        '#options' => $layout_options = $selectable_regions,
520
        '#default_value' => $region,
521
      );
522
    }
523
    $form['regions_post']['#markup'] = '</div>';
524

    
525
    // Show previews from old and new layouts
526
    $form['preview'] = array(
527
      '#type' => 'container',
528
      '#prefix' => '<div class="ds-layout-preview"/>',
529
      '#suffix' => '</div>',
530
    );
531

    
532
    $fallback_image = drupal_get_path('module', 'ds') . '/images/preview.png';
533
    $old_image = (isset($old_layout['image']) &&  !empty($old_layout['image'])) ? $old_layout['path'] . '/' . $old_layout['layout'] . '.png' : $fallback_image;
534
    if (isset($old_layout['panels']) && !empty($old_layout['panels']['icon'])) {
535
      $old_image = $old_layout['panels']['path'] . '/' . $old_layout['panels']['icon'];
536
    }
537
    $new_image = (isset($new_layout['image']) &&  !empty($new_layout['image'])) ? $new_layout['path'] . '/' . $new_layout_key . '.png' : $fallback_image;
538
    if (isset($new_layout['panels']) && !empty($new_layout['panels']['icon'])) {
539
      $new_image = $new_layout['panels']['path'] . '/' . $new_layout['panels']['icon'];
540
    }
541
    $arrow = drupal_get_path('module', 'ds') . '/images/arrow.png';
542

    
543
    $form['preview']['old_layout'] = array(
544
      '#markup' => '<div class="ds-layout-preview-image"><img src="' . base_path() . $old_image . '"/></div>',
545
    );
546
    $form['preview']['arrow'] = array(
547
      '#markup' => '<div class="ds-layout-preview-arrow"><img src="' . base_path() . $arrow . '"/></div>',
548
    );
549
    $form['preview']['new_layout'] = array(
550
      '#markup' => '<div class="ds-layout-preview-image"><img src="' . base_path() . $new_image . '"/></div>',
551
    );
552
    $form['#attached']['css'][] = drupal_get_path('module', 'ds') . '/css/ds.admin.css';
553

    
554
    // Submit button
555
    $form['actions'] = array('#type' => 'actions');
556
    $form['actions']['submit'] = array(
557
      '#type' => 'submit',
558
      '#value' => t('Save'),
559
      '#prefix' => '<div class="ds-layout-change-save">',
560
      '#suffix' => '</div>',
561
    );
562
  }
563
  else {
564
    $form['nothing'] = array('#markup' => t('No valid configuration found.'));
565
  }
566

    
567
  return $form;
568
}
569

    
570
/**
571
 * Submit callback: save the layout change.
572
 */
573
function ds_field_ui_layout_change_submit($form, &$form_state) {
574

    
575
  // Prepare some variables.
576
  $old_layout = $form['#old_layout'];
577
  $new_layout = $form['#new_layout'];
578
  $new_layout_key = $form['#new_layout_key'];
579
  $entity_type = $form['#entity_type'];
580
  $bundle = $form['#bundle'];
581
  $view_mode = $form['#view_mode'];
582

    
583
  // Create new record.
584
  $record = new stdClass();
585
  $record->id = $form['#export_id'];
586
  $record->entity_type = $entity_type;
587
  $record->bundle = $bundle;
588
  $record->view_mode = $view_mode;
589
  $record->layout = $new_layout_key;
590
  $record->settings = $old_layout['settings'];
591
  unset($record->settings['regions']);
592
  unset($record->settings['fields']);
593

    
594
  // map old regions to new ones
595
  foreach ($old_layout['regions'] as $region => $region_title) {
596
    $new_region = $form_state['values']['ds_' . $region];
597
    if ($new_region != '' && isset($old_layout['settings']['regions'][$region])) {
598
      foreach ($old_layout['settings']['regions'][$region] as $field_key => $field) {
599
        if (!isset($record->settings['regions'][$new_region])) {
600
          $record->settings['regions'][$new_region] = array();
601
        }
602
        $record->settings['regions'][$new_region][] = $field;
603
        $record->settings['fields'][$field] = $new_region;
604
      }
605
    }
606
  }
607

    
608
  // Remove old record.
609
  db_delete('ds_layout_settings')
610
    ->condition('entity_type', $entity_type)
611
    ->condition('bundle', $bundle)
612
    ->condition('view_mode', $view_mode)
613
    ->execute();
614

    
615
  // Save new record.
616
  drupal_write_record('ds_layout_settings', $record);
617

    
618
  // Clear entity info cache.
619
  cache_clear_all('entity_info', 'cache', TRUE);
620

    
621
  // Show message.
622
  drupal_set_message(t('The layout change has been saved.'));
623
}
624

    
625
/**
626
 * Save the layout settings from the 'Manage display' screen.
627
 */
628
function ds_field_ui_layouts_save($form, &$form_state) {
629
  $weight = 0;
630

    
631
  // Get default values.
632
  $entity_type = $form['#entity_type'];
633
  $bundle = $form['#bundle'];
634
  $view_mode = $form['#view_mode'];
635

    
636
  // Determine layout variables.
637
  $layout = $form_state['values']['additional_settings']['layout'];
638
  $old_layout = $form_state['values']['additional_settings']['old_layout'];
639
  $new_layout = ($layout != $old_layout) || empty($old_layout);
640

    
641
  // Save layout and add regions if necessary.
642
  $record = new stdClass;
643
  $record->id = $form['#export_id'];
644
  $record->entity_type = $entity_type;
645
  $record->bundle = $bundle;
646
  $record->view_mode = $view_mode;
647
  $record->layout = $layout;
648
  $record->settings = array();
649

    
650
  $form_state['layout_saved'] = FALSE;
651

    
652
  // Remove old layout if necessary.
653
  if ($new_layout && !empty($old_layout)) {
654
    db_delete('ds_layout_settings')
655
      ->condition('entity_type', $entity_type)
656
      ->condition('bundle', $bundle)
657
      ->condition('view_mode', $view_mode)
658
      ->execute();
659
  }
660

    
661
  if ($new_layout && !empty($layout)) {
662

    
663
    $form_state['layout_saved'] = TRUE;
664

    
665
    // Save new layout.
666
    $record->settings = $record->settings;
667

    
668
    // Let other modules alter the layout settings.
669
    drupal_alter('ds_layout_settings', $record, $form_state);
670

    
671
    // Move current visible fields into a default region, so
672
    // we keep their current settings.
673
    $layouts = ds_get_layout_info();
674
    $sl = $layouts[$layout];
675
    $first_region = key($sl['regions']);
676
    $record->settings['regions'] = array();
677
    $record->settings['fields'] = array();
678
    $record->settings['classes'] = array();
679
    $record->settings['wrappers'] = array();
680
    $record->settings['layout_wrapper'] = 'div';
681
    $record->settings['layout_attributes'] = '';
682
    $record->settings['layout_attributes_merge'] = variable_get('ds_layout_attributes_merge', TRUE);
683
    $record->settings['layout_link_attribute'] = FALSE;
684
    $record->settings['layout_link_custom'] = '';
685
    $fields = _ds_sort_fields($form_state['values']['fields'], 'weight');
686
    foreach ($fields as $field_key => $field) {
687

    
688
      // Ignore new fieldgroup, new field or existing field.
689
      if (in_array($field_key, array('_add_new_field', '_add_existing_field', '_add_new_group'))) {
690
        continue;
691
      }
692

    
693
      // Can either be form or display.
694
      if ((isset($field['type']) && $field['type'] != 'hidden') || $record->view_mode == 'form') {
695
        $record->settings['regions'][$first_region][$weight++] = $field_key;
696
        $record->settings['fields'][$field_key] = $first_region;
697
      }
698
    }
699
    // In case this is the full node view mode and if the comment module
700
    // is enabled for this content type, add it as well.
701
    if ($record->entity_type == 'node' && $record->view_mode == 'full' && module_exists('comment')) {
702
      $record->settings['regions'][$first_region][] = 'comments';
703
      $record->settings['fields']['comments'] = $first_region;
704
    }
705

    
706
    // Save the record.
707
    drupal_write_record('ds_layout_settings', $record);
708
  }
709
  // Update existing layout.
710
  elseif (!empty($layout)) {
711

    
712
    $form_state['layout_saved'] = TRUE;
713

    
714
    $fields = _ds_sort_fields($form_state['values']['fields'], 'weight');
715

    
716
    foreach ($fields as $key => $field) {
717

    
718
      // Make sure we need to save anything for this field.
719
      if (_ds_field_valid($key, $field, $form_state, $view_mode)) {
720
        continue;
721
      }
722

    
723
      if (!isset($record->settings['regions'][$field['region']])) {
724
        $record->settings['regions'][$field['region']] = array();
725
      }
726
      $record->settings['regions'][$field['region']][$weight++] = $key;
727
      $record->settings['fields'][$key] = $field['region'];
728

    
729
      // Save limit.
730
      $limit = isset($field['format']['limit']) ? trim($field['format']['limit']) : '';
731
      if (is_numeric($limit) || $limit === 'delta') {
732
        $record->settings['limit'][$key] = $limit;
733
      }
734
    }
735

    
736
    // Save the region classes.
737
    $record->settings['classes'] = array();
738
    foreach (array_keys($form['fields']['#regions']) as $region) {
739

    
740
      // Ignore hidden region.
741
      if ($region == 'hidden') {
742
        continue;
743
      }
744

    
745
      if (isset($form_state['values']['additional_settings']['layout_class'])) {
746
        $record->settings['classes']['layout_class'] = $form_state['values']['additional_settings']['layout_class'];
747
      }
748

    
749
      // Additional classes on regions.
750
      if (isset($form_state['values']['additional_settings'][$region])) {
751
        // Do not save empty string.
752
        $classes = is_array($form_state['values']['additional_settings'][$region]) ? implode(' ', $form_state['values']['additional_settings'][$region]) : array();
753
        if (!empty($classes)) {
754
          $record->settings['classes'][$region] = $form_state['values']['additional_settings'][$region];
755
        }
756
      }
757

    
758
      // Additional wrappers on regions.
759
      if (isset($form_state['values']['additional_settings']['region_wrapper'][$region])) {
760
        $record->settings['wrappers'][$region] = $form_state['values']['additional_settings']['region_wrapper'][$region];
761
      }
762
    }
763

    
764
    // Layout wrapper
765
    $record->settings['layout_wrapper'] = $form_state['values']['additional_settings']['region_wrapper']['layout_wrapper'];
766
    $record->settings['layout_attributes'] = filter_xss_admin($form_state['values']['additional_settings']['region_wrapper']['layout_attributes']);
767
    $record->settings['layout_attributes_merge'] = $form_state['values']['additional_settings']['region_wrapper']['layout_attributes_merge'];
768

    
769
    // Link attribute.
770
    $record->settings['layout_link_attribute'] = $form_state['values']['additional_settings']['region_wrapper']['layout_link_attribute'];
771
    $record->settings['layout_link_custom'] = $form_state['values']['additional_settings']['region_wrapper']['layout_link_custom'];
772

    
773
    $record->settings = $record->settings;
774

    
775
    // Let other modules alter the layout settings.
776
    drupal_alter('ds_layout_settings', $record, $form_state);
777

    
778
    $l = $form['#ds_layout'];
779
    if ($l->export_type == 2) {
780
      drupal_write_record('ds_layout_settings', $record);
781
    }
782
    else {
783
      drupal_write_record('ds_layout_settings', $record, array('id'));
784
    }
785

    
786
    // Clear entity info cache.
787
    cache_clear_all('entity_info', 'cache', TRUE);
788
  }
789
}
790

    
791
/**
792
 * Form validation handler for _ds_field_ui_fields().
793
 */
794
function ds_field_ui_fields_validate($form, &$form_state) {
795
  foreach (element_children($form['fields']) as $key) {
796
    if (isset($form_state['values']['fields'][$key]['settings_edit_form'])) {
797
      $settings = isset($form_state['values']['fields'][$key]['settings_edit_form']['settings']['ft']) ? $form_state['values']['fields'][$key]['settings_edit_form']['settings']['ft'] : array();
798
      if (!empty($settings)) {
799
        $merge = isset($form_state['formatter_settings'][$key]['ft']) ? $form_state['formatter_settings'][$key]['ft'] : array();
800
        $form_state['formatter_settings'][$key]['ft'] = array_merge($merge, $settings);
801
      }
802
    }
803
  }
804
}
805

    
806
/**
807
 * Save the field settings from the 'Manage display' screen.
808
 */
809
function ds_field_ui_fields_save($form, &$form_state) {
810
  // Setup some variables.
811
  $entity_type = $form['#entity_type'];
812
  $bundle = $form['#bundle'];
813
  $view_mode = $form['#view_mode'];
814

    
815
  // Delete previous field configuration configuration.
816
  db_delete('ds_field_settings')
817
    ->condition('entity_type', $entity_type)
818
    ->condition('bundle', $bundle)
819
    ->condition('view_mode', $view_mode)
820
    ->execute();
821

    
822
  if (empty($form_state['layout_saved'])) {
823
    return;
824
  }
825

    
826
  $field_settings = array();
827

    
828
  // Save settings for each field.
829
  $fields = $form['#ds_fields'];
830
  foreach ($fields as $key => $field) {
831

    
832
    // Field settings.
833
    $field_values = $form_state['values']['fields'][$field];
834

    
835
    // In case the region is hidden, do not save.
836
    if (isset($field_values['region']) && $field_values['region'] == 'hidden') {
837
      continue;
838
    }
839

    
840
    // Build settings.
841
    $settings = array();
842
    $settings['weight'] = $field_values['weight'];
843
    $settings['label'] = $field_values['label'];
844
    $settings['format'] = $field_values['format']['type'];
845

    
846
    // Any formatter settings.
847
    if (isset($form_state['formatter_settings'][$field])) {
848
      $settings['formatter_settings'] = $form_state['formatter_settings'][$field];
849
    }
850

    
851
    $field_settings[$field] = $settings;
852
  }
853

    
854
  // Allow other modules to modify the field settings before they get saved.
855
  drupal_alter('ds_field_settings', $field_settings, $form, $form_state);
856

    
857
  // Save the record.
858
  if (!empty($field_settings)) {
859
    $record = new stdClass;
860
    $record->id = $form['#export_id'];
861
    $record->entity_type = $entity_type;
862
    $record->bundle = $bundle;
863
    $record->view_mode = $view_mode;
864
    $record->settings = $field_settings;
865
    drupal_write_record('ds_field_settings', $record);
866
  }
867

    
868
  // Clear the ds_fields cache.
869
  cache_clear_all('ds_fields:', 'cache', TRUE);
870
  cache_clear_all('ds_field_settings', 'cache');
871
}
872

    
873
/**
874
 * Clone a fields layout.
875
 */
876
function ds_field_ui_layout_clone($form, &$form_state) {
877

    
878
  $clone = $form_state['values']['additional_settings']['clone'];
879
  $entity_type = $form['#entity_type'];
880
  $bundle = $form['#bundle'];
881
  $view_mode = $form['#view_mode'];
882

    
883
  ctools_include('export');
884
  $layout = ctools_export_crud_load('ds_layout_settings', $clone);
885

    
886
  // Delete previous layout settings configuration.
887
  db_delete('ds_layout_settings')
888
    ->condition('entity_type', $entity_type)
889
    ->condition('bundle', $bundle)
890
    ->condition('view_mode', $view_mode)
891
    ->execute();
892

    
893
  // Delete previous field configuration configuration.
894
  db_delete('ds_field_settings')
895
    ->condition('entity_type', $entity_type)
896
    ->condition('bundle', $bundle)
897
    ->condition('view_mode', $view_mode)
898
    ->execute();
899

    
900
  // Save new layout record for ds.
901
  if ($layout) {
902
    $record = new stdClass();
903
    $record->id = $form['#export_id'];
904
    $record->entity_type = $entity_type;
905
    $record->bundle = $bundle;
906
    $record->view_mode = $view_mode;
907
    $record->layout = $layout->layout;
908
    $record->settings = $layout->settings;
909

    
910
    // Let other modules alter the layout settings.
911
    drupal_alter('ds_layout_settings', $record, $form_state);
912

    
913
    // Save layout record.
914
    drupal_write_record('ds_layout_settings', $record);
915

    
916
    // Copy the view mode settings.
917
    list($ce, $cb, $cv) = explode('|', $clone);
918
    _ds_field_ui_clone_view_mode_settings($entity_type, $bundle, $view_mode, $cv);
919

    
920
    // Clear entity info cache.
921
    cache_clear_all('entity_info', 'cache', TRUE);
922

    
923
    // Show message.
924
    drupal_set_message(t('The layout has been cloned.'));
925

    
926
  }
927
  else {
928
    drupal_set_message(t('No layout was cloned.'));
929
  }
930
}
931

    
932
/**
933
 * Populates display settings for a new view mode from the another view mode.
934
 *
935
 * This is almost a straight copy from Field UI, but with the addition
936
 * that we can pass the view mode from which we want to clone from.
937
 */
938
function _ds_field_ui_clone_view_mode_settings($entity_type, $bundle, $view_mode, $copy_view_mode) {
939

    
940
  $settings = field_bundle_settings($entity_type, $bundle);
941

    
942
  // Update display settings for field instances.
943
  $instances = field_read_instances(array('entity_type' => $entity_type, 'bundle' => $bundle));
944
  foreach ($instances as $instance) {
945
    // If this field instance has display settings defined for this view mode,
946
    // respect those settings.
947
    if (isset($instance['display'][$copy_view_mode])) {
948
      $instance['display'][$view_mode] = $instance['display'][$copy_view_mode];
949
      field_update_instance($instance);
950
    }
951
  }
952

    
953
  // Update display settings for 'extra fields'.
954
  foreach (array_keys($settings['extra_fields']['display']) as $name) {
955
    if (isset($settings['extra_fields']['display'][$name][$copy_view_mode])) {
956
      $settings['extra_fields']['display'][$name][$view_mode] = $settings['extra_fields']['display'][$name][$copy_view_mode];
957
    }
958
  }
959

    
960
  // Save the settings.
961
  field_bundle_settings($entity_type, $bundle, $settings);
962
}
963

    
964
/**
965
 * Implements hook_field_formatter_settings_form().
966
 */
967
function ds_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
968

    
969
  $display = $instance['display'][$view_mode];
970
  $settings = $display['settings'];
971

    
972
  // Taxonomy view modes.
973
  if ($display['type'] === 'ds_taxonomy_view_mode') {
974
    $options = array();
975
    $view_modes = ds_entity_view_modes('taxonomy_term');
976
    foreach ($view_modes as $key => $info) {
977
      $options[$key] = $info['label'];
978
    }
979
    $element['taxonomy_term_reference_view_mode'] = array(
980
      '#title'   => t('View mode'),
981
      '#type'    => 'select',
982
      '#options' => $options,
983
      '#default_value' => $settings['taxonomy_term_reference_view_mode'],
984
    );
985
    return $element;
986
  }
987

    
988
  // Taxonomy separated.
989
  if ($display['type'] === 'ds_taxonomy_separator' || $display['type'] == 'ds_taxonomy_separator_localized') {
990
    $element['taxonomy_term_link'] = array(
991
      '#title' => t('Link to term'),
992
      '#type' => 'checkbox',
993
      '#size' => 10,
994
      '#default_value' => $settings['taxonomy_term_link'],
995
    );
996
    $separators = array(
997
      ' ' => t('space'),
998
      ', ' => t('comma'),
999
      ' - ' => t('dash'),
1000
      ' / ' => t('slash'),
1001
    );
1002
    drupal_alter('ds_taxonomy_term_separators', $separators);
1003
    $element['taxonomy_term_separator'] = array(
1004
      '#title' => t('Separator'),
1005
      '#type' => 'select',
1006
      '#options' => $separators,
1007
      '#default_value' => $settings['taxonomy_term_separator'],
1008
      '#states' => array(
1009
        'visible' => array(
1010
          'select[name="fields[field_tags][settings_edit_form][settings][taxonomy_term_list]"]' => array('value' => 'separated_list'),
1011
        ),
1012
      ),
1013
    );
1014
    return $element;
1015
  }
1016
}
1017

    
1018
/**
1019
 * Implements hook_field_formatter_settings_summary().
1020
 */
1021
function ds_field_formatter_settings_summary($field, $instance, $view_mode) {
1022
  $summary = '';
1023
  $display = $instance['display'][$view_mode];
1024
  $settings = $display['settings'];
1025

    
1026
  if ($display['type'] === 'ds_taxonomy_view_mode') {
1027
    $entity_info = entity_get_info('taxonomy_term');
1028
    $modes = $entity_info['view modes'];
1029
    $mode = $modes[$settings['taxonomy_term_reference_view_mode']]['label'];
1030
    $summary = t('View mode: %mode', array('%mode' => $mode));
1031
  }
1032

    
1033
  if ($display['type'] === 'ds_taxonomy_separator' || $display['type'] == 'ds_taxonomy_separator_localized') {
1034
    $separators = array(
1035
      ' ' => t('space'),
1036
      ', ' => t('comma'),
1037
      ' - ' => t('dash'),
1038
      ' / ' => t('slash'),
1039
    );
1040
    drupal_alter('ds_taxonomy_term_separators', $separators);
1041
    $summary .= t('Separated by !sep', array('!sep' => $separators[$settings['taxonomy_term_separator']]));
1042
    $summary .= $settings['taxonomy_term_link'] ? ', ' . t('linked') : ', ' . t('not linked');
1043
  }
1044

    
1045
  return $summary;
1046
}
1047

    
1048
/**
1049
 * Creates a summary for the field format configuration summary.
1050
 *
1051
 * @param $field
1052
 *   The configuration of the field.
1053
 *
1054
 * @return $summary
1055
 *   An markup array.
1056
 */
1057
function ds_field_settings_summary($field, $form_state, $form, $view_mode) {
1058

    
1059
  $summary = '';
1060

    
1061
  // Not all fields have settings.
1062
  if (isset($field['properties']['settings'])) {
1063
    $summary = module_invoke($field['module'], 'ds_field_format_summary', $field);
1064
  }
1065

    
1066
  if (module_exists('ds_extras') && variable_get('ds_extras_field_template', FALSE)) {
1067
    module_load_include('inc', 'ds_extras', 'includes/ds_extras.admin');
1068

    
1069
    // Field template summary
1070
    if (!in_array($field['field_type'], array(DS_FIELD_TYPE_IGNORE, DS_FIELD_TYPE_PREPROCESS))) {
1071
      $functions = module_invoke_all('ds_field_theme_functions_info');
1072
      $default_field_function = variable_get('ft-default', 'theme_field');
1073
      $field_function = isset($form_state['formatter_settings'][$field['name']]['ft']['func']) ? $form_state['formatter_settings'][$field['name']]['ft']['func'] : $default_field_function;
1074

    
1075
      $summary .= 'Field template: ' . check_plain($functions[$field_function]) . '<br />';
1076
    }
1077
  }
1078

    
1079
  if (!empty($form_state['complete form'])) {
1080
    $formatter_name = $form_state['complete form']['fields'][$field['name']]['format']['type']['#value'];
1081
  }
1082
  else {
1083
    $formatter_name = $form['fields'][$field['name']]['format']['type']['#default_value'];
1084
  }
1085

    
1086
  // Allow other modules to alter the formatter summary.
1087
  $context = array(
1088
    'formatter' => $formatter_name,
1089
    'field' => $field,
1090
    'instance' => array(
1091
      'display' => array(
1092
        $view_mode => array(
1093
          'label' => '',
1094
          'type' => '',
1095
          'weight' => '',
1096
          'settings' => isset($field['formatter_settings']) ? $field['formatter_settings'] : array(),
1097
          'module' => '',
1098
        )
1099
      )
1100
    ),
1101
    'view_mode' => $view_mode,
1102
    'ds' => TRUE,
1103
  );
1104
  drupal_alter('field_formatter_settings_summary', $summary, $context);
1105

    
1106
  if (empty($summary)) {
1107
    return NULL; // no summary return nothing
1108
  }
1109

    
1110
  return array(
1111
    '#markup' => '<div class="field-formatter-summary">' . $summary . '</div>',
1112
    '#cell_attributes' => array('class' => array('field-formatter-summary-cell')),
1113
  );
1114
}
1115

    
1116
/**
1117
 * Creates a form for Display Suite fields.
1118
 * .
1119
 * @param $field
1120
 *   The field definition.
1121
 *
1122
 * @return $form
1123
 *   A form definition.
1124
 */
1125
function ds_field_settings_form($field, &$form_state, $entity_form, $view_mode) {
1126
  $form = module_invoke($field['module'], 'ds_field_settings_form', $field);
1127

    
1128
  // Add field template settings to every field if enabled.
1129
  if (module_exists('ds_extras') && variable_get('ds_extras_field_template', FALSE)) {
1130
    $context = array(
1131
      'instance' => array(
1132
        'entity_type' => $field['entity_type'],
1133
        'bundle' => $field['bundle'],
1134
        'field_name' => $field['name'],
1135
      ),
1136
      'view_mode' => $field['view_mode'],
1137
    );
1138

    
1139
    // Load the formatter settings form
1140
    module_load_include('inc', 'ds_extras', 'includes/ds_extras.admin');
1141
    // Protect against empty $form.
1142
    if (!is_array($form)) $form = array();
1143
    if (!in_array($field['field_type'], array(DS_FIELD_TYPE_IGNORE, DS_FIELD_TYPE_PREPROCESS))) {
1144
      ds_extras_field_template_settings_form($form, $form_state, $context);
1145
    }
1146
    else {
1147
      $form['#markup'] = t('This field does not support Field templates.');
1148
    }
1149
  }
1150

    
1151
  $formatter_name = $form_state['complete form']['fields'][$field['name']]['format']['type']['#value'];
1152

    
1153
  // Allow other modules to alter the formatter settings form.
1154
  $context = array(
1155
    'ds' => TRUE,
1156
    'formatter' => $formatter_name,
1157
    'field' => $field,
1158
    'instance' => array(
1159
      'label' => $field['title'],
1160
      'bundle' => $field['bundle'],
1161
      'entity_type' => $field['entity_type'],
1162
      'display' => array(
1163
        'default' => array(
1164
          'settings' => isset($field['formatter_settings']) ? $field['formatter_settings'] : array(),
1165
        ),
1166
      ),
1167
    ),
1168
    'view_mode' => $view_mode,
1169
    'form' => $entity_form,
1170
    'form_state' => $form_state,
1171
  );
1172
  drupal_alter('field_formatter_settings_form', $form, $context);
1173

    
1174
  return $form;
1175
}
1176

    
1177
/**
1178
 * Implements hook_ds_field_format_summary().
1179
 */
1180
function ds_ds_field_format_summary($field) {
1181
  $summary = '';
1182
  $settings = isset($field['formatter_settings']) ? $field['formatter_settings'] : $field['properties']['default'];
1183
  $functions = module_invoke_all('ds_field_theme_functions_info');
1184
  foreach ($settings as $key => $value) {
1185

    
1186
    // Ignore Field Formatter conditions.
1187
    if ($key == 'conditions') {
1188
      continue;
1189
    }
1190

    
1191
    if ($key == 'ctools') {
1192
      $conf = unserialize($value);
1193
      $summary .= t('Type: !type', array('!type' => check_plain(drupal_ucfirst(str_replace('_', ' ', $conf['subtype'])))));
1194
    }
1195
    elseif ($key == 'ft' || is_array($value)) {
1196
      // Do nothing
1197
    }
1198
    elseif (!empty($value)) {
1199
      $value = is_numeric($value) ? ($value ? t('Yes') : t('No')) : check_plain($value);
1200
      $summary .= ' ' . str_replace('_', ' ', drupal_ucfirst(check_plain($key))) . ': ' . check_plain($value) . '<br />';
1201
    }
1202
  }
1203

    
1204
  if (empty($summary) && ($field['field_type'] == DS_FIELD_TYPE_CTOOLS)) {
1205
    $summary .= t('Not configured yet.') . '<br />';
1206
  }
1207

    
1208
  return $summary;
1209
}
1210

    
1211
/**
1212
 * Implements hook_ds_field_settings_form().
1213
 */
1214
function ds_ds_field_settings_form($field) {
1215
  $form = array();
1216

    
1217
  $settings = !empty($field['formatter_settings']) ? $field['formatter_settings'] : (!empty($field['properties']['default']) ? $field['properties']['default'] : array());
1218

    
1219
  if (empty($field['properties']['settings'])) {
1220
    return $form;
1221
  }
1222

    
1223
  foreach ($field['properties']['settings'] as $key => $value) {
1224

    
1225
    switch ($value['type']) {
1226

    
1227
      case 'textfield':
1228
        $form[$key] = array(
1229
          '#type' => 'textfield',
1230
          '#title' => str_replace('_', ' ', check_plain(drupal_ucfirst($key))),
1231
          '#default_value' => isset($settings[$key]) ? $settings[$key] : '',
1232
          '#size' => 40,
1233
          '#description' => isset($value['description']) ? check_plain($value['description']) : '',
1234
        );
1235
        break;
1236

    
1237
      case 'select':
1238
        $form[$key] = array(
1239
          '#type' => 'select',
1240
          '#title' => check_plain(drupal_ucfirst($key)),
1241
          '#default_value' => isset($settings[$key]) ? $settings[$key] : '',
1242
          '#options' => $value['options'],
1243
          '#description' => isset($value['description']) ? check_plain($value['description']) : '',
1244
        );
1245
        break;
1246

    
1247
      case 'checkbox':
1248
        $form[$key] = array(
1249
          '#type' => 'checkbox',
1250
          '#title' => str_replace('_', ' ', check_plain(drupal_ucfirst($key))),
1251
          '#default_value' => isset($settings[$key]) ? $settings[$key] : '',
1252
          '#description' => isset($value['description']) ? check_plain($value['description']) : '',
1253
        );
1254
        break;
1255

    
1256
      case 'ctools':
1257
        ctools_include('modal');
1258
        ctools_include('object-cache');
1259
        ctools_modal_add_js();
1260
        $form[$key] = array(
1261
          '#type' => 'hidden',
1262
          '#default_value' => isset($settings[$key]) ? $settings[$key] : '',
1263
          '#weight' => 2,
1264
        );
1265
        $action = 'add';
1266
        $args = '';
1267
        $conf = array();
1268
        $query = array('query' => array('selection' => 1));
1269
        $title = t('Select content');
1270
        if (isset($settings[$key])) {
1271
          $query = array();
1272
          $ctools = unserialize($settings['ctools']);
1273
          $type = $ctools['type'];
1274
          $subtype = $ctools['subtype'];
1275
          $args = '/' . $type . '/' . $subtype;
1276
          $action = 'edit';
1277
          $conf = $ctools['conf'];
1278
          $title = t('Edit content');
1279
        }
1280
        $form['select'] = array(
1281
          '#markup' => '<div class="select-content-link">' . l($title, 'admin/structure/ds/fields/manage_ctools/content/' . $action . '/' . $field['entity_type'] . '/' . $field['name'] . $args, array('attributes' => array('class' => array('ctools-use-modal'))) + $query) . '</div>',
1282
          '#weight' => -10,
1283
        );
1284
        $form['load_terms'] = array(
1285
          '#type' => 'checkbox',
1286
          '#title' => t('Load terms'),
1287
          '#description' => t('Toggle if you are embedding a view with term fields.'),
1288
          '#default_value' => isset($settings['load_terms']) ? $settings['load_terms'] : '',
1289
          '#weight' => -1,
1290
        );
1291
        $form['show_title']['#weight'] = 0;
1292
        $form['title_wrapper']['#weight'] = 1;
1293
        ctools_object_cache_set($field['name'], $field['name'], $conf);
1294
        break;
1295
    }
1296
  }
1297

    
1298
  return $form;
1299
}
1300

    
1301
/**
1302
 * Add entity contexts.
1303
 */
1304
function ds_get_entity_context($entity_type) {
1305
  ctools_include('context');
1306
  $arguments = array(
1307
    array(
1308
      'keyword' => $entity_type,
1309
      'identifier' => drupal_ucfirst($entity_type) . ' being viewed',
1310
      'id' => 1,
1311
      'name' => 'entity_id:' . $entity_type,
1312
      'settings' => array(),
1313
    ),
1314
  );
1315

    
1316
  return ctools_context_get_placeholders_from_argument($arguments);
1317
}
1318

    
1319
/**
1320
 * Return the configuration settings for the CTools field.
1321
 */
1322
function ds_ctools_content($action = 'add', $entity_type = '', $field_name = '', $type_name = '', $subtype_name = '', $step = NULL) {
1323

    
1324
  ctools_include('modal');
1325
  ctools_include('ajax');
1326
  ctools_include('content');
1327
  ctools_include('object-cache');
1328

    
1329
  $commands = array();
1330
  $content_type = ctools_get_content_type($type_name);
1331
  $subtype = ctools_content_get_subtype($content_type, $subtype_name);
1332

    
1333
  if ($data = ctools_object_cache_get($field_name, $field_name)) {
1334
    $conf = $data;
1335
  }
1336
  else {
1337
    $conf = ctools_content_get_defaults($content_type, $subtype);
1338
  }
1339

    
1340
  $url = 'admin/structure/ds/fields/manage_ctools/content/' . $action . '/' . $entity_type . '/' . $field_name;
1341
  $base_url = $url;
1342
  if (!empty($type_name) && !empty($subtype_name)) {
1343
    $url .= '/' . $type_name . '/' . $subtype_name . '/%step';
1344
  }
1345
  $form_info = array(
1346
    'path' => $url,
1347
    'show cancel' => TRUE,
1348
    'next callback' => 'ds_ctools_content_next',
1349
  );
1350

    
1351
  // Get entity context.
1352
  $contexts = ds_get_entity_context($entity_type);
1353

    
1354
  $form_state = array(
1355
    'contexts' => $contexts,
1356
    'ajax' => TRUE,
1357
    'modal' => TRUE,
1358
    'modal return' => TRUE,
1359
    'field_name' => $field_name,
1360
  );
1361

    
1362
  // Call the content form.
1363
  $output = ctools_content_form($action, $form_info, $form_state, $content_type, $subtype_name, $subtype, $conf, $step);
1364

    
1365
  if (!empty($form_state['complete']) || isset($_GET['dismiss'])) {
1366
    $configuration = array(
1367
      'conf' => $form_state['conf'],
1368
      'type' => $type_name,
1369
      'subtype' => $subtype_name,
1370
    );
1371
    $commands[] = ctools_modal_command_dismiss();
1372
    $commands[] = ajax_command_invoke('input[name="fields[' . $field_name . '][settings_edit_form][settings][ctools]"]', 'dsCtoolsContentConfiguration', array(serialize($configuration)));
1373
    $commands[] = ajax_command_invoke('.select-content-link', 'dsCtoolsContentUpdate', array(serialize($configuration)));
1374
    ctools_object_cache_clear($field_name, $field_name);
1375
  }
1376
  // Content selection
1377
  elseif (!empty($form_state['cancel']) || isset($_GET['selection'])) {
1378
    ctools_object_cache_clear($field_name, $field_name);
1379
    $commands[] = ds_ctools_content_select($contexts, $field_name, $action, $entity_type);
1380
  }
1381
  // No configuration anymore.
1382
  elseif ($output === FALSE && !isset($_GET['dismiss'])) {
1383
    $output = t('No further configuration exists for this content type.<br/><br/><a href="!close_modal" class="use-ajax">Click here to close the modal and save the settings.</a><br/><br/><a href="!new_content" class="use-ajax">Click here to select new content</a>.', array('!new_content' => url($base_url, array('query' => array('selection' => TRUE))), '!close_modal' => url($url, array('query' => array('dismiss' => 1)))));
1384
    $commands[] = ctools_modal_command_display(t('Edit content'), $output);
1385
  }
1386
  // Form render.
1387
  else {
1388
    $commands = ctools_modal_form_render($form_state, $output);
1389
  }
1390

    
1391
  print ajax_render($commands);
1392
  ajax_footer();
1393
  exit;
1394
}
1395

    
1396
/**
1397
 * Handle the 'next' click on the add/edit field form wizard.
1398
 */
1399
function ds_ctools_content_next(&$form_state) {
1400
  ctools_object_cache_set($form_state['field_name'], $form_state['field_name'], $form_state['conf']);
1401
}
1402

    
1403
/**
1404
 * Select content.
1405
 *
1406
 * @param $contexts
1407
 *   A collection of contexts, usually the entity.
1408
 * @param $field_name
1409
 *   The name of the field.
1410
 * @param $action
1411
 *   The name of the action.
1412
 * @param $entity_type
1413
 *   The name of the entity type.
1414
 */
1415
function ds_ctools_content_select($contexts, $field_name, $action, $entity_type) {
1416

    
1417
  // Get content types.
1418
  $content_types = ctools_content_get_available_types($contexts);
1419

    
1420
  $categories = $category_names = $ordered = array();
1421

    
1422
  foreach ($content_types as $type_name => $subtypes) {
1423
    foreach ($subtypes as $subtype_name => $content_type) {
1424
      list($category_key, $category) = ds_ctools_get_category($content_type);
1425

    
1426
      if (empty($categories[$category_key])) {
1427
        $categories[$category_key] = array(
1428
          'title' => $category,
1429
          'content' => array(),
1430
        );
1431
        $category_names[$category_key] = $category;
1432
      }
1433

    
1434
      $content_title = filter_xss_admin($content_type['title']);
1435

    
1436
      // Ensure content with the same title doesn't overwrite each other.
1437
      while (isset($categories[$category_key]['content'][$content_title])) {
1438
        $content_title .= '-';
1439
      }
1440

    
1441
      $categories[$category_key]['content'][$content_title] = $content_type;
1442
      $categories[$category_key]['content'][$content_title]['type_name'] = $type_name;
1443
      $categories[$category_key]['content'][$content_title]['subtype_name'] = $subtype_name;
1444
    }
1445
  }
1446

    
1447
  // Now sort
1448
  natcasesort($category_names);
1449
  foreach ($category_names as $category => $name) {
1450
    $ordered[$category] = $categories[$category];
1451
  }
1452

    
1453
  $left = '';
1454
  $right = '<div class="content">' . t('Content options are divided by category. Please select a category from the left to proceed.') . '</div>';
1455
  foreach ($ordered as $section => $section_content) {
1456
    // Section.
1457
    if ($section == 'root') {
1458
      $section_content['title'] = t('Content');
1459
    }
1460
    $left .= '<div class="section"><a href="" id="' . $section . '" class="section-link">' . $section_content['title'] . '</a></div>';
1461
    // Content.
1462
    $right .= '<div id="' . $section . '-container" class="selection-hide content">';
1463
    $right .= '<h2>' . $section_content['title'] . '</h2>';
1464
    foreach ($section_content['content'] as $key => $value) {
1465
      $right .= '<div class="content-item">';
1466
      $variables = array(
1467
        'path' => ctools_content_admin_icon($value),
1468
      );
1469
      $right .= theme('image', $variables) . '&nbsp;';
1470
      $right .= ctools_ajax_text_button($key, 'admin/structure/ds/fields/manage_ctools/content/' . $action . '/' . $entity_type . '/' . $field_name . '/' . $value['type_name'] . '/' . $value['subtype_name'], $key);
1471
      $right .= '</div>';
1472
    }
1473
    $right .= '</div>';
1474
  }
1475

    
1476
  // Create output.
1477
  $output = '<div id="ctools-content-selection">';
1478
  $output .= '<div id="ds-left">' . $left . '</div>';
1479
  $output .= '<div id="ds-right">' . $right . '</div>';
1480
  $output .= '</div>';
1481

    
1482
  return ctools_modal_command_display(t('Select content'), $output);
1483
}
1484

    
1485
/**
1486
 * Helper function to get the category.
1487
 */
1488
function ds_ctools_get_category($content_type) {
1489
  if (isset($content_type['top level'])) {
1490
    $category = 'root';
1491
  }
1492
  elseif (isset($content_type['category'])) {
1493
    if (is_array($content_type['category'])) {
1494
      list($category, $weight) = $content_type['category'];
1495
    }
1496
    else {
1497
      $category = $content_type['category'];
1498
    }
1499
  }
1500
  else {
1501
    $category = t('Uncategorized');
1502
  }
1503

    
1504
  return array(preg_replace('/[^a-z0-9]/', '-', drupal_strtolower($category)), $category);
1505
}
1506

    
1507
/**
1508
 * Add fake field group value in.
1509
 */
1510
function _ds_field_group_field_ui_fix_notices($form, &$form_state) {
1511
  $field_group = array(
1512
    'group_name' => '',
1513
    'label' => '',
1514
  );
1515
  $form_state['values']['fields']['_add_new_group'] = $field_group;
1516
}
1517

    
1518
/**
1519
 * Add the layouts fieldset on the Field UI screen.
1520
 *
1521
 * @param $entity_type
1522
 *   The name of the entity type.
1523
 * @param $bundle
1524
 *   The name of the bundle
1525
 * @param $view_mode
1526
 *   The name of the view_mode
1527
 * @param $form
1528
 *   A collection of form properties.
1529
 */
1530
function _ds_field_ui_table_layouts($entity_type, $bundle, $view_mode, &$form, $form_state) {
1531

    
1532
  $layout_options = array();
1533
  $ds_layouts = ds_get_layout_info();
1534
  $layout_options = array('' => t('- None -'));
1535
  foreach ($ds_layouts as $key => $layout) {
1536
    $optgroup = 'Display Suite';
1537

    
1538
    // Panels can not be used on Views fields and forms.
1539
    if (!empty($layout['module']) && $layout['module'] == 'panels' && isset($form_state['no_panels'])) {
1540
      continue;
1541
    }
1542

    
1543
    // Create new layout option group.
1544
    if (!empty($layout['module'])) {
1545
      $optgroup = drupal_ucfirst($layout['module']);
1546
    }
1547

    
1548
    if (!isset($layout_options[$optgroup])) {
1549
      $layout_options[$optgroup] = array();
1550
    }
1551

    
1552
    // Stack the layout.
1553
    $layout_options[$optgroup][$key] = $layout['label'];
1554
  }
1555

    
1556
  // If there is only one $optgroup, move it to the root.
1557
  if (count($layout_options) == 2) {
1558
    $options = $layout_options[$optgroup];
1559
    $layout_options = array_merge(array('' => t('- None -')), $options);
1560
  }
1561

    
1562
  // Add layouts form.
1563
  $form['additional_settings']['ds_layouts'] = array(
1564
    '#type' => 'fieldset',
1565
    '#title' => t('Layout for !bundle in !view_mode', array('!bundle' => str_replace('_', ' ', $bundle), '!view_mode' => str_replace('_', ' ', $view_mode))),
1566
    '#collapsible' => TRUE,
1567
    '#collapsed' => FALSE,
1568
    '#parents' => array('additional_settings'),
1569
    '#weight' => -100,
1570
  );
1571

    
1572
  ctools_include('export');
1573
  $layout = new stdClass();
1574
  $ds_layout_settings = ctools_export_crud_load_all('ds_layout_settings');
1575
  if (isset($ds_layout_settings[$form['#export_id']])) {
1576
    $layout = $ds_layout_settings[$form['#export_id']];
1577
  }
1578

    
1579
  if (!empty($layout) && isset($layout->layout) && isset($ds_layouts[$layout->layout]) && empty($layout->disabled)) {
1580
    $layout->settings = $layout->settings;
1581
    $layout->regions = $ds_layouts[$layout->layout]['regions'];
1582
    $form['#ds_layout'] = $layout;
1583
  }
1584

    
1585

    
1586
  // The layout is defined in code.
1587
  if (isset($layout->export_type)) {
1588
    // Enabled/disable the layout.
1589
    if (empty($layout->disabled)) {
1590
      $link = t('This layout is defined in code') . ': ' . l(t('disable layout.'), 'admin/structure/ds/disable/' . $form['#export_id'], array('query' => drupal_get_destination()));
1591
    }
1592
    else {
1593
      $link = t('A layout is defined in code but has been disabled') . ': ' . l(t('enable layout.'), 'admin/structure/ds/enable/' . $form['#export_id'], array('query' => drupal_get_destination()));
1594
    }
1595
    $form['additional_settings']['ds_layouts']['enable_disable'] = array(
1596
      '#markup' => $link,
1597
      '#weight' => 2,
1598
    );
1599

    
1600
    // Overridden in database.
1601
    if ($layout->export_type == 3) {
1602
      $form['additional_settings']['ds_layouts']['revert'] = array(
1603
        '#markup' => l(t('This layout is overridden. Click to revert to default settings.'), 'admin/structure/ds/revert-layout/' . $form['#export_id'], array('query' => drupal_get_destination())),
1604
        '#weight' => 1,
1605
      );
1606
    }
1607
  }
1608

    
1609
  // Load the layout preview form
1610
  $layout->layout_options = $layout_options;
1611
  _ds_field_ui_table_layouts_preview($form, $form_state, $ds_layouts, $layout, $entity_type, $bundle, $view_mode);
1612

    
1613
  if (!empty($layout) && isset($layout->regions)) {
1614

    
1615
    // Add wrappers
1616
    $wrapper_options = array('div' => 'Div', 'span' => 'Span', 'section' => 'Section', 'article' => 'Article', 'header' => 'Header', 'footer' => 'Footer', 'aside' => 'Aside');
1617
    $form['additional_settings']['region_wrapper'] = array(
1618
      '#type' => 'fieldset',
1619
      '#title' => t('Custom wrappers'),
1620
      '#description' => t('Choose a wrapper. All Display Suite layouts support this option.')
1621
    );
1622

    
1623
    // Hide the fieldset in case of the reset layout.
1624
    if ($layout->layout === 'ds_reset') {
1625
      $form['additional_settings']['region_wrapper']['#access'] = FALSE;
1626
    }
1627

    
1628
    foreach (array_keys($layout->regions) as $region) {
1629
      $form['additional_settings']['region_wrapper'][$region] = array(
1630
        '#type' => 'select',
1631
        '#options' => $wrapper_options,
1632
        '#title' => t('Wrapper for @region', array('@region' => $layout->regions[$region])),
1633
        '#default_value' => isset($layout->settings['wrappers'], $layout->settings['wrappers'][$region]) ? $layout->settings['wrappers'][$region] : 'div',
1634
      );
1635
    }
1636

    
1637
    $form['additional_settings']['region_wrapper']['layout_wrapper'] = array(
1638
      '#type' => 'select',
1639
      '#options' => $wrapper_options,
1640
      '#title' => t('Layout wrapper'),
1641
      '#default_value' => isset($layout->settings['layout_wrapper']) ? $layout->settings['layout_wrapper'] : 'div',
1642
      '#weight' => 10,
1643
    );
1644

    
1645
    $form['additional_settings']['region_wrapper']['layout_attributes'] = array(
1646
      '#type' => 'textfield',
1647
      '#title' => t('Layout attributes'),
1648
      '#description' => 'E.g. role="navigation"',
1649
      '#default_value' => isset($layout->settings['layout_attributes']) ? $layout->settings['layout_attributes'] : '',
1650
      '#weight' => 11,
1651
    );
1652
    $form['additional_settings']['region_wrapper']['layout_attributes_merge'] = array(
1653
      '#type' => 'checkbox',
1654
      '#title' => t('Merge other layout attributes'),
1655
      '#description' => 'Certain modules might provide additional attributes for the template wrapper, e.g. RDFa. Disable this option if you prefer to specify these attributes above.',
1656
      '#default_value' => isset($layout->settings['layout_attributes_merge']) ? $layout->settings['layout_attributes_merge'] : variable_get('ds_layout_attributes_merge', TRUE),
1657
      '#weight' => 12,
1658
    );
1659

    
1660
    $form['additional_settings']['region_wrapper']['layout_link_attribute'] = array(
1661
      '#type' => 'select',
1662
      '#options' => array(
1663
        '' => t('No link'),
1664
        'content' => t('Link to content'),
1665
        'custom' => t('Custom'),
1666
        'tokens' => t('Tokens')
1667
      ),
1668
      '#title' => t('Add link'),
1669
      '#description' => t('This will add an onclick attribute on the layout wrapper.'),
1670
      '#default_value' => isset($layout->settings['layout_link_attribute']) ? $layout->settings['layout_link_attribute'] : FALSE,
1671
      '#weight' => 12,
1672
    );
1673

    
1674
    $form['additional_settings']['region_wrapper']['layout_link_custom'] = array(
1675
      '#type' => 'textfield',
1676
      '#title' => t('Custom link'),
1677
      '#description' => t('You may use tokens for this link if you selected tokens.'),
1678
      '#default_value' => isset($layout->settings['layout_link_custom']) ? $layout->settings['layout_link_custom'] : FALSE,
1679
      '#weight' => 13,
1680
      '#states' => array(
1681
        'visible' => array(array(
1682
          ':input[name="additional_settings[region_wrapper][layout_link_attribute]"]' => array(array("value" => "tokens"), array("value" => "custom")),
1683
        )),
1684
      ),
1685
    );
1686

    
1687
    if (module_exists('token')) {
1688
      $form['additional_settings']['region_wrapper']['tokens'] = array(
1689
        '#title' => t('Tokens'),
1690
        '#type' => 'container',
1691
        '#weight' => 14,
1692
        '#states' => array(
1693
          'visible' => array(
1694
            ':input[name="additional_settings[region_wrapper][layout_link_attribute]"]' => array("value" => "tokens"),
1695
          ),
1696
        ),
1697
      );
1698
      $form['additional_settings']['region_wrapper']['tokens']['help'] = array(
1699
        '#theme' => 'token_tree',
1700
        '#token_types' => 'all',
1701
        '#global_types' => FALSE,
1702
        '#dialog' => TRUE,
1703
      );
1704
    }
1705

    
1706

    
1707

    
1708
    // Add extra classes for the regions to have more control while theming.
1709
    $form['additional_settings']['ds_classes'] = array(
1710
      '#type' => 'fieldset',
1711
      '#title' => t('Custom classes'),
1712
      '#collapsible' => TRUE,
1713
      '#collapsed' => TRUE,
1714
      '#parents' => array('additional_settings'),
1715
      '#access' => empty($chosen_layout['flexible']),
1716
    );
1717

    
1718
    $classes_access = (user_access('admin_classes') && module_exists('ds_ui'));
1719
    $classes = _ds_classes();
1720
    if (!empty($classes)) {
1721

    
1722
      $form['additional_settings']['ds_classes']['layout_class'] = array(
1723
        '#type' => 'select',
1724
        '#multiple' => TRUE,
1725
        '#options' => $classes,
1726
        '#title' => t('Class for layout'),
1727
        '#default_value' => isset($layout->settings['classes']['layout_class']) ? $layout->settings['classes']['layout_class'] : '',
1728
      );
1729

    
1730
      foreach (array_keys($layout->regions) as $region) {
1731
        $form['additional_settings']['ds_classes'][$region] = array(
1732
          '#type' => 'select',
1733
          '#multiple' => TRUE,
1734
          '#options' => $classes,
1735
          '#title' => t('Class for @region', array('@region' => $region)),
1736
          '#default_value' => isset($layout->settings['classes'][$region]) ? $layout->settings['classes'][$region] : '',
1737
        );
1738
      }
1739
      if ($classes_access) {
1740
        $form['additional_settings']['ds_classes']['info'] = array('#markup' => l(t('Manage region  and field CSS classes'), 'admin/structure/ds/classes', array('query' => drupal_get_destination())));
1741
      }
1742
    }
1743
    else {
1744
      if ($classes_access) {
1745
        $form['additional_settings']['ds_classes']['info'] = array('#markup' => '<p>' . t('You have not defined any CSS classes which can be used on regions.') . '</p><p>' . l(t('Manage region and field CSS classes'), 'admin/structure/ds/classes', array('query' => drupal_get_destination())) . '</p>');
1746
      }
1747
      else {
1748
        $form['additional_settings']['ds_classes']['#access'] = FALSE;
1749
      }
1750
    }
1751
  }
1752
  else {
1753

    
1754
    if ($view_mode != 'form') {
1755
      // See if we can clone from another view mode.
1756
      $options = array();
1757
      $ds_layout_settings = ctools_export_crud_load_all('ds_layout_settings');
1758
      foreach ($ds_layout_settings as $row) {
1759
        // Do not clone from form layouts.
1760
        if ($row->view_mode == 'form') {
1761
          continue;
1762
        }
1763
        if ($row->entity_type == $entity_type && $row->bundle == $bundle) {
1764
          $name = drupal_ucfirst(str_replace('_', ' ', $row->entity_type)) . ' > ' . drupal_ucfirst(str_replace('_', ' ', $row->bundle)) . ' > ' . drupal_ucfirst(str_replace('_', ' ', $row->view_mode));
1765
          if (!empty($row->disabled)) {
1766
            $name .= ' ' . t('(disabled)');
1767
          }
1768
          $options[$row->id] = $name;
1769
        }
1770
      }
1771

    
1772
      if (!empty($options)) {
1773

    
1774
        // Clone from another layout.
1775
        $form['additional_settings']['ds_clone'] = array(
1776
          '#type' => 'fieldset',
1777
          '#title' => t('Clone layout'),
1778
          '#collapsible' => TRUE,
1779
          '#collapsed' => TRUE,
1780
          '#parents' => array('additional_settings'),
1781
        );
1782
        $form['additional_settings']['ds_clone']['clone'] = array(
1783
          '#title' => t('Select an existing layout to clone.'),
1784
          '#type' => 'select',
1785
          '#options' => $options,
1786
          '#weight' => 20,
1787
        );
1788
        $form['additional_settings']['ds_clone']['clone_submit'] = array(
1789
          '#type' => 'submit',
1790
          '#value' => t('Clone layout'),
1791
          '#submit' => array('ds_field_ui_layout_clone'),
1792
          '#weight' => 21,
1793
        );
1794
      }
1795
    }
1796
  }
1797

    
1798
  $form['additional_settings']['ds_layouts']['id'] = array(
1799
    '#type' => 'value',
1800
    '#value' => isset($layout->id) ? $layout->id : $form['#export_id'],
1801
  );
1802

    
1803
  $form['additional_settings']['ds_layouts']['old_layout'] = array(
1804
    '#type' => 'value',
1805
    '#value' => isset($layout->layout) ? $layout->layout : 0,
1806
  );
1807

    
1808
  // Add validate and submit handlers. Layout needs be first so
1809
  // we can reset the type key for Field API fields.
1810
  $form['#validate'][] = 'ds_field_ui_layouts_validate';
1811
  $submit = $form['#submit'];
1812
  $form['#submit'] = array('ds_field_ui_layouts_save');
1813
  $form['#submit'] = array_merge($form['#submit'], $submit);
1814
}
1815

    
1816
/**
1817
 * Add the layout previews to the Field UI screen.
1818
 *
1819
 * @param $form
1820
 *   A collection of form properties.
1821
 * @param $form_state
1822
 *   The state of the form
1823
 * @param $ds_layouts
1824
 *   Collection of all the layouts
1825
 * @param $layout
1826
 *   Current selected layout
1827
 * @param $entity_type
1828
 *   The name of the entity type.
1829
 * @param $bundle
1830
 *   The name of the bundle
1831
 * @param $view_mode
1832
 *   The name of the view_mode
1833
 */
1834
function _ds_field_ui_table_layouts_preview(&$form, &$form_state, $ds_layouts, $layout, $entity_type, $bundle, $view_mode) {
1835
  $layout_string = '';
1836

    
1837
  $form['additional_settings']['ds_layouts']['layout'] = array(
1838
    '#type' => 'select',
1839
    '#title' => t('Select a layout'),
1840
    '#options' => $layout->layout_options,
1841
    '#default_value' => isset($layout->layout) && empty($layout->disabled) ? $layout->layout : '',
1842
    '#prefix' => '<div class="ds-select-layout">',
1843
    '#suffix' => '</div>',
1844
    '#weight' => -1,
1845
    '#ajax' => array(
1846
      'callback' => 'ds_field_ui_table_layouts_preview_callback',
1847
      'wrapper' => 'ds_layout_wrapper',
1848
    ),
1849
  );
1850
  if (!isset($layout->layout)) {
1851
    $form['additional_settings']['ds_layouts']['layout']['#description'] = t("A layout must be selected to enable Display Suite functionality.");
1852
  }
1853

    
1854
  $form['additional_settings']['ds_layouts']['preview'] = array(
1855
    '#type' => 'container',
1856
    '#prefix' => '<div id="ds_layout_wrapper">',
1857
    '#suffix' => '</div>',
1858
    '#weight' => -3,
1859
  );
1860

    
1861
  if (isset($layout->layout) || isset($form_state['values']['additional_settings']['layout'])) {
1862
    $layout_string = isset($form_state['values']['additional_settings']['layout']) ? $form_state['values']['additional_settings']['layout'] : $layout->layout;
1863
  }
1864

    
1865
  if (!empty($layout_string)) {
1866
    $chosen_layout = $ds_layouts[$layout_string];
1867

    
1868
    if (empty($chosen_layout['flexible'])) {
1869

    
1870
      $selected = '<strong>' . $chosen_layout['label'] . '</strong>';
1871
      $selected .= '<br/>' . t('The default template can be found in %path', array('%path' => $chosen_layout['path']));
1872
      $suggestions = t('Template suggestions') . ':<ul>';
1873
      $suggestions_array = array();
1874

    
1875
      $suggestions_array[0] = $layout_string . '--' . $entity_type;
1876
      $suggestions_array[2] = $layout_string . '--' . $entity_type . '-' . $bundle;
1877
      if (!isset($form_state['no_view_mode_suggestions']) && $view_mode != 'default') {
1878
        $suggestions_array[1] = $layout_string . '--' . $entity_type . '-' . $view_mode;
1879
        $suggestions_array[3] = $layout_string . '--' . $entity_type . '-' . $bundle . '-' . $view_mode;
1880
      }
1881

    
1882
      ksort($suggestions_array);
1883
      $suggestions = '<ul><li>' . implode('.tpl.php</li><li>', $suggestions_array) . '.tpl.php</li></ul>';
1884
    }
1885
    else {
1886
      $suggestions = '';
1887
      $selected = t('You have selected the flexible %layout_label layout.', array('%layout_label' => $chosen_layout['label'], '%path' => $chosen_layout['path']));
1888
    }
1889

    
1890
    if (isset($form_state['values']['additional_settings']['layout']) || (!empty($layout) && isset($layout->regions))) {
1891
      $fallback_image = drupal_get_path('module', 'ds') . '/images/preview.png';
1892
      $current_layout = isset($form_state['values']['additional_settings']['layout']) && (!isset($layout->layout) || $form_state['values']['additional_settings']['layout'] != $layout->layout) ? t('Current layout (after save)') : t('Current layout');
1893
      $image = (isset($chosen_layout['image']) && !empty($chosen_layout['image'])) ? $chosen_layout['path'] . '/' . $layout_string . '.png' : $fallback_image;
1894
      if (isset($chosen_layout['panels']) && !empty($chosen_layout['panels']['icon'])) {
1895
        $image = $chosen_layout['panels']['path'] . '/' . $chosen_layout['panels']['icon'];
1896
      }
1897

    
1898
      $form['additional_settings']['ds_layouts']['preview'] ['title'] = array(
1899
        '#markup' => '<div class="ds-layout-preview-title">' . $current_layout . '</div>',
1900
      );
1901
      $form['additional_settings']['ds_layouts']['preview'] ['image'] = array(
1902
        '#markup' => '<div class="ds-layout-preview-image"><img src="' . base_path() . $image . '"/></div>',
1903
      );
1904
      $form['additional_settings']['ds_layouts']['preview'] ['suggestions'] = array(
1905
        '#markup' => '<div class="ds-layout-preview-suggestion"><p>' . $selected . '</p><p>' . t('!suggestions', array('!suggestions' => strtr($suggestions, '_', '-'))) . '</p></div>',
1906
      );
1907
    }
1908

    
1909
    if (isset($form_state['values']['additional_settings']['layout']) && (!isset($layout->layout) || $form_state['values']['additional_settings']['layout'] != $layout->layout)) {
1910

    
1911
      // Get admin path.
1912
      $admin_path = _field_ui_bundle_admin_path($entity_type, $bundle);
1913
      if ($view_mode != 'form') {
1914
        $admin_path .= '/display';
1915
      }
1916
      else {
1917
        $admin_path .= '/fields';
1918
      }
1919

    
1920
      // If regions aren't set we don't have to move fields.
1921
      if (isset($layout->regions)) {
1922
        $url = 'admin/structure/ds/change-layout/' . $entity_type . '/' . $bundle . '/' . $view_mode . '/' . $layout_string . '?destination=' . $admin_path;
1923
        $form['#validate'][] = 'ds_field_ui_change_layout_validate';
1924
      }
1925
      else {
1926
        $url = $admin_path;
1927
      }
1928

    
1929
      if ($view_mode != 'default' && $view_mode != 'form') {
1930
        $url .= '/' . $view_mode;
1931
      }
1932

    
1933
      $form['layout_changed_url'] = array(
1934
        '#type' => 'value',
1935
        '#value' => $url,
1936
      );
1937

    
1938
      $form['#submit'][] = 'ds_field_ui_change_layout_submit';
1939
    }
1940
  }
1941
}
1942

    
1943
/**
1944
 * Ajax callback for _ds_field_ui_table_layouts_preview().
1945
 */
1946
function ds_field_ui_table_layouts_preview_callback($form, $form_state) {
1947
  return $form['additional_settings']['ds_layouts']['preview'];
1948
}
1949

    
1950
/**
1951
 * Form validation handler for _ds_field_ui_table_layouts_preview().
1952
 */
1953
function ds_field_ui_change_layout_validate(&$form, &$form_state) {
1954
  $key1 = array_search('ds_field_ui_layouts_save', $form['#submit']);
1955
  $key2 = array_search('ds_field_ui_fields_save', $form['#submit']);
1956
  unset($form['#submit'][$key1]);
1957
  unset($form['#submit'][$key2]);
1958
}
1959

    
1960
/**
1961
 * Form submission handler for _ds_field_ui_table_layouts_preview().
1962
 */
1963
function ds_field_ui_change_layout_submit($form, &$form_state) {
1964
  unset($_GET['destination']);
1965
  global $base_url;
1966
  $url = $base_url . '/' . $form_state['values']['layout_changed_url'];
1967
  $form_state['redirect'] = $url;
1968
}
1969

    
1970
/**
1971
 * Add the fields to the Field UI form.
1972
 *
1973
 * @param $entity_type
1974
 *   The name of the entity type.
1975
 * @param $bundle
1976
 *   The name of the bundle
1977
 * @param $view_mode
1978
 *   The name of the view_mode
1979
 * @param $form
1980
 *   A collection of form properties.
1981
 * @param $form_state
1982
 *   A collection of form_state properties.
1983
 */
1984
function _ds_field_ui_fields($entity_type, $bundle, $view_mode, &$form, &$form_state) {
1985

    
1986
  // Do not add the fields if there is no layout.
1987
  if (!isset($form['#ds_layout'])) {
1988
    return;
1989
  }
1990

    
1991
  // Get the fields and put them on the form.
1992
  $fields = ds_get_fields($entity_type, FALSE);
1993

    
1994
  // Ultimate alter on Field UI fields, only used for edge cases.
1995
  $context = array(
1996
    'entity_type' => $entity_type,
1997
    'bundle' => $bundle,
1998
    'view_mode' => $view_mode,
1999
  );
2000
  // Load views file if entity type is not ds_views.
2001
  // We need to cache the hook it's implementing.
2002
  if ($entity_type != 'ds_views' && module_exists('ds_extras') && variable_get('ds_extras_vd', FALSE)) {
2003
    module_load_include('inc', 'ds_extras', 'includes/ds_extras.vd');
2004
  }
2005
  drupal_alter('ds_fields_ui', $fields, $context);
2006

    
2007
  // Get field settings.
2008
  $field_settings = ds_get_field_settings($entity_type, $bundle, $view_mode, FALSE);
2009
  $form['#field_settings'] = $field_settings;
2010

    
2011
  $table = &$form['fields'];
2012
  $form['#ds_fields'] = array();
2013

    
2014
  $field_label_options = array(
2015
    'above' => t('Above'),
2016
    'inline' => t('Inline'),
2017
    'hidden' => t('<Hidden>'),
2018
  );
2019
  drupal_alter('ds_label_options', $field_label_options);
2020

    
2021
  // Regions for fields.
2022
  $field_regions = array();
2023
  if (isset($form['#ds_layout']->settings['fields'])) {
2024
    $field_regions = $form['#ds_layout']->settings['fields'];
2025
  }
2026

    
2027
  foreach ($fields as $key => $field) {
2028

    
2029
    // Check on ui_limit.
2030
    if (isset($field['ui_limit'])) {
2031

    
2032
      $continue = TRUE;
2033
      foreach ($field['ui_limit'] as $limitation) {
2034
        list($limit_bundle, $limit_view_mode) = explode('|', $limitation);
2035
        if ($limit_bundle == '*' || $limit_bundle == $bundle) {
2036
          if ($limit_view_mode == '*' || $limit_view_mode == $view_mode) {
2037
            $continue = FALSE;
2038
          }
2039
        }
2040
      }
2041

    
2042
      if ($continue) {
2043
        continue;
2044
      }
2045
    }
2046

    
2047
    $form['#ds_fields'][] = $key;
2048

    
2049
    // Check on formatter settings.
2050
    if (isset($form_state['formatter_settings'][$key])) {
2051
      $field['formatter_settings'] = $form_state['formatter_settings'][$key];
2052
    }
2053
    elseif (isset($field_settings[$key]['formatter_settings'])) {
2054
      $field['formatter_settings'] = $field_settings[$key]['formatter_settings'];
2055
      $form_state['formatter_settings'][$key] = $field['formatter_settings'];
2056
    }
2057

    
2058
    if (!isset($field_settings[$key]['ft']) && isset($field_settings[$key]['ft'])) {
2059
      $form_state['formatter_settings'][$key]['ft'] = $field_settings[$key]['ft'];
2060
    }
2061

    
2062
    $value = isset($form_state['formatter_settings']) ? $form_state['formatter_settings'] : array();
2063

    
2064
    $hidden = array('hidden' => t('<Hidden>'));
2065
    $formatters = isset($field['properties']['formatters']) ? $hidden + $field['properties']['formatters'] : $hidden + array('default' => t('Default'));
2066

    
2067
    $table[$key] = array(
2068
      '#row_type' => 'field',
2069
      '#js_settings' => array('field'),
2070
      '#region_callback' => 'field_ui_display_overview_row_region',
2071
      '#attributes' => array('class' => array('draggable', 'tabledrag-leaf')),
2072
      'human_name' => array(
2073
        '#markup' => check_plain($field['title']),
2074
      ),
2075
      'weight' => array(
2076
        '#type' => 'textfield',
2077
        '#default_value' => isset($field_settings[$key]['weight']) ? $field_settings[$key]['weight'] : 0,
2078
        '#size' => 3,
2079
        '#attributes' => array('class' => array('field-weight')),
2080
      ),
2081
      'parent_wrapper' => array(
2082
        'parent' => array(
2083
          '#type' => 'select',
2084
          '#empty_value' => '',
2085
          '#options' => array(),
2086
          '#attributes' => array('class' => array('field-parent')),
2087
          '#parents' => array('fields', $key, 'parent'),
2088
        ),
2089
        'hidden_name' => array(
2090
          '#type' => 'hidden',
2091
          '#default_value' => $key,
2092
          '#attributes' => array('class' => array('field-name')),
2093
        ),
2094
      ),
2095
      'label' => array(
2096
        '#type' => 'select',
2097
        '#options' => $field_label_options,
2098
        '#default_value' => isset($field_settings[$key]['label']) ? $field_settings[$key]['label'] : 'hidden',
2099
      ),
2100
      'format' => array(
2101
        'type' => array(
2102
          '#type' => 'select',
2103
          '#options' => $formatters,
2104
          '#default_value' => isset($field_settings[$key]['format']) ? $field_settings[$key]['format'] : 'hidden',
2105
          '#attributes' => array('class' => array('field-formatter-type')),
2106
        ),
2107
      ),
2108
      'settings_summary' => array(),
2109
      'settings_edit' => array(),
2110
    );
2111

    
2112
    // Don't show summary or cogwheel in hidden region.
2113
    if (_ds_field_ui_check_hidden_region($key, $form_state, $field_regions)) {
2114
      continue;
2115
    }
2116

    
2117
    $field['name'] = $key;
2118
    $field['entity_type'] = $entity_type;
2119
    $field['bundle'] = $bundle;
2120
    $field['view_mode'] = $view_mode;
2121

    
2122
    if ($form_state['formatter_settings_edit'] == $key) {
2123
      $table[$key]['settings_summary']['#attributes']['colspan'] = 2;
2124
      $settings_form = ds_field_settings_form($field, $form_state, $form, $view_mode);
2125
      ds_field_row_form_format_construct($table, $key, $settings_form);
2126
    }
2127
    else {
2128
      // After saving, the settings are updated here as well. First we create
2129
      // the element for the table cell.
2130
      $summary = ds_field_settings_summary($field, $form_state, $form, $view_mode);
2131

    
2132
      if (isset($summary)) {
2133
        $table[$key]['settings_summary'] = $summary;
2134
        ds_field_row_form_format_summary_construct($table, $key);
2135
      }
2136
    }
2137
  }
2138

    
2139
  // Add fields submit handler.
2140
  $form['#submit'][] = 'ds_field_ui_fields_save';
2141
}
2142

    
2143
/**
2144
 * Alter the core field on the the Field UI form.
2145
 *
2146
 * @param $entity_type
2147
 *   The name of the entity type.
2148
 * @param $bundle
2149
 *   The name of the bundle
2150
 * @param $view_mode
2151
 *   The name of the view_mode
2152
 * @param $form
2153
 *   A collection of form properties.
2154
 * @param $form_state
2155
 *   A collection of form_state properties.
2156
 */
2157
function _ds_field_ui_core_fields($entity_type, $bundle, $view_mode, &$form, &$form_state) {
2158
  $entity_type = $form['#entity_type'];
2159
  $bundle = $form['#bundle'];
2160
  $view_mode = $form['#view_mode'];
2161

    
2162
  // Gather type information.
2163
  $instances = field_info_instances($entity_type, $bundle);
2164

    
2165
  $field_types = field_info_field_types();
2166
  $extra_fields = field_info_extra_fields($entity_type, $bundle, 'display');
2167

    
2168
  $table = &$form['fields'];
2169

    
2170
  // Regions for fields.
2171
  $field_regions = array();
2172
  if (isset($form['#ds_layout']->settings['fields'])) {
2173
    $field_regions = $form['#ds_layout']->settings['fields'];
2174
  }
2175

    
2176
  // Field rows.
2177
  foreach ($instances as $key => $instance) {
2178

    
2179
    // Don't show summary or cogwheel in hidden region.
2180
    if (_ds_field_ui_check_hidden_region($key, $form_state, $field_regions)) {
2181
      $table[$key]['settings_summary']['#markup'] = '';
2182
      $table[$key]['settings_edit'] = array();
2183
      continue;
2184
    }
2185

    
2186
    $field = field_info_field($instance['field_name']);
2187
    $display = $instance['display'][$view_mode];
2188

    
2189
    // Check the currently selected formatter, and merge persisted values for
2190
    // formatter settings.
2191
    if (isset($form_state['values']['fields'][$key]['type'])) {
2192
      $formatter_type = $form_state['values']['fields'][$key]['type'];
2193
    }
2194
    else {
2195
      $formatter_type = $display['type'];
2196
    }
2197

    
2198
    $settings = $display['settings'];
2199
    if (isset($form_state['formatter_settings'][$key])) {
2200
      $settings = array_merge($settings, $form_state['formatter_settings'][$key]);
2201
    }
2202
    $settings += field_info_formatter_settings($formatter_type);
2203

    
2204
    // Import field settings and merge with Field API settings.
2205
    if (!isset($form_state['formatter_settings'][$key]) && !empty($form['#field_settings'][$key]['formatter_settings']['ft'])) {
2206
      $form_state['formatter_settings'][$key] = $settings;
2207
      $form_state['formatter_settings'][$key]['ft'] = $form['#field_settings'][$key]['formatter_settings']['ft'];
2208
    }
2209

    
2210
    // Change default value or Field API format, so we can change the right
2211
    // settings form when clicking on the cogwheel.
2212
    $form['fields'][$key]['format']['type']['#default_value'] = $formatter_type;
2213

    
2214
    $instance['display'][$view_mode]['type'] = $formatter_type;
2215
    $formatter = field_info_formatter_types($formatter_type);
2216
    $instance['display'][$view_mode]['module'] = $formatter['module'];
2217
    $instance['display'][$view_mode]['settings'] = $settings;
2218

    
2219
    // Base button element for the various formatter settings actions.
2220
    $base_button = array(
2221
      '#submit' => array(
2222
        'field_ui_display_overview_multistep_submit',
2223
      ),
2224
      '#ajax' => array(
2225
        'callback' => 'field_ui_display_overview_multistep_js',
2226
        'wrapper' => 'field-display-overview-wrapper',
2227
        'effect' => 'fade',
2228
      ),
2229
      '#field_name' => $key,
2230
    );
2231

    
2232
    if ($form_state['formatter_settings_edit'] == $key) {
2233
      $formatter_type = $form_state['complete form']['fields'][$key]['format']['type']['#default_value'];
2234
      $formatter = field_info_formatter_types($formatter_type);
2235
      $instance['display'][$view_mode]['type'] = $formatter_type;
2236
      $instance['display'][$view_mode]['module'] = $formatter['module'];
2237
      $instance['display'][$view_mode]['settings'] = $settings + field_info_formatter_settings($formatter_type);
2238
      $function = $formatter['module'] . '_field_formatter_settings_form';
2239

    
2240
      // Add the default formatter settings if any.
2241
      $settings_form = array();
2242
      if (function_exists($function)) {
2243
        $settings_form = $function($field, $instance, $view_mode, $form, $form_state);
2244
      }
2245

    
2246
      // Add the field templates form when needed
2247
      if (module_exists('ds_extras') && variable_get('ds_extras_field_template', FALSE)) {
2248
        $context = array(
2249
          'instance' => $instance,
2250
          'view_mode' => $view_mode,
2251
        );
2252

    
2253
        // Load the form
2254
        module_load_include('inc', 'ds_extras', 'includes/ds_extras.admin');
2255
        ds_extras_field_template_settings_form($settings_form, $form_state, $context);
2256
      }
2257

    
2258
      // Allow other modules to alter the formatter settings form.
2259
      $context = array(
2260
        'module' => $formatter['module'],
2261
        'formatter' => $formatter,
2262
        'field' => $field,
2263
        'instance' => $instance,
2264
        'view_mode' => $view_mode,
2265
        'form' => $form,
2266
        'form_state' => $form_state,
2267
      );
2268
      drupal_alter('field_formatter_settings_form', $settings_form, $context);
2269

    
2270
      if ($settings_form) {
2271
        $table[$key]['format']['#cell_attributes'] = array('colspan' => 3);
2272
        $table[$key]['format']['settings_edit_form'] = array(
2273
          '#type' => 'container',
2274
          '#attributes' => array('class' => array('field-formatter-settings-edit-form')),
2275
          '#parents' => array('fields', $key, 'settings_edit_form'),
2276
          'label' => array(
2277
            '#markup' => t('Format settings:') . ' <span class="formatter-name">' . $formatter['label'] . '</span>',
2278
          ),
2279
          'settings' => $settings_form,
2280
          'actions' => array(
2281
            '#type' => 'actions',
2282
            'save_settings' => $base_button + array(
2283
              '#type' => 'submit',
2284
              '#name' => $key . '_formatter_settings_update',
2285
              '#value' => t('Update'),
2286
              '#op' => 'update',
2287
            ),
2288
            'cancel_settings' => $base_button + array(
2289
              '#type' => 'submit',
2290
              '#name' => $key . '_formatter_settings_cancel',
2291
              '#value' => t('Cancel'),
2292
              '#op' => 'cancel',
2293
              // Do not check errors for the 'Cancel' button, but make sure we
2294
              // get the value of the 'formatter type' select.
2295
              '#limit_validation_errors' => array(array('fields', $key, 'type')),
2296
            ),
2297
          ),
2298
        );
2299
        $table[$key]['#attributes']['class'][] = 'field-formatter-settings-editing';
2300
        $table[$key]['format']['type']['#attributes']['class'] = array('element-invisible');
2301
      }
2302
    }
2303
    else {
2304
      $summary = module_invoke($formatter['module'], 'field_formatter_settings_summary', $field, $instance, $view_mode);
2305

    
2306
      // Allow other modules to alter the formatter summary.
2307
      $context = array(
2308
        'module' => $formatter['module'],
2309
        'formatter' => $formatter,
2310
        'field' => $field,
2311
        'instance' => $instance,
2312
        'view_mode' => $view_mode,
2313
      );
2314
      drupal_alter('field_formatter_settings_summary', $summary, $context);
2315

    
2316
      if (module_exists('ds_extras') && variable_get('ds_extras_field_template', FALSE)) {
2317
        module_load_include('inc', 'ds_extras', 'includes/ds_extras.admin');
2318

    
2319
        // Field template summary
2320
        $functions = module_invoke_all('ds_field_theme_functions_info');
2321
        $default_field_function = variable_get('ft-default', 'theme_field');
2322
        $field_function = isset($form_state['formatter_settings'][$key]['ft']['func']) ? $form_state['formatter_settings'][$key]['ft']['func'] : $default_field_function;
2323

    
2324
        if (!empty($summary)) {
2325
          $summary .= '<br />';
2326
        }
2327
        $summary .= 'Field template: ' . check_plain($functions[$field_function]) . '<br />';
2328
      }
2329

    
2330
      if (!empty($summary)) {
2331
        $table[$key]['settings_summary'] = array();
2332
        $table[$key]['settings_edit'] = array();
2333

    
2334
        $table[$key]['settings_summary'] = array(
2335
          '#markup' => '<div class="field-formatter-summary">' . $summary . '</div>',
2336
          '#cell_attributes' => array('class' => array('field-formatter-summary-cell')),
2337
        );
2338
        // Render the other part of the summary
2339
        ds_field_row_form_format_summary_construct($table, $key);
2340
      }
2341
    }
2342
  }
2343
}
2344

    
2345
/**
2346
 * Helper function to check if we are in a hidden region or not.
2347
 */
2348
function _ds_field_ui_check_hidden_region($key, $form_state, $field_regions) {
2349
  $continue = FALSE;
2350
  if (isset($form_state['input']['fields'][$key]['region'])) {
2351
    if ($form_state['input']['fields'][$key]['region'] == 'hidden') {
2352
      $continue = TRUE;
2353
    }
2354
  }
2355
  elseif (!isset($field_regions[$key]) || $field_regions[$key] == 'hidden') {
2356
    $continue = TRUE;
2357
  }
2358

    
2359
  return $continue;
2360
}
2361

    
2362
/**
2363
 * Helper function for building the formatter settings.
2364
 */
2365
function ds_field_row_form_format_construct(&$table, $key, $settings_form) {
2366

    
2367
  $base_button = array(
2368
    '#submit' => array(
2369
      'field_ui_display_overview_multistep_submit',
2370
    ),
2371
    '#validate' => array(
2372
      'ds_field_ui_fields_validate',
2373
    ),
2374
    '#ajax' => array(
2375
      'callback' => 'field_ui_display_overview_multistep_js',
2376
      'wrapper' => 'field-display-overview-wrapper',
2377
      'effect' => 'fade',
2378
    ),
2379
    '#field_name' => $key,
2380
  );
2381
  $table[$key]['format']['settings_edit'] = array(
2382
    '#type' => 'container',
2383
    '#attributes' => array('class' => array('field-formatter-settings-edit-form')),
2384
    '#parents' => array('fields', $key, 'settings_edit_form'),
2385
    '#weight' => -5,
2386
    // Create a settings form where hooks can pick in.
2387
    'settings' => $settings_form,
2388
    'actions' => array(
2389
      '#type' => 'actions',
2390
      'save_settings' => $base_button + array(
2391
        '#type' => 'submit',
2392
        '#name' => $key . '_formatter_settings_update',
2393
        '#value' => t('Update'),
2394
        '#op' => 'update',
2395
      ),
2396
      'cancel_settings' => $base_button + array(
2397
        '#type' => 'submit',
2398
        '#name' => $key . '_formatter_settings_cancel',
2399
        '#value' => t('Cancel'),
2400
        '#op' => 'cancel',
2401
        // Do not check errors for the 'Cancel' button.
2402
        '#limit_validation_errors' => array(),
2403
      ),
2404
    ),
2405
  );
2406
  $table[$key]['#attributes']['class'][] = 'field-formatter-settings-editing';
2407
  $table[$key]['format']['type']['#attributes']['class'] = array('element-invisible');
2408
}
2409

    
2410
/**
2411
 * Helper function for formatter summary settings.
2412
 */
2413
function ds_field_row_form_format_summary_construct(&$table, $key) {
2414

    
2415
  $base_button = array(
2416
    '#submit' => array('field_ui_display_overview_multistep_submit'),
2417
    '#ajax' => array(
2418
      'callback' => 'field_ui_display_overview_multistep_js',
2419
      'wrapper' => 'field-display-overview-wrapper',
2420
      'effect' => 'fade',
2421
    ),
2422
    '#field_name' => $key,
2423
  );
2424

    
2425
  // Add the configure button.
2426
  $table[$key]['settings_edit'] = $base_button + array(
2427
    '#type' => 'image_button',
2428
    '#name' => $key . '_formatter_settings_edit',
2429
    '#src' => 'misc/configure.png',
2430
    '#attributes' => array('class' => array('field-formatter-settings-edit'), 'alt' => t('Edit')),
2431
    '#op' => 'edit',
2432
    // Do not check errors for the 'Edit' button.
2433
    '#limit_validation_errors' => array(),
2434
    '#prefix' => '<div class="field-formatter-settings-edit-wrapper">',
2435
    '#suffix' => '</div>',
2436
  );
2437
}
2438

    
2439
/**
2440
 * Add tab for adding new fields on the fly.
2441
 *
2442
 * @param $entity_type
2443
 *   The name of the entity type.
2444
 * @param $bundle
2445
 *   The name of the bundle
2446
 * @param $view_mode
2447
 *   The name of the view_mode
2448
 * @param $form
2449
 *   A collection of form properties.
2450
 * @param $form_state
2451
 *   A collection of form_state properties.
2452
 */
2453
function _ds_field_ui_custom_fields($entity_type, $bundle, $view_mode, &$form, $form_state) {
2454

    
2455
  $form['additional_settings']['add_custom_fields'] = array(
2456
    '#type' => 'fieldset',
2457
    '#title' => t('Custom fields'),
2458
    '#description' => t('Click on one of the buttons to create a new field.') . '<p></p>',
2459
    '#access' => user_access('admin_fields'),
2460
  );
2461

    
2462
  // Include the CTools tools that we need.
2463
  ctools_include('ajax');
2464
  ctools_include('modal');
2465

    
2466
  // Add CTools' javascript to the page.
2467
  ctools_modal_add_js();
2468

    
2469
  $field_types = array(
2470
    'custom_field' => t('Add a code field'),
2471
    'manage_ctools' => t('Add a dynamic field'),
2472
  );
2473
  if (module_exists('block')) {
2474
    $field_types['manage_block'] = t('Add a block field');
2475
  }
2476
  $field_types['manage_preprocess'] = t('Add a preprocess field');
2477

    
2478
  foreach ($field_types as $field_key => $field_title) {
2479

    
2480
    $form['ctools_add_field_' . $field_key . '_url'] = array(
2481
      '#type' => 'hidden',
2482
      '#attributes' => array('class' => array('ctools_add_field_' . $field_key . '-url')),
2483
      '#value' => url('admin/structure/ds/nojs/add_field/' . $field_key),
2484
    );
2485

    
2486
    $form['additional_settings']['add_custom_fields']['ctools_add_field_' . $field_key] = array(
2487
      '#type' => 'button',
2488
      '#value' => $field_title,
2489
      '#attributes' => array('class' => array('ctools-use-modal')),
2490
      '#id' => 'ctools_add_field_' . $field_key,
2491
    );
2492
  }
2493
  $form['additional_settings']['add_custom_fields']['manage_fields'] = array(
2494
    '#type' => 'link',
2495
    '#title' => 'Manage fields',
2496
    '#href' => 'admin/structure/ds/fields',
2497
    '#prefix' => '<div>',
2498
    '#suffix' => '</div>',
2499
  );
2500
}
2501

    
2502
/**
2503
 * Utility function to check if we need to save anything for this field.
2504
 */
2505
function _ds_field_valid($key, $field, &$form_state, $view_mode = 'default') {
2506
  $continue = FALSE;
2507

    
2508
  // Ignore the Field group module and the region to block plugin.
2509
  if ($key == '_add_new_group' || $key == '_add_new_field' || $key == '_add_new_block_region') {
2510
    $continue = TRUE;
2511
  }
2512

    
2513
  // If the field is in hidden region, do not save. Check if the
2514
  // field has a type key which means it's from Field API and
2515
  // we need to reset that type to 'hidden' so it doesn't get
2516
  // fired by Field API in the frontend.
2517
  if (isset($field['region']) && $field['region'] == 'hidden') {
2518
    if (isset($field['type']) && $view_mode != 'form') {
2519
      $form_state['values']['fields'][$key]['type'] = 'hidden';
2520
    }
2521

    
2522
    // In case of a form, fields will be set with #access to FALSE.
2523
    if ($view_mode != 'form') {
2524
      $continue = TRUE;
2525
    }
2526
  }
2527

    
2528
  return $continue;
2529
}
2530

    
2531
/**
2532
 * Utility function to return CSS classes.
2533
 */
2534
function _ds_classes($name = 'ds_classes_regions') {
2535
  static $classes = array();
2536

    
2537
  if (!isset($classes[$name])) {
2538
    $classes[$name] = array();
2539
    $custom_classes = trim(variable_get($name, ''));
2540
    if (!empty($custom_classes)) {
2541
      $classes[$name][''] = t('None');
2542
      $custom_classes = explode("\n", $custom_classes);
2543
      foreach ($custom_classes as $key => $value) {
2544
        $classes_splitted = explode("|", $value);
2545
        $key = trim($classes_splitted[0]);
2546
        $friendly_name = isset($classes_splitted[1]) ? trim($classes_splitted[1]) : $key;
2547
        $classes[$name][check_plain($key)] = $friendly_name;
2548
      }
2549
    }
2550
    $name_clone = $name; // Prevent the name from being changed.
2551
    drupal_alter('ds_classes', $classes[$name], $name_clone);
2552
  }
2553

    
2554
  return $classes[$name];
2555
}
2556

    
2557
/**
2558
 * Utility function to sort a multidimensional array by a value in a sub-array.
2559
 *
2560
 * @param $a
2561
 *   The array to sort.
2562
 * @param $subkey
2563
 *   The subkey to sort by.
2564
 */
2565
function _ds_sort_fields($a, $subkey) {
2566
  foreach ($a as $k => $v) {
2567
    if (isset($v[$subkey])) {
2568
      $b[$k] = $v[$subkey];
2569
    }
2570
  }
2571
  asort($b);
2572
  foreach ($b as $key => $val) {
2573
    $c[$key] = $a[$key];
2574
  }
2575
  return $c;
2576
}