Projet

Général

Profil

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

root / drupal7 / sites / all / modules / ds / includes / ds.field_ui.inc @ 3dfa8105

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
    $element['use_content_language'] = array(
986
      '#type' => 'checkbox',
987
      '#title' => t('Use current content language'),
988
      '#default_value' => $settings['use_content_language'],
989
    );
990
    return $element;
991
  }
992

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

    
1023
/**
1024
 * Implements hook_field_formatter_settings_summary().
1025
 */
1026
function ds_field_formatter_settings_summary($field, $instance, $view_mode) {
1027
  $summary = '';
1028
  $display = $instance['display'][$view_mode];
1029
  $settings = $display['settings'];
1030

    
1031
  if ($display['type'] === 'ds_taxonomy_view_mode') {
1032
    $entity_info = entity_get_info('taxonomy_term');
1033
    $modes = $entity_info['view modes'];
1034
    $mode = $modes[$settings['taxonomy_term_reference_view_mode']]['label'];
1035
    $summary .= t('View mode: %mode', array('%mode' => $mode)) . '<br />';;
1036
    $summary .= !empty($settings['use_content_language']) ? t('Use current content language') : t('Use field language');
1037
  }
1038

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

    
1051
  return $summary;
1052
}
1053

    
1054
/**
1055
 * Creates a summary for the field format configuration summary.
1056
 *
1057
 * @param $field
1058
 *   The configuration of the field.
1059
 *
1060
 * @return $summary
1061
 *   An markup array.
1062
 */
1063
function ds_field_settings_summary($field, $form_state, $form, $view_mode) {
1064

    
1065
  $summary = '';
1066

    
1067
  // Not all fields have settings.
1068
  if (isset($field['properties']['settings'])) {
1069
    $summary = module_invoke($field['module'], 'ds_field_format_summary', $field);
1070
  }
1071

    
1072
  if (module_exists('ds_extras') && variable_get('ds_extras_field_template', FALSE)) {
1073
    module_load_include('inc', 'ds_extras', 'includes/ds_extras.admin');
1074

    
1075
    // Field template summary
1076
    if (!in_array($field['field_type'], array(DS_FIELD_TYPE_IGNORE, DS_FIELD_TYPE_PREPROCESS))) {
1077
      $functions = module_invoke_all('ds_field_theme_functions_info');
1078
      $default_field_function = variable_get('ft-default', 'theme_field');
1079
      $field_function = isset($form_state['formatter_settings'][$field['name']]['ft']['func']) ? $form_state['formatter_settings'][$field['name']]['ft']['func'] : $default_field_function;
1080

    
1081
      $summary .= 'Field template: ' . check_plain($functions[$field_function]) . '<br />';
1082
    }
1083
  }
1084

    
1085
  if (!empty($form_state['complete form'])) {
1086
    $formatter_name = $form_state['complete form']['fields'][$field['name']]['format']['type']['#value'];
1087
  }
1088
  else {
1089
    $formatter_name = $form['fields'][$field['name']]['format']['type']['#default_value'];
1090
  }
1091

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

    
1112
  if (empty($summary)) {
1113
    return NULL; // no summary return nothing
1114
  }
1115

    
1116
  return array(
1117
    '#markup' => '<div class="field-formatter-summary">' . $summary . '</div>',
1118
    '#cell_attributes' => array('class' => array('field-formatter-summary-cell')),
1119
  );
1120
}
1121

    
1122
/**
1123
 * Creates a form for Display Suite fields.
1124
 * .
1125
 * @param $field
1126
 *   The field definition.
1127
 *
1128
 * @return $form
1129
 *   A form definition.
1130
 */
1131
function ds_field_settings_form($field, &$form_state, $entity_form, $view_mode) {
1132
  $form = module_invoke($field['module'], 'ds_field_settings_form', $field);
1133

    
1134
  // Add field template settings to every field if enabled.
1135
  if (module_exists('ds_extras') && variable_get('ds_extras_field_template', FALSE)) {
1136
    $context = array(
1137
      'instance' => array(
1138
        'entity_type' => $field['entity_type'],
1139
        'bundle' => $field['bundle'],
1140
        'field_name' => $field['name'],
1141
      ),
1142
      'view_mode' => $field['view_mode'],
1143
    );
1144

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

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

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

    
1180
  return $form;
1181
}
1182

    
1183
/**
1184
 * Implements hook_ds_field_format_summary().
1185
 */
1186
function ds_ds_field_format_summary($field) {
1187
  $summary = '';
1188
  $settings = isset($field['formatter_settings']) ? $field['formatter_settings'] : $field['properties']['default'];
1189
  $functions = module_invoke_all('ds_field_theme_functions_info');
1190
  foreach ($settings as $key => $value) {
1191

    
1192
    // Ignore Field Formatter conditions.
1193
    if ($key == 'conditions') {
1194
      continue;
1195
    }
1196

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

    
1210
  if (empty($summary) && ($field['field_type'] == DS_FIELD_TYPE_CTOOLS)) {
1211
    $summary .= t('Not configured yet.') . '<br />';
1212
  }
1213

    
1214
  return $summary;
1215
}
1216

    
1217
/**
1218
 * Implements hook_ds_field_settings_form().
1219
 */
1220
function ds_ds_field_settings_form($field) {
1221
  $form = array();
1222

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

    
1225
  if (empty($field['properties']['settings'])) {
1226
    return $form;
1227
  }
1228

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

    
1231
    switch ($value['type']) {
1232

    
1233
      case 'textfield':
1234
        $form[$key] = array(
1235
          '#type' => 'textfield',
1236
          '#title' => str_replace('_', ' ', check_plain(drupal_ucfirst($key))),
1237
          '#default_value' => isset($settings[$key]) ? $settings[$key] : '',
1238
          '#size' => 40,
1239
          '#description' => isset($value['description']) ? check_plain($value['description']) : '',
1240
        );
1241
        break;
1242

    
1243
      case 'select':
1244
        $form[$key] = array(
1245
          '#type' => 'select',
1246
          '#title' => check_plain(drupal_ucfirst($key)),
1247
          '#default_value' => isset($settings[$key]) ? $settings[$key] : '',
1248
          '#options' => $value['options'],
1249
          '#description' => isset($value['description']) ? check_plain($value['description']) : '',
1250
        );
1251
        break;
1252

    
1253
      case 'checkbox':
1254
        $form[$key] = array(
1255
          '#type' => 'checkbox',
1256
          '#title' => str_replace('_', ' ', check_plain(drupal_ucfirst($key))),
1257
          '#default_value' => isset($settings[$key]) ? $settings[$key] : '',
1258
          '#description' => isset($value['description']) ? check_plain($value['description']) : '',
1259
        );
1260
        break;
1261

    
1262
      case 'ctools':
1263
        ctools_include('modal');
1264
        ctools_include('object-cache');
1265
        ctools_modal_add_js();
1266
        $form[$key] = array(
1267
          '#type' => 'hidden',
1268
          '#default_value' => isset($settings[$key]) ? $settings[$key] : '',
1269
          '#weight' => 2,
1270
        );
1271
        $action = 'add';
1272
        $args = '';
1273
        $conf = array();
1274
        $query = array('query' => array('selection' => 1));
1275
        $title = t('Select content');
1276
        if (isset($settings[$key])) {
1277
          $query = array();
1278
          $ctools = unserialize($settings['ctools']);
1279
          $type = $ctools['type'];
1280
          $subtype = $ctools['subtype'];
1281
          $args = '/' . $type . '/' . $subtype;
1282
          $action = 'edit';
1283
          $conf = $ctools['conf'];
1284
          $title = t('Edit content');
1285
        }
1286
        $form['select'] = array(
1287
          '#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>',
1288
          '#weight' => -10,
1289
        );
1290
        $form['load_terms'] = array(
1291
          '#type' => 'checkbox',
1292
          '#title' => t('Load terms'),
1293
          '#description' => t('Toggle if you are embedding a view with term fields.'),
1294
          '#default_value' => isset($settings['load_terms']) ? $settings['load_terms'] : '',
1295
          '#weight' => -1,
1296
        );
1297
        $form['show_title']['#weight'] = 0;
1298
        $form['title_wrapper']['#weight'] = 1;
1299
        ctools_object_cache_set($field['name'], $field['name'], $conf);
1300
        break;
1301
    }
1302
  }
1303

    
1304
  return $form;
1305
}
1306

    
1307
/**
1308
 * Add entity contexts.
1309
 */
1310
function ds_get_entity_context($entity_type) {
1311
  ctools_include('context');
1312
  $arguments = array(
1313
    array(
1314
      'keyword' => $entity_type,
1315
      'identifier' => drupal_ucfirst($entity_type) . ' being viewed',
1316
      'id' => 1,
1317
      'name' => 'entity_id:' . $entity_type,
1318
      'settings' => array(),
1319
    ),
1320
  );
1321

    
1322
  return ctools_context_get_placeholders_from_argument($arguments);
1323
}
1324

    
1325
/**
1326
 * Return the configuration settings for the CTools field.
1327
 */
1328
function ds_ctools_content($action = 'add', $entity_type = '', $field_name = '', $type_name = '', $subtype_name = '', $step = NULL) {
1329

    
1330
  ctools_include('modal');
1331
  ctools_include('ajax');
1332
  ctools_include('content');
1333
  ctools_include('object-cache');
1334

    
1335
  $commands = array();
1336
  $content_type = ctools_get_content_type($type_name);
1337
  $subtype = ctools_content_get_subtype($content_type, $subtype_name);
1338

    
1339
  if ($data = ctools_object_cache_get($field_name, $field_name)) {
1340
    $conf = $data;
1341
  }
1342
  else {
1343
    $conf = ctools_content_get_defaults($content_type, $subtype);
1344
  }
1345

    
1346
  $url = 'admin/structure/ds/fields/manage_ctools/content/' . $action . '/' . $entity_type . '/' . $field_name;
1347
  $base_url = $url;
1348
  if (!empty($type_name) && !empty($subtype_name)) {
1349
    $url .= '/' . $type_name . '/' . $subtype_name . '/%step';
1350
  }
1351
  $form_info = array(
1352
    'path' => $url,
1353
    'show cancel' => TRUE,
1354
    'next callback' => 'ds_ctools_content_next',
1355
  );
1356

    
1357
  // Get entity context.
1358
  $contexts = ds_get_entity_context($entity_type);
1359

    
1360
  $form_state = array(
1361
    'contexts' => $contexts,
1362
    'ajax' => TRUE,
1363
    'modal' => TRUE,
1364
    'modal return' => TRUE,
1365
    'field_name' => $field_name,
1366
  );
1367

    
1368
  // Call the content form.
1369
  $output = ctools_content_form($action, $form_info, $form_state, $content_type, $subtype_name, $subtype, $conf, $step);
1370

    
1371
  if (!empty($form_state['complete']) || isset($_GET['dismiss'])) {
1372
    $configuration = array(
1373
      'conf' => $form_state['conf'],
1374
      'type' => $type_name,
1375
      'subtype' => $subtype_name,
1376
    );
1377
    $commands[] = ctools_modal_command_dismiss();
1378
    $commands[] = ajax_command_invoke('input[name="fields[' . $field_name . '][settings_edit_form][settings][ctools]"]', 'dsCtoolsContentConfiguration', array(serialize($configuration)));
1379
    $commands[] = ajax_command_invoke('.select-content-link', 'dsCtoolsContentUpdate', array(serialize($configuration)));
1380
    ctools_object_cache_clear($field_name, $field_name);
1381
  }
1382
  // Content selection
1383
  elseif (!empty($form_state['cancel']) || isset($_GET['selection'])) {
1384
    ctools_object_cache_clear($field_name, $field_name);
1385
    $commands[] = ds_ctools_content_select($contexts, $field_name, $action, $entity_type);
1386
  }
1387
  // No configuration anymore.
1388
  elseif ($output === FALSE && !isset($_GET['dismiss'])) {
1389
    $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)))));
1390
    $commands[] = ctools_modal_command_display(t('Edit content'), $output);
1391
  }
1392
  // Form render.
1393
  else {
1394
    $commands = ctools_modal_form_render($form_state, $output);
1395
  }
1396

    
1397
  print ajax_render($commands);
1398
  ajax_footer();
1399
  exit;
1400
}
1401

    
1402
/**
1403
 * Handle the 'next' click on the add/edit field form wizard.
1404
 */
1405
function ds_ctools_content_next(&$form_state) {
1406
  ctools_object_cache_set($form_state['field_name'], $form_state['field_name'], $form_state['conf']);
1407
}
1408

    
1409
/**
1410
 * Select content.
1411
 *
1412
 * @param $contexts
1413
 *   A collection of contexts, usually the entity.
1414
 * @param $field_name
1415
 *   The name of the field.
1416
 * @param $action
1417
 *   The name of the action.
1418
 * @param $entity_type
1419
 *   The name of the entity type.
1420
 */
1421
function ds_ctools_content_select($contexts, $field_name, $action, $entity_type) {
1422

    
1423
  // Get content types.
1424
  $content_types = ctools_content_get_available_types($contexts);
1425

    
1426
  $categories = $category_names = $ordered = array();
1427

    
1428
  foreach ($content_types as $type_name => $subtypes) {
1429
    foreach ($subtypes as $subtype_name => $content_type) {
1430
      list($category_key, $category) = ds_ctools_get_category($content_type);
1431

    
1432
      if (empty($categories[$category_key])) {
1433
        $categories[$category_key] = array(
1434
          'title' => $category,
1435
          'content' => array(),
1436
        );
1437
        $category_names[$category_key] = $category;
1438
      }
1439

    
1440
      $content_title = filter_xss_admin($content_type['title']);
1441

    
1442
      // Ensure content with the same title doesn't overwrite each other.
1443
      while (isset($categories[$category_key]['content'][$content_title])) {
1444
        $content_title .= '-';
1445
      }
1446

    
1447
      $categories[$category_key]['content'][$content_title] = $content_type;
1448
      $categories[$category_key]['content'][$content_title]['type_name'] = $type_name;
1449
      $categories[$category_key]['content'][$content_title]['subtype_name'] = $subtype_name;
1450
    }
1451
  }
1452

    
1453
  // Now sort
1454
  natcasesort($category_names);
1455
  foreach ($category_names as $category => $name) {
1456
    $ordered[$category] = $categories[$category];
1457
  }
1458

    
1459
  $left = '';
1460
  $right = '<div class="content">' . t('Content options are divided by category. Please select a category from the left to proceed.') . '</div>';
1461
  foreach ($ordered as $section => $section_content) {
1462
    // Section.
1463
    if ($section == 'root') {
1464
      $section_content['title'] = t('Content');
1465
    }
1466
    $left .= '<div class="section"><a href="" id="' . $section . '" class="section-link">' . $section_content['title'] . '</a></div>';
1467
    // Content.
1468
    $right .= '<div id="' . $section . '-container" class="selection-hide content">';
1469
    $right .= '<h2>' . $section_content['title'] . '</h2>';
1470
    foreach ($section_content['content'] as $key => $value) {
1471
      $right .= '<div class="content-item">';
1472
      $variables = array(
1473
        'path' => ctools_content_admin_icon($value),
1474
      );
1475
      $right .= theme('image', $variables) . '&nbsp;';
1476
      $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);
1477
      $right .= '</div>';
1478
    }
1479
    $right .= '</div>';
1480
  }
1481

    
1482
  // Create output.
1483
  $output = '<div id="ctools-content-selection">';
1484
  $output .= '<div id="ds-left">' . $left . '</div>';
1485
  $output .= '<div id="ds-right">' . $right . '</div>';
1486
  $output .= '</div>';
1487

    
1488
  return ctools_modal_command_display(t('Select content'), $output);
1489
}
1490

    
1491
/**
1492
 * Helper function to get the category.
1493
 */
1494
function ds_ctools_get_category($content_type) {
1495
  if (isset($content_type['top level'])) {
1496
    $category = 'root';
1497
  }
1498
  elseif (isset($content_type['category'])) {
1499
    if (is_array($content_type['category'])) {
1500
      list($category, $weight) = $content_type['category'];
1501
    }
1502
    else {
1503
      $category = $content_type['category'];
1504
    }
1505
  }
1506
  else {
1507
    $category = t('Uncategorized');
1508
  }
1509

    
1510
  return array(preg_replace('/[^a-z0-9]/', '-', drupal_strtolower($category)), $category);
1511
}
1512

    
1513
/**
1514
 * Add fake field group value in.
1515
 */
1516
function _ds_field_group_field_ui_fix_notices($form, &$form_state) {
1517
  $field_group = array(
1518
    'group_name' => '',
1519
    'label' => '',
1520
  );
1521
  $form_state['values']['fields']['_add_new_group'] = $field_group;
1522
}
1523

    
1524
/**
1525
 * Add the layouts fieldset on the Field UI screen.
1526
 *
1527
 * @param $entity_type
1528
 *   The name of the entity type.
1529
 * @param $bundle
1530
 *   The name of the bundle
1531
 * @param $view_mode
1532
 *   The name of the view_mode
1533
 * @param $form
1534
 *   A collection of form properties.
1535
 */
1536
function _ds_field_ui_table_layouts($entity_type, $bundle, $view_mode, &$form, $form_state) {
1537

    
1538
  $layout_options = array();
1539
  $ds_layouts = ds_get_layout_info();
1540
  $layout_options = array('' => t('- None -'));
1541
  foreach ($ds_layouts as $key => $layout) {
1542
    $optgroup = 'Display Suite';
1543

    
1544
    // Panels can not be used on Views fields and forms.
1545
    if (!empty($layout['module']) && $layout['module'] == 'panels' && isset($form_state['no_panels'])) {
1546
      continue;
1547
    }
1548

    
1549
    // Create new layout option group.
1550
    if (!empty($layout['module'])) {
1551
      $optgroup = drupal_ucfirst($layout['module']);
1552
    }
1553

    
1554
    if (!isset($layout_options[$optgroup])) {
1555
      $layout_options[$optgroup] = array();
1556
    }
1557

    
1558
    // Stack the layout.
1559
    $layout_options[$optgroup][$key] = $layout['label'];
1560
  }
1561

    
1562
  // If there is only one $optgroup, move it to the root.
1563
  if (count($layout_options) == 2) {
1564
    $options = $layout_options[$optgroup];
1565
    $layout_options = array_merge(array('' => t('- None -')), $options);
1566
  }
1567

    
1568
  // Add layouts form.
1569
  $form['additional_settings']['ds_layouts'] = array(
1570
    '#type' => 'fieldset',
1571
    '#title' => t('Layout for !bundle in !view_mode', array('!bundle' => str_replace('_', ' ', $bundle), '!view_mode' => str_replace('_', ' ', $view_mode))),
1572
    '#collapsible' => TRUE,
1573
    '#collapsed' => FALSE,
1574
    '#parents' => array('additional_settings'),
1575
    '#weight' => -100,
1576
  );
1577

    
1578
  ctools_include('export');
1579
  $layout = new stdClass();
1580
  $ds_layout_settings = ctools_export_crud_load_all('ds_layout_settings');
1581
  if (isset($ds_layout_settings[$form['#export_id']])) {
1582
    $layout = $ds_layout_settings[$form['#export_id']];
1583
  }
1584

    
1585
  if (!empty($layout) && isset($layout->layout) && isset($ds_layouts[$layout->layout]) && empty($layout->disabled)) {
1586
    $layout->settings = $layout->settings;
1587
    $layout->regions = $ds_layouts[$layout->layout]['regions'];
1588
    $form['#ds_layout'] = $layout;
1589
  }
1590

    
1591

    
1592
  // The layout is defined in code.
1593
  if (isset($layout->export_type)) {
1594
    // Enabled/disable the layout.
1595
    if (empty($layout->disabled)) {
1596
      $link = t('This layout is defined in code') . ': ' . l(t('disable layout.'), 'admin/structure/ds/disable/' . $form['#export_id'], array('query' => drupal_get_destination()));
1597
    }
1598
    else {
1599
      $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()));
1600
    }
1601
    $form['additional_settings']['ds_layouts']['enable_disable'] = array(
1602
      '#markup' => $link,
1603
      '#weight' => 2,
1604
    );
1605

    
1606
    // Overridden in database.
1607
    if ($layout->export_type == 3) {
1608
      $form['additional_settings']['ds_layouts']['revert'] = array(
1609
        '#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())),
1610
        '#weight' => 1,
1611
      );
1612
    }
1613
  }
1614

    
1615
  // Load the layout preview form
1616
  $layout->layout_options = $layout_options;
1617
  _ds_field_ui_table_layouts_preview($form, $form_state, $ds_layouts, $layout, $entity_type, $bundle, $view_mode);
1618

    
1619
  if (!empty($layout) && isset($layout->regions)) {
1620

    
1621
    // Add wrappers
1622
    $wrapper_options = array(
1623
      'div' => 'Div',
1624
      'span' => 'Span',
1625
      'section' => 'Section',
1626
      'article' => 'Article',
1627
      'header' => 'Header',
1628
      'footer' => 'Footer',
1629
      'aside' => 'Aside',
1630
      'figure' => 'Figure'
1631
    );
1632
    $form['additional_settings']['region_wrapper'] = array(
1633
      '#type' => 'fieldset',
1634
      '#title' => t('Custom wrappers'),
1635
      '#description' => t('Choose a wrapper. All Display Suite layouts support this option.')
1636
    );
1637

    
1638
    // Hide the fieldset in case of the reset layout.
1639
    if ($layout->layout === 'ds_reset') {
1640
      $form['additional_settings']['region_wrapper']['#access'] = FALSE;
1641
    }
1642

    
1643
    foreach (array_keys($layout->regions) as $region) {
1644
      $form['additional_settings']['region_wrapper'][$region] = array(
1645
        '#type' => 'select',
1646
        '#options' => $wrapper_options,
1647
        '#title' => t('Wrapper for @region', array('@region' => $layout->regions[$region])),
1648
        '#default_value' => isset($layout->settings['wrappers'], $layout->settings['wrappers'][$region]) ? $layout->settings['wrappers'][$region] : 'div',
1649
      );
1650
    }
1651

    
1652
    $form['additional_settings']['region_wrapper']['layout_wrapper'] = array(
1653
      '#type' => 'select',
1654
      '#options' => $wrapper_options,
1655
      '#title' => t('Layout wrapper'),
1656
      '#default_value' => isset($layout->settings['layout_wrapper']) ? $layout->settings['layout_wrapper'] : 'div',
1657
      '#weight' => 10,
1658
    );
1659

    
1660
    $form['additional_settings']['region_wrapper']['layout_attributes'] = array(
1661
      '#type' => 'textfield',
1662
      '#title' => t('Layout attributes'),
1663
      '#description' => 'E.g. role="navigation"',
1664
      '#default_value' => isset($layout->settings['layout_attributes']) ? $layout->settings['layout_attributes'] : '',
1665
      '#weight' => 11,
1666
    );
1667
    $form['additional_settings']['region_wrapper']['layout_attributes_merge'] = array(
1668
      '#type' => 'checkbox',
1669
      '#title' => t('Merge other layout attributes'),
1670
      '#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.',
1671
      '#default_value' => isset($layout->settings['layout_attributes_merge']) ? $layout->settings['layout_attributes_merge'] : variable_get('ds_layout_attributes_merge', TRUE),
1672
      '#weight' => 12,
1673
    );
1674

    
1675
    $form['additional_settings']['region_wrapper']['layout_link_attribute'] = array(
1676
      '#type' => 'select',
1677
      '#options' => array(
1678
        '' => t('No link'),
1679
        'content' => t('Link to content'),
1680
        'custom' => t('Custom'),
1681
        'tokens' => t('Tokens')
1682
      ),
1683
      '#title' => t('Add link'),
1684
      '#description' => t('This will add an onclick attribute on the layout wrapper.'),
1685
      '#default_value' => isset($layout->settings['layout_link_attribute']) ? $layout->settings['layout_link_attribute'] : FALSE,
1686
      '#weight' => 12,
1687
    );
1688

    
1689
    $form['additional_settings']['region_wrapper']['layout_link_custom'] = array(
1690
      '#type' => 'textfield',
1691
      '#title' => t('Custom link'),
1692
      '#description' => t('You may use tokens for this link if you selected tokens.'),
1693
      '#default_value' => isset($layout->settings['layout_link_custom']) ? $layout->settings['layout_link_custom'] : FALSE,
1694
      '#weight' => 13,
1695
      '#states' => array(
1696
        'visible' => array(array(
1697
          ':input[name="additional_settings[region_wrapper][layout_link_attribute]"]' => array(array("value" => "tokens"), array("value" => "custom")),
1698
        )),
1699
      ),
1700
    );
1701

    
1702
    if (module_exists('token')) {
1703
      $form['additional_settings']['region_wrapper']['tokens'] = array(
1704
        '#title' => t('Tokens'),
1705
        '#type' => 'container',
1706
        '#weight' => 14,
1707
        '#states' => array(
1708
          'visible' => array(
1709
            ':input[name="additional_settings[region_wrapper][layout_link_attribute]"]' => array("value" => "tokens"),
1710
          ),
1711
        ),
1712
      );
1713
      $form['additional_settings']['region_wrapper']['tokens']['help'] = array(
1714
        '#theme' => 'token_tree',
1715
        '#token_types' => 'all',
1716
        '#global_types' => FALSE,
1717
        '#dialog' => TRUE,
1718
      );
1719
    }
1720

    
1721

    
1722

    
1723
    // Add extra classes for the regions to have more control while theming.
1724
    $form['additional_settings']['ds_classes'] = array(
1725
      '#type' => 'fieldset',
1726
      '#title' => t('Custom classes'),
1727
      '#collapsible' => TRUE,
1728
      '#collapsed' => TRUE,
1729
      '#parents' => array('additional_settings'),
1730
      '#access' => empty($chosen_layout['flexible']),
1731
    );
1732

    
1733
    $classes_access = (user_access('admin_classes') && module_exists('ds_ui'));
1734
    $classes = _ds_classes();
1735
    if (!empty($classes)) {
1736

    
1737
      $form['additional_settings']['ds_classes']['layout_class'] = array(
1738
        '#type' => 'select',
1739
        '#multiple' => TRUE,
1740
        '#options' => $classes,
1741
        '#title' => t('Class for layout'),
1742
        '#default_value' => isset($layout->settings['classes']['layout_class']) ? $layout->settings['classes']['layout_class'] : '',
1743
      );
1744

    
1745
      foreach (array_keys($layout->regions) as $region) {
1746
        $form['additional_settings']['ds_classes'][$region] = array(
1747
          '#type' => 'select',
1748
          '#multiple' => TRUE,
1749
          '#options' => $classes,
1750
          '#title' => t('Class for @region', array('@region' => $region)),
1751
          '#default_value' => isset($layout->settings['classes'][$region]) ? $layout->settings['classes'][$region] : '',
1752
        );
1753
      }
1754
      if ($classes_access) {
1755
        $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())));
1756
      }
1757
    }
1758
    else {
1759
      if ($classes_access) {
1760
        $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>');
1761
      }
1762
      else {
1763
        $form['additional_settings']['ds_classes']['#access'] = FALSE;
1764
      }
1765
    }
1766
  }
1767
  else {
1768

    
1769
    if ($view_mode != 'form') {
1770
      // See if we can clone from another view mode.
1771
      $options = array();
1772
      $ds_layout_settings = ctools_export_crud_load_all('ds_layout_settings');
1773
      foreach ($ds_layout_settings as $row) {
1774
        // Do not clone from form layouts.
1775
        if ($row->view_mode == 'form') {
1776
          continue;
1777
        }
1778
        if ($row->entity_type == $entity_type && $row->bundle == $bundle) {
1779
          $name = drupal_ucfirst(str_replace('_', ' ', $row->entity_type)) . ' > ' . drupal_ucfirst(str_replace('_', ' ', $row->bundle)) . ' > ' . drupal_ucfirst(str_replace('_', ' ', $row->view_mode));
1780
          if (!empty($row->disabled)) {
1781
            $name .= ' ' . t('(disabled)');
1782
          }
1783
          $options[$row->id] = $name;
1784
        }
1785
      }
1786

    
1787
      if (!empty($options)) {
1788

    
1789
        // Clone from another layout.
1790
        $form['additional_settings']['ds_clone'] = array(
1791
          '#type' => 'fieldset',
1792
          '#title' => t('Clone layout'),
1793
          '#collapsible' => TRUE,
1794
          '#collapsed' => TRUE,
1795
          '#parents' => array('additional_settings'),
1796
        );
1797
        $form['additional_settings']['ds_clone']['clone'] = array(
1798
          '#title' => t('Select an existing layout to clone.'),
1799
          '#type' => 'select',
1800
          '#options' => $options,
1801
          '#weight' => 20,
1802
        );
1803
        $form['additional_settings']['ds_clone']['clone_submit'] = array(
1804
          '#type' => 'submit',
1805
          '#value' => t('Clone layout'),
1806
          '#submit' => array('ds_field_ui_layout_clone'),
1807
          '#weight' => 21,
1808
        );
1809
      }
1810
    }
1811
  }
1812

    
1813
  $form['additional_settings']['ds_layouts']['id'] = array(
1814
    '#type' => 'value',
1815
    '#value' => isset($layout->id) ? $layout->id : $form['#export_id'],
1816
  );
1817

    
1818
  $form['additional_settings']['ds_layouts']['old_layout'] = array(
1819
    '#type' => 'value',
1820
    '#value' => isset($layout->layout) ? $layout->layout : 0,
1821
  );
1822

    
1823
  // Add validate and submit handlers. Layout needs be first so
1824
  // we can reset the type key for Field API fields.
1825
  $form['#validate'][] = 'ds_field_ui_layouts_validate';
1826
  $submit = $form['#submit'];
1827
  $form['#submit'] = array('ds_field_ui_layouts_save');
1828
  $form['#submit'] = array_merge($form['#submit'], $submit);
1829
}
1830

    
1831
/**
1832
 * Add the layout previews to the Field UI screen.
1833
 *
1834
 * @param $form
1835
 *   A collection of form properties.
1836
 * @param $form_state
1837
 *   The state of the form
1838
 * @param $ds_layouts
1839
 *   Collection of all the layouts
1840
 * @param $layout
1841
 *   Current selected layout
1842
 * @param $entity_type
1843
 *   The name of the entity type.
1844
 * @param $bundle
1845
 *   The name of the bundle
1846
 * @param $view_mode
1847
 *   The name of the view_mode
1848
 */
1849
function _ds_field_ui_table_layouts_preview(&$form, &$form_state, $ds_layouts, $layout, $entity_type, $bundle, $view_mode) {
1850
  $layout_string = '';
1851

    
1852
  $form['additional_settings']['ds_layouts']['layout'] = array(
1853
    '#type' => 'select',
1854
    '#title' => t('Select a layout'),
1855
    '#options' => $layout->layout_options,
1856
    '#default_value' => isset($layout->layout) && empty($layout->disabled) ? $layout->layout : '',
1857
    '#prefix' => '<div class="ds-select-layout">',
1858
    '#suffix' => '</div>',
1859
    '#weight' => -1,
1860
    '#ajax' => array(
1861
      'callback' => 'ds_field_ui_table_layouts_preview_callback',
1862
      'wrapper' => 'ds_layout_wrapper',
1863
    ),
1864
  );
1865
  if (!isset($layout->layout)) {
1866
    $form['additional_settings']['ds_layouts']['layout']['#description'] = t("A layout must be selected to enable Display Suite functionality.");
1867
  }
1868

    
1869
  $form['additional_settings']['ds_layouts']['preview'] = array(
1870
    '#type' => 'container',
1871
    '#prefix' => '<div id="ds_layout_wrapper">',
1872
    '#suffix' => '</div>',
1873
    '#weight' => -3,
1874
  );
1875

    
1876
  if (isset($layout->layout) || isset($form_state['values']['additional_settings']['layout'])) {
1877
    $layout_string = isset($form_state['values']['additional_settings']['layout']) ? $form_state['values']['additional_settings']['layout'] : $layout->layout;
1878
  }
1879

    
1880
  if (!empty($layout_string)) {
1881
    $chosen_layout = $ds_layouts[$layout_string];
1882

    
1883
    if (empty($chosen_layout['flexible'])) {
1884

    
1885
      $selected = '<strong>' . $chosen_layout['label'] . '</strong>';
1886
      $selected .= '<br/>' . t('The default template can be found in %path', array('%path' => $chosen_layout['path']));
1887
      $suggestions = t('Template suggestions') . ':<ul>';
1888
      $suggestions_array = array();
1889

    
1890
      $suggestions_array[0] = $layout_string . '--' . $entity_type;
1891
      $suggestions_array[2] = $layout_string . '--' . $entity_type . '-' . $bundle;
1892
      if (!isset($form_state['no_view_mode_suggestions']) && $view_mode != 'default') {
1893
        $suggestions_array[1] = $layout_string . '--' . $entity_type . '-' . $view_mode;
1894
        $suggestions_array[3] = $layout_string . '--' . $entity_type . '-' . $bundle . '-' . $view_mode;
1895
      }
1896

    
1897
      ksort($suggestions_array);
1898
      $suggestions = '<ul><li>' . implode('.tpl.php</li><li>', $suggestions_array) . '.tpl.php</li></ul>';
1899
    }
1900
    else {
1901
      $suggestions = '';
1902
      $selected = t('You have selected the flexible %layout_label layout.', array('%layout_label' => $chosen_layout['label'], '%path' => $chosen_layout['path']));
1903
    }
1904

    
1905
    if (isset($form_state['values']['additional_settings']['layout']) || (!empty($layout) && isset($layout->regions))) {
1906
      $fallback_image = drupal_get_path('module', 'ds') . '/images/preview.png';
1907
      $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');
1908
      $image = (isset($chosen_layout['image']) && !empty($chosen_layout['image'])) ? $chosen_layout['path'] . '/' . $layout_string . '.png' : $fallback_image;
1909
      if (isset($chosen_layout['panels']) && !empty($chosen_layout['panels']['icon'])) {
1910
        $image = $chosen_layout['panels']['path'] . '/' . $chosen_layout['panels']['icon'];
1911
      }
1912

    
1913
      $form['additional_settings']['ds_layouts']['preview'] ['title'] = array(
1914
        '#markup' => '<div class="ds-layout-preview-title">' . $current_layout . '</div>',
1915
      );
1916
      $form['additional_settings']['ds_layouts']['preview'] ['image'] = array(
1917
        '#markup' => '<div class="ds-layout-preview-image"><img src="' . base_path() . $image . '"/></div>',
1918
      );
1919
      $form['additional_settings']['ds_layouts']['preview'] ['suggestions'] = array(
1920
        '#markup' => '<div class="ds-layout-preview-suggestion"><p>' . $selected . '</p><p>' . t('!suggestions', array('!suggestions' => strtr($suggestions, '_', '-'))) . '</p></div>',
1921
      );
1922
    }
1923

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

    
1926
      // Get admin path.
1927
      $admin_path = _field_ui_bundle_admin_path($entity_type, $bundle);
1928
      if ($view_mode != 'form') {
1929
        $admin_path .= '/display';
1930
      }
1931
      else {
1932
        $admin_path .= '/fields';
1933
      }
1934

    
1935
      // If regions aren't set we don't have to move fields.
1936
      if (isset($layout->regions)) {
1937
        $url = 'admin/structure/ds/change-layout/' . $entity_type . '/' . $bundle . '/' . $view_mode . '/' . $layout_string . '?destination=' . $admin_path;
1938
        $form['#validate'][] = 'ds_field_ui_change_layout_validate';
1939
      }
1940
      else {
1941
        $url = $admin_path;
1942
      }
1943

    
1944
      if ($view_mode != 'default' && $view_mode != 'form') {
1945
        $url .= '/' . $view_mode;
1946
      }
1947

    
1948
      $form['layout_changed_url'] = array(
1949
        '#type' => 'value',
1950
        '#value' => $url,
1951
      );
1952

    
1953
      $form['#submit'][] = 'ds_field_ui_change_layout_submit';
1954
    }
1955
  }
1956
}
1957

    
1958
/**
1959
 * Ajax callback for _ds_field_ui_table_layouts_preview().
1960
 */
1961
function ds_field_ui_table_layouts_preview_callback($form, $form_state) {
1962
  return $form['additional_settings']['ds_layouts']['preview'];
1963
}
1964

    
1965
/**
1966
 * Form validation handler for _ds_field_ui_table_layouts_preview().
1967
 */
1968
function ds_field_ui_change_layout_validate(&$form, &$form_state) {
1969
  $key1 = array_search('ds_field_ui_layouts_save', $form['#submit']);
1970
  $key2 = array_search('ds_field_ui_fields_save', $form['#submit']);
1971
  unset($form['#submit'][$key1]);
1972
  unset($form['#submit'][$key2]);
1973
}
1974

    
1975
/**
1976
 * Form submission handler for _ds_field_ui_table_layouts_preview().
1977
 */
1978
function ds_field_ui_change_layout_submit($form, &$form_state) {
1979
  unset($_GET['destination']);
1980
  global $base_url;
1981
  $url = $base_url . '/' . $form_state['values']['layout_changed_url'];
1982
  $form_state['redirect'] = $url;
1983
}
1984

    
1985
/**
1986
 * Add the fields to the Field UI form.
1987
 *
1988
 * @param $entity_type
1989
 *   The name of the entity type.
1990
 * @param $bundle
1991
 *   The name of the bundle
1992
 * @param $view_mode
1993
 *   The name of the view_mode
1994
 * @param $form
1995
 *   A collection of form properties.
1996
 * @param $form_state
1997
 *   A collection of form_state properties.
1998
 */
1999
function _ds_field_ui_fields($entity_type, $bundle, $view_mode, &$form, &$form_state) {
2000

    
2001
  // Do not add the fields if there is no layout.
2002
  if (!isset($form['#ds_layout'])) {
2003
    return;
2004
  }
2005

    
2006
  // Get the fields and put them on the form.
2007
  $fields = ds_get_fields($entity_type, FALSE);
2008

    
2009
  // Ultimate alter on Field UI fields, only used for edge cases.
2010
  $context = array(
2011
    'entity_type' => $entity_type,
2012
    'bundle' => $bundle,
2013
    'view_mode' => $view_mode,
2014
  );
2015
  // Load views file if entity type is not ds_views.
2016
  // We need to cache the hook it's implementing.
2017
  if ($entity_type != 'ds_views' && module_exists('ds_extras') && variable_get('ds_extras_vd', FALSE)) {
2018
    module_load_include('inc', 'ds_extras', 'includes/ds_extras.vd');
2019
  }
2020
  drupal_alter('ds_fields_ui', $fields, $context);
2021

    
2022
  // Get field settings.
2023
  $field_settings = ds_get_field_settings($entity_type, $bundle, $view_mode, FALSE);
2024
  $form['#field_settings'] = $field_settings;
2025

    
2026
  $table = &$form['fields'];
2027
  $form['#ds_fields'] = array();
2028

    
2029
  $field_label_options = array(
2030
    'above' => t('Above'),
2031
    'inline' => t('Inline'),
2032
    'hidden' => t('<Hidden>'),
2033
  );
2034
  drupal_alter('ds_label_options', $field_label_options);
2035

    
2036
  // Regions for fields.
2037
  $field_regions = array();
2038
  if (isset($form['#ds_layout']->settings['fields'])) {
2039
    $field_regions = $form['#ds_layout']->settings['fields'];
2040
  }
2041

    
2042
  foreach ($fields as $key => $field) {
2043

    
2044
    // Check on ui_limit.
2045
    if (!empty($field['ui_limit'])) {
2046

    
2047
      $continue = TRUE;
2048
      foreach ($field['ui_limit'] as $limitation) {
2049
        list($limit_bundle, $limit_view_mode) = explode('|', $limitation);
2050
        if ($limit_bundle == '*' || $limit_bundle == $bundle) {
2051
          if ($limit_view_mode == '*' || $limit_view_mode == $view_mode) {
2052
            $continue = FALSE;
2053
          }
2054
        }
2055
      }
2056

    
2057
      if ($continue) {
2058
        continue;
2059
      }
2060
    }
2061

    
2062
    $form['#ds_fields'][] = $key;
2063

    
2064
    // Check on formatter settings.
2065
    if (isset($form_state['formatter_settings'][$key])) {
2066
      $field['formatter_settings'] = $form_state['formatter_settings'][$key];
2067
    }
2068
    elseif (isset($field_settings[$key]['formatter_settings'])) {
2069
      $field['formatter_settings'] = $field_settings[$key]['formatter_settings'];
2070
      $form_state['formatter_settings'][$key] = $field['formatter_settings'];
2071
    }
2072

    
2073
    if (!isset($field_settings[$key]['ft']) && isset($field_settings[$key]['ft'])) {
2074
      $form_state['formatter_settings'][$key]['ft'] = $field_settings[$key]['ft'];
2075
    }
2076

    
2077
    $value = isset($form_state['formatter_settings']) ? $form_state['formatter_settings'] : array();
2078

    
2079
    $hidden = array('hidden' => t('<Hidden>'));
2080
    $formatters = isset($field['properties']['formatters']) ? $hidden + $field['properties']['formatters'] : $hidden + array('default' => t('Default'));
2081

    
2082
    $table[$key] = array(
2083
      '#row_type' => 'field',
2084
      '#js_settings' => array('field'),
2085
      '#region_callback' => 'field_ui_display_overview_row_region',
2086
      '#attributes' => array('class' => array('draggable', 'tabledrag-leaf')),
2087
      'human_name' => array(
2088
        '#markup' => check_plain($field['title']),
2089
      ),
2090
      'weight' => array(
2091
        '#type' => 'textfield',
2092
        '#default_value' => isset($field_settings[$key]['weight']) ? $field_settings[$key]['weight'] : 0,
2093
        '#size' => 3,
2094
        '#attributes' => array('class' => array('field-weight')),
2095
      ),
2096
      'parent_wrapper' => array(
2097
        'parent' => array(
2098
          '#type' => 'select',
2099
          '#empty_value' => '',
2100
          '#options' => array(),
2101
          '#attributes' => array('class' => array('field-parent')),
2102
          '#parents' => array('fields', $key, 'parent'),
2103
        ),
2104
        'hidden_name' => array(
2105
          '#type' => 'hidden',
2106
          '#default_value' => $key,
2107
          '#attributes' => array('class' => array('field-name')),
2108
        ),
2109
      ),
2110
      'label' => array(
2111
        '#type' => 'select',
2112
        '#options' => $field_label_options,
2113
        '#default_value' => isset($field_settings[$key]['label']) ? $field_settings[$key]['label'] : 'hidden',
2114
      ),
2115
      'format' => array(
2116
        'type' => array(
2117
          '#type' => 'select',
2118
          '#options' => $formatters,
2119
          '#default_value' => isset($field_settings[$key]['format']) ? $field_settings[$key]['format'] : 'hidden',
2120
          '#attributes' => array('class' => array('field-formatter-type')),
2121
        ),
2122
      ),
2123
      'settings_summary' => array(),
2124
      'settings_edit' => array(),
2125
    );
2126

    
2127
    // Don't show summary or cogwheel in hidden region.
2128
    if (_ds_field_ui_check_hidden_region($key, $form_state, $field_regions)) {
2129
      continue;
2130
    }
2131

    
2132
    $field['name'] = $key;
2133
    $field['entity_type'] = $entity_type;
2134
    $field['bundle'] = $bundle;
2135
    $field['view_mode'] = $view_mode;
2136

    
2137
    if ($form_state['formatter_settings_edit'] == $key) {
2138
      $table[$key]['settings_summary']['#attributes']['colspan'] = 2;
2139
      $settings_form = ds_field_settings_form($field, $form_state, $form, $view_mode);
2140
      ds_field_row_form_format_construct($table, $key, $settings_form);
2141
    }
2142
    else {
2143
      // After saving, the settings are updated here as well. First we create
2144
      // the element for the table cell.
2145
      $summary = ds_field_settings_summary($field, $form_state, $form, $view_mode);
2146

    
2147
      if (isset($summary)) {
2148
        $table[$key]['settings_summary'] = $summary;
2149
        ds_field_row_form_format_summary_construct($table, $key);
2150
      }
2151
    }
2152
  }
2153

    
2154
  // Add fields submit handler.
2155
  $form['#submit'][] = 'ds_field_ui_fields_save';
2156
}
2157

    
2158
/**
2159
 * Alter the core field on the the Field UI form.
2160
 *
2161
 * @param $entity_type
2162
 *   The name of the entity type.
2163
 * @param $bundle
2164
 *   The name of the bundle
2165
 * @param $view_mode
2166
 *   The name of the view_mode
2167
 * @param $form
2168
 *   A collection of form properties.
2169
 * @param $form_state
2170
 *   A collection of form_state properties.
2171
 */
2172
function _ds_field_ui_core_fields($entity_type, $bundle, $view_mode, &$form, &$form_state) {
2173
  $entity_type = $form['#entity_type'];
2174
  $bundle = $form['#bundle'];
2175
  $view_mode = $form['#view_mode'];
2176

    
2177
  // Gather type information.
2178
  $instances = field_info_instances($entity_type, $bundle);
2179

    
2180
  $field_types = field_info_field_types();
2181
  $extra_fields = field_info_extra_fields($entity_type, $bundle, 'display');
2182

    
2183
  $table = &$form['fields'];
2184

    
2185
  // Regions for fields.
2186
  $field_regions = array();
2187
  if (isset($form['#ds_layout']->settings['fields'])) {
2188
    $field_regions = $form['#ds_layout']->settings['fields'];
2189
  }
2190

    
2191
  // Field rows.
2192
  foreach ($instances as $key => $instance) {
2193

    
2194
    // Don't show summary or cogwheel in hidden region.
2195
    if (_ds_field_ui_check_hidden_region($key, $form_state, $field_regions)) {
2196
      $table[$key]['settings_summary']['#markup'] = '';
2197
      $table[$key]['settings_edit'] = array();
2198
      continue;
2199
    }
2200

    
2201
    $field = field_info_field($instance['field_name']);
2202
    $display = $instance['display'][$view_mode];
2203

    
2204
    // Check the currently selected formatter, and merge persisted values for
2205
    // formatter settings.
2206
    if (isset($form_state['values']['fields'][$key]['type'])) {
2207
      $formatter_type = $form_state['values']['fields'][$key]['type'];
2208
    }
2209
    else {
2210
      $formatter_type = $display['type'];
2211
    }
2212

    
2213
    $settings = $display['settings'];
2214
    if (isset($form_state['formatter_settings'][$key])) {
2215
      $settings = array_merge($settings, $form_state['formatter_settings'][$key]);
2216
    }
2217
    $settings += field_info_formatter_settings($formatter_type);
2218

    
2219
    // Import field settings and merge with Field API settings.
2220
    if (!isset($form_state['formatter_settings'][$key]) && !empty($form['#field_settings'][$key]['formatter_settings']['ft'])) {
2221
      $form_state['formatter_settings'][$key] = $settings;
2222
      $form_state['formatter_settings'][$key]['ft'] = $form['#field_settings'][$key]['formatter_settings']['ft'];
2223
    }
2224

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

    
2229
    $instance['display'][$view_mode]['type'] = $formatter_type;
2230
    $formatter = field_info_formatter_types($formatter_type);
2231
    $instance['display'][$view_mode]['module'] = $formatter['module'];
2232
    $instance['display'][$view_mode]['settings'] = $settings;
2233

    
2234
    // Base button element for the various formatter settings actions.
2235
    $base_button = array(
2236
      '#submit' => array(
2237
        'field_ui_display_overview_multistep_submit',
2238
      ),
2239
      '#ajax' => array(
2240
        'callback' => 'field_ui_display_overview_multistep_js',
2241
        'wrapper' => 'field-display-overview-wrapper',
2242
        'effect' => 'fade',
2243
      ),
2244
      '#field_name' => $key,
2245
    );
2246

    
2247
    if ($form_state['formatter_settings_edit'] == $key) {
2248
      $formatter_type = $form_state['complete form']['fields'][$key]['format']['type']['#default_value'];
2249
      $formatter = field_info_formatter_types($formatter_type);
2250
      $instance['display'][$view_mode]['type'] = $formatter_type;
2251
      $instance['display'][$view_mode]['module'] = $formatter['module'];
2252
      $instance['display'][$view_mode]['settings'] = $settings + field_info_formatter_settings($formatter_type);
2253
      $function = $formatter['module'] . '_field_formatter_settings_form';
2254

    
2255
      // Add the default formatter settings if any.
2256
      $settings_form = array();
2257
      if (function_exists($function)) {
2258
        $settings_form = $function($field, $instance, $view_mode, $form, $form_state);
2259
      }
2260

    
2261
      // Add the field templates form when needed
2262
      if (module_exists('ds_extras') && variable_get('ds_extras_field_template', FALSE)) {
2263
        $context = array(
2264
          'instance' => $instance,
2265
          'view_mode' => $view_mode,
2266
        );
2267

    
2268
        // Load the form
2269
        module_load_include('inc', 'ds_extras', 'includes/ds_extras.admin');
2270
        if (!is_array($settings_form)) $settings_form = array();
2271
        ds_extras_field_template_settings_form($settings_form, $form_state, $context);
2272
      }
2273

    
2274
      // Allow other modules to alter the formatter settings form.
2275
      $context = array(
2276
        'module' => $formatter['module'],
2277
        'formatter' => $formatter,
2278
        'field' => $field,
2279
        'instance' => $instance,
2280
        'view_mode' => $view_mode,
2281
        'form' => $form,
2282
        'form_state' => $form_state,
2283
      );
2284
      drupal_alter('field_formatter_settings_form', $settings_form, $context);
2285

    
2286
      if ($settings_form) {
2287
        $table[$key]['format']['#cell_attributes'] = array('colspan' => 3);
2288
        $table[$key]['format']['settings_edit_form'] = array(
2289
          '#type' => 'container',
2290
          '#attributes' => array('class' => array('field-formatter-settings-edit-form')),
2291
          '#parents' => array('fields', $key, 'settings_edit_form'),
2292
          'label' => array(
2293
            '#markup' => t('Format settings:') . ' <span class="formatter-name">' . $formatter['label'] . '</span>',
2294
          ),
2295
          'settings' => $settings_form,
2296
          'actions' => array(
2297
            '#type' => 'actions',
2298
            'save_settings' => $base_button + array(
2299
              '#type' => 'submit',
2300
              '#name' => $key . '_formatter_settings_update',
2301
              '#value' => t('Update'),
2302
              '#op' => 'update',
2303
            ),
2304
            'cancel_settings' => $base_button + array(
2305
              '#type' => 'submit',
2306
              '#name' => $key . '_formatter_settings_cancel',
2307
              '#value' => t('Cancel'),
2308
              '#op' => 'cancel',
2309
              // Do not check errors for the 'Cancel' button, but make sure we
2310
              // get the value of the 'formatter type' select.
2311
              '#limit_validation_errors' => array(array('fields', $key, 'type')),
2312
            ),
2313
          ),
2314
        );
2315
        $table[$key]['#attributes']['class'][] = 'field-formatter-settings-editing';
2316
        $table[$key]['format']['type']['#attributes']['class'] = array('element-invisible');
2317
      }
2318
    }
2319
    else {
2320
      $summary = module_invoke($formatter['module'], 'field_formatter_settings_summary', $field, $instance, $view_mode);
2321

    
2322
      // Allow other modules to alter the formatter summary.
2323
      $context = array(
2324
        'module' => $formatter['module'],
2325
        'formatter' => $formatter,
2326
        'field' => $field,
2327
        'instance' => $instance,
2328
        'view_mode' => $view_mode,
2329
      );
2330
      drupal_alter('field_formatter_settings_summary', $summary, $context);
2331

    
2332
      if (module_exists('ds_extras') && variable_get('ds_extras_field_template', FALSE)) {
2333
        module_load_include('inc', 'ds_extras', 'includes/ds_extras.admin');
2334

    
2335
        // Field template summary
2336
        $functions = module_invoke_all('ds_field_theme_functions_info');
2337
        $default_field_function = variable_get('ft-default', 'theme_field');
2338
        $field_function = isset($form_state['formatter_settings'][$key]['ft']['func']) ? $form_state['formatter_settings'][$key]['ft']['func'] : $default_field_function;
2339

    
2340
        if (!empty($summary)) {
2341
          $summary .= '<br />';
2342
        }
2343
        $summary .= 'Field template: ' . check_plain($functions[$field_function]) . '<br />';
2344
      }
2345

    
2346
      if (!empty($summary)) {
2347
        $table[$key]['settings_summary'] = array();
2348
        $table[$key]['settings_edit'] = array();
2349

    
2350
        $table[$key]['settings_summary'] = array(
2351
          '#markup' => '<div class="field-formatter-summary">' . $summary . '</div>',
2352
          '#cell_attributes' => array('class' => array('field-formatter-summary-cell')),
2353
        );
2354
        // Render the other part of the summary
2355
        ds_field_row_form_format_summary_construct($table, $key);
2356
      }
2357
    }
2358
  }
2359
}
2360

    
2361
/**
2362
 * Helper function to check if we are in a hidden region or not.
2363
 */
2364
function _ds_field_ui_check_hidden_region($key, $form_state, $field_regions) {
2365
  $continue = FALSE;
2366
  if (isset($form_state['input']['fields'][$key]['region'])) {
2367
    if ($form_state['input']['fields'][$key]['region'] == 'hidden') {
2368
      $continue = TRUE;
2369
    }
2370
  }
2371
  elseif (!isset($field_regions[$key]) || $field_regions[$key] == 'hidden') {
2372
    $continue = TRUE;
2373
  }
2374

    
2375
  return $continue;
2376
}
2377

    
2378
/**
2379
 * Helper function for building the formatter settings.
2380
 */
2381
function ds_field_row_form_format_construct(&$table, $key, $settings_form) {
2382

    
2383
  $base_button = array(
2384
    '#submit' => array(
2385
      'field_ui_display_overview_multistep_submit',
2386
    ),
2387
    '#validate' => array(
2388
      'ds_field_ui_fields_validate',
2389
    ),
2390
    '#ajax' => array(
2391
      'callback' => 'field_ui_display_overview_multistep_js',
2392
      'wrapper' => 'field-display-overview-wrapper',
2393
      'effect' => 'fade',
2394
    ),
2395
    '#field_name' => $key,
2396
  );
2397
  $table[$key]['format']['settings_edit'] = array(
2398
    '#type' => 'container',
2399
    '#attributes' => array('class' => array('field-formatter-settings-edit-form')),
2400
    '#parents' => array('fields', $key, 'settings_edit_form'),
2401
    '#weight' => -5,
2402
    // Create a settings form where hooks can pick in.
2403
    'settings' => $settings_form,
2404
    'actions' => array(
2405
      '#type' => 'actions',
2406
      'save_settings' => $base_button + array(
2407
        '#type' => 'submit',
2408
        '#name' => $key . '_formatter_settings_update',
2409
        '#value' => t('Update'),
2410
        '#op' => 'update',
2411
      ),
2412
      'cancel_settings' => $base_button + array(
2413
        '#type' => 'submit',
2414
        '#name' => $key . '_formatter_settings_cancel',
2415
        '#value' => t('Cancel'),
2416
        '#op' => 'cancel',
2417
        // Do not check errors for the 'Cancel' button.
2418
        '#limit_validation_errors' => array(),
2419
      ),
2420
    ),
2421
  );
2422
  $table[$key]['#attributes']['class'][] = 'field-formatter-settings-editing';
2423
  $table[$key]['format']['type']['#attributes']['class'] = array('element-invisible');
2424
}
2425

    
2426
/**
2427
 * Helper function for formatter summary settings.
2428
 */
2429
function ds_field_row_form_format_summary_construct(&$table, $key) {
2430

    
2431
  $base_button = array(
2432
    '#submit' => array('field_ui_display_overview_multistep_submit'),
2433
    '#ajax' => array(
2434
      'callback' => 'field_ui_display_overview_multistep_js',
2435
      'wrapper' => 'field-display-overview-wrapper',
2436
      'effect' => 'fade',
2437
    ),
2438
    '#field_name' => $key,
2439
  );
2440

    
2441
  // Add the configure button.
2442
  $table[$key]['settings_edit'] = $base_button + array(
2443
    '#type' => 'image_button',
2444
    '#name' => $key . '_formatter_settings_edit',
2445
    '#src' => 'misc/configure.png',
2446
    '#attributes' => array('class' => array('field-formatter-settings-edit'), 'alt' => t('Edit')),
2447
    '#op' => 'edit',
2448
    // Do not check errors for the 'Edit' button.
2449
    '#limit_validation_errors' => array(),
2450
    '#prefix' => '<div class="field-formatter-settings-edit-wrapper">',
2451
    '#suffix' => '</div>',
2452
  );
2453
}
2454

    
2455
/**
2456
 * Add tab for adding new fields on the fly.
2457
 *
2458
 * @param $entity_type
2459
 *   The name of the entity type.
2460
 * @param $bundle
2461
 *   The name of the bundle
2462
 * @param $view_mode
2463
 *   The name of the view_mode
2464
 * @param $form
2465
 *   A collection of form properties.
2466
 * @param $form_state
2467
 *   A collection of form_state properties.
2468
 */
2469
function _ds_field_ui_custom_fields($entity_type, $bundle, $view_mode, &$form, $form_state) {
2470

    
2471
  $form['additional_settings']['add_custom_fields'] = array(
2472
    '#type' => 'fieldset',
2473
    '#title' => t('Custom fields'),
2474
    '#description' => t('Click on one of the buttons to create a new field.') . '<p></p>',
2475
    '#access' => user_access('admin_fields'),
2476
  );
2477

    
2478
  // Include the CTools tools that we need.
2479
  ctools_include('ajax');
2480
  ctools_include('modal');
2481

    
2482
  // Add CTools' javascript to the page.
2483
  ctools_modal_add_js();
2484

    
2485
  $field_types = array(
2486
    'custom_field' => t('Add a code field'),
2487
    'manage_ctools' => t('Add a dynamic field'),
2488
  );
2489
  $field_types['manage_block'] = t('Add a block field');
2490
  $field_types['manage_preprocess'] = t('Add a preprocess field');
2491

    
2492
  foreach ($field_types as $field_key => $field_title) {
2493

    
2494
    $form['ctools_add_field_' . $field_key . '_url'] = array(
2495
      '#type' => 'hidden',
2496
      '#attributes' => array('class' => array('ctools_add_field_' . $field_key . '-url')),
2497
      '#value' => url('admin/structure/ds/nojs/add_field/' . $field_key),
2498
    );
2499

    
2500
    $form['additional_settings']['add_custom_fields']['ctools_add_field_' . $field_key] = array(
2501
      '#type' => 'button',
2502
      '#value' => $field_title,
2503
      '#attributes' => array('class' => array('ctools-use-modal')),
2504
      '#id' => 'ctools_add_field_' . $field_key,
2505
    );
2506
  }
2507
  $form['additional_settings']['add_custom_fields']['manage_fields'] = array(
2508
    '#type' => 'link',
2509
    '#title' => 'Manage fields',
2510
    '#href' => 'admin/structure/ds/fields',
2511
    '#prefix' => '<div>',
2512
    '#suffix' => '</div>',
2513
  );
2514
}
2515

    
2516
/**
2517
 * Utility function to check if we need to save anything for this field.
2518
 */
2519
function _ds_field_valid($key, $field, &$form_state, $view_mode = 'default') {
2520
  $continue = FALSE;
2521

    
2522
  // Ignore the Field group module and the region to block plugin.
2523
  if ($key == '_add_new_group' || $key == '_add_new_field' || $key == '_add_new_block_region') {
2524
    $continue = TRUE;
2525
  }
2526

    
2527
  // If the field is in hidden region, do not save. Check if the
2528
  // field has a type key which means it's from Field API and
2529
  // we need to reset that type to 'hidden' so it doesn't get
2530
  // fired by Field API in the frontend.
2531
  if (isset($field['region']) && $field['region'] == 'hidden') {
2532
    if (isset($field['type']) && $view_mode != 'form') {
2533
      $form_state['values']['fields'][$key]['type'] = 'hidden';
2534
    }
2535

    
2536
    // In case of a form, fields will be set with #access to FALSE.
2537
    if ($view_mode != 'form') {
2538
      $continue = TRUE;
2539
    }
2540
  }
2541

    
2542
  return $continue;
2543
}
2544

    
2545
/**
2546
 * Utility function to return CSS classes.
2547
 */
2548
function _ds_classes($name = 'ds_classes_regions') {
2549
  static $classes = array();
2550

    
2551
  if (!isset($classes[$name])) {
2552
    $classes[$name] = array();
2553
    $custom_classes = trim(variable_get($name, ''));
2554
    if (!empty($custom_classes)) {
2555
      $classes[$name][''] = t('None');
2556
      $custom_classes = explode("\n", $custom_classes);
2557
      foreach ($custom_classes as $key => $value) {
2558
        $classes_splitted = explode("|", $value);
2559
        $key = trim($classes_splitted[0]);
2560
        $friendly_name = isset($classes_splitted[1]) ? trim($classes_splitted[1]) : $key;
2561
        $classes[$name][check_plain($key)] = $friendly_name;
2562
      }
2563
    }
2564
    $name_clone = $name; // Prevent the name from being changed.
2565
    drupal_alter('ds_classes', $classes[$name], $name_clone);
2566
  }
2567

    
2568
  return $classes[$name];
2569
}
2570

    
2571
/**
2572
 * Utility function to sort a multidimensional array by a value in a sub-array.
2573
 *
2574
 * @param $a
2575
 *   The array to sort.
2576
 * @param $subkey
2577
 *   The subkey to sort by.
2578
 */
2579
function _ds_sort_fields($a, $subkey) {
2580
  foreach ($a as $k => $v) {
2581
    if (isset($v[$subkey])) {
2582
      $b[$k] = $v[$subkey];
2583
    }
2584
  }
2585
  asort($b);
2586
  foreach ($b as $key => $val) {
2587
    $c[$key] = $a[$key];
2588
  }
2589
  return $c;
2590
}