Projet

Général

Profil

Paste
Télécharger (91,7 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / ds / includes / ds.field_ui.inc @ 6e9292aa

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
    // Additional settings
774
    if (isset($form_state['values']['additional_settings']['preview']['info']['settings']['disable_css'])) {
775
      $record->settings['layout_disable_css'] = $form_state['values']['additional_settings']['preview']['info']['settings']['disable_css'];
776
    }
777

    
778
    $record->settings = $record->settings;
779

    
780
    // Let other modules alter the layout settings.
781
    drupal_alter('ds_layout_settings', $record, $form_state);
782

    
783
    $l = $form['#ds_layout'];
784
    if ($l->export_type == 2) {
785
      drupal_write_record('ds_layout_settings', $record);
786
    }
787
    else {
788
      drupal_write_record('ds_layout_settings', $record, array('id'));
789
    }
790

    
791
    // Clear entity info cache.
792
    cache_clear_all('entity_info', 'cache', TRUE);
793
  }
794
}
795

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

    
811
/**
812
 * Save the field settings from the 'Manage display' screen.
813
 */
814
function ds_field_ui_fields_save($form, &$form_state) {
815
  // Setup some variables.
816
  $entity_type = $form['#entity_type'];
817
  $bundle = $form['#bundle'];
818
  $view_mode = $form['#view_mode'];
819

    
820
  // Delete previous field configuration configuration.
821
  db_delete('ds_field_settings')
822
    ->condition('entity_type', $entity_type)
823
    ->condition('bundle', $bundle)
824
    ->condition('view_mode', $view_mode)
825
    ->execute();
826

    
827
  if (empty($form_state['layout_saved'])) {
828
    return;
829
  }
830

    
831
  $field_settings = array();
832

    
833
  // Save settings for each field.
834
  $fields = $form['#ds_fields'];
835
  foreach ($fields as $key => $field) {
836

    
837
    // Field settings.
838
    $field_values = $form_state['values']['fields'][$field];
839

    
840
    // In case the region is hidden, do not save.
841
    if (isset($field_values['region']) && $field_values['region'] == 'hidden') {
842
      continue;
843
    }
844

    
845
    // Build settings.
846
    $settings = array();
847
    $settings['weight'] = $field_values['weight'];
848
    $settings['label'] = $field_values['label'];
849
    $settings['format'] = $field_values['format']['type'];
850

    
851
    // Any formatter settings.
852
    if (isset($form_state['formatter_settings'][$field])) {
853
      $settings['formatter_settings'] = $form_state['formatter_settings'][$field];
854
    }
855

    
856
    $field_settings[$field] = $settings;
857
  }
858

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

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

    
873
  // Clear the ds_fields cache.
874
  cache_clear_all('ds_fields:', 'cache', TRUE);
875
  cache_clear_all('ds_field_settings', 'cache');
876
}
877

    
878
/**
879
 * Clone a fields layout.
880
 */
881
function ds_field_ui_layout_clone($form, &$form_state) {
882

    
883
  $clone = $form_state['values']['additional_settings']['clone'];
884
  $entity_type = $form['#entity_type'];
885
  $bundle = $form['#bundle'];
886
  $view_mode = $form['#view_mode'];
887

    
888
  ctools_include('export');
889
  $layout = ctools_export_crud_load('ds_layout_settings', $clone);
890

    
891
  // Delete previous layout settings configuration.
892
  db_delete('ds_layout_settings')
893
    ->condition('entity_type', $entity_type)
894
    ->condition('bundle', $bundle)
895
    ->condition('view_mode', $view_mode)
896
    ->execute();
897

    
898
  // Delete previous field configuration configuration.
899
  db_delete('ds_field_settings')
900
    ->condition('entity_type', $entity_type)
901
    ->condition('bundle', $bundle)
902
    ->condition('view_mode', $view_mode)
903
    ->execute();
904

    
905
  // Save new layout record for ds.
906
  if ($layout) {
907
    $record = new stdClass();
908
    $record->id = $form['#export_id'];
909
    $record->entity_type = $entity_type;
910
    $record->bundle = $bundle;
911
    $record->view_mode = $view_mode;
912
    $record->layout = $layout->layout;
913
    $record->settings = $layout->settings;
914

    
915
    // Let other modules alter the layout settings.
916
    drupal_alter('ds_layout_settings', $record, $form_state);
917

    
918
    // Save layout record.
919
    drupal_write_record('ds_layout_settings', $record);
920

    
921
    // Copy the view mode settings.
922
    list($ce, $cb, $cv) = explode('|', $clone);
923
    _ds_field_ui_clone_view_mode_settings($entity_type, $bundle, $view_mode, $cv);
924

    
925
    // Clear entity info cache.
926
    cache_clear_all('entity_info', 'cache', TRUE);
927

    
928
    // Show message.
929
    drupal_set_message(t('The layout has been cloned.'));
930

    
931
  }
932
  else {
933
    drupal_set_message(t('No layout was cloned.'));
934
  }
935
}
936

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

    
945
  $settings = field_bundle_settings($entity_type, $bundle);
946

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

    
958
  // Update display settings for 'extra fields'.
959
  foreach (array_keys($settings['extra_fields']['display']) as $name) {
960
    if (isset($settings['extra_fields']['display'][$name][$copy_view_mode])) {
961
      $settings['extra_fields']['display'][$name][$view_mode] = $settings['extra_fields']['display'][$name][$copy_view_mode];
962
    }
963
  }
964

    
965
  // Save the settings.
966
  field_bundle_settings($entity_type, $bundle, $settings);
967
}
968

    
969
/**
970
 * Implements hook_field_formatter_settings_form().
971
 */
972
function ds_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
973

    
974
  $display = $instance['display'][$view_mode];
975
  $settings = $display['settings'];
976

    
977
  // Taxonomy view modes.
978
  if ($display['type'] === 'ds_taxonomy_view_mode') {
979
    $options = array();
980
    $view_modes = ds_entity_view_modes('taxonomy_term');
981
    foreach ($view_modes as $key => $info) {
982
      $options[$key] = $info['label'];
983
    }
984
    $element['taxonomy_term_reference_view_mode'] = array(
985
      '#title'   => t('View mode'),
986
      '#type'    => 'select',
987
      '#options' => $options,
988
      '#default_value' => $settings['taxonomy_term_reference_view_mode'],
989
    );
990
    $element['use_content_language'] = array(
991
      '#type' => 'checkbox',
992
      '#title' => t('Use current content language'),
993
      '#default_value' => $settings['use_content_language'],
994
    );
995
    return $element;
996
  }
997

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

    
1028
/**
1029
 * Implements hook_field_formatter_settings_summary().
1030
 */
1031
function ds_field_formatter_settings_summary($field, $instance, $view_mode) {
1032
  $summary = '';
1033
  $display = $instance['display'][$view_mode];
1034
  $settings = $display['settings'];
1035

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

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

    
1056
  return $summary;
1057
}
1058

    
1059
/**
1060
 * Creates a summary for the field format configuration summary.
1061
 *
1062
 * @param $field
1063
 *   The configuration of the field.
1064
 *
1065
 * @return $summary
1066
 *   An markup array.
1067
 */
1068
function ds_field_settings_summary($field, $form_state, $form, $view_mode) {
1069

    
1070
  $summary = '';
1071

    
1072
  // Not all fields have settings.
1073
  if (isset($field['properties']['settings'])) {
1074
    $summary = module_invoke($field['module'], 'ds_field_format_summary', $field);
1075
  }
1076

    
1077
  if (module_exists('ds_extras') && variable_get('ds_extras_field_template', FALSE)) {
1078
    module_load_include('inc', 'ds_extras', 'includes/ds_extras.admin');
1079

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

    
1086
      $summary .= 'Field template: ' . check_plain($functions[$field_function]) . '<br />';
1087
    }
1088
  }
1089

    
1090
  if (!empty($form_state['complete form'])) {
1091
    $formatter_name = $form_state['complete form']['fields'][$field['name']]['format']['type']['#value'];
1092
  }
1093
  else {
1094
    $formatter_name = $form['fields'][$field['name']]['format']['type']['#default_value'];
1095
  }
1096

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

    
1117
  if (empty($summary)) {
1118
    return NULL; // no summary return nothing
1119
  }
1120

    
1121
  return array(
1122
    '#markup' => '<div class="field-formatter-summary">' . $summary . '</div>',
1123
    '#cell_attributes' => array('class' => array('field-formatter-summary-cell')),
1124
  );
1125
}
1126

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

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

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

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

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

    
1185
  return $form;
1186
}
1187

    
1188
/**
1189
 * Implements hook_ds_field_format_summary().
1190
 */
1191
function ds_ds_field_format_summary($field) {
1192
  $summary = '';
1193
  $settings = isset($field['formatter_settings']) ? $field['formatter_settings'] : $field['properties']['default'];
1194
  $functions = module_invoke_all('ds_field_theme_functions_info');
1195
  foreach ($settings as $key => $value) {
1196

    
1197
    // Ignore Field Formatter conditions.
1198
    if ($key == 'conditions') {
1199
      continue;
1200
    }
1201

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

    
1215
  if (empty($summary) && ($field['field_type'] == DS_FIELD_TYPE_CTOOLS)) {
1216
    $summary .= t('Not configured yet.') . '<br />';
1217
  }
1218

    
1219
  return $summary;
1220
}
1221

    
1222
/**
1223
 * Implements hook_ds_field_settings_form().
1224
 */
1225
function ds_ds_field_settings_form($field) {
1226
  $form = array();
1227

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

    
1230
  if (empty($field['properties']['settings'])) {
1231
    return $form;
1232
  }
1233

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

    
1236
    switch ($value['type']) {
1237

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

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

    
1258
      case 'checkbox':
1259
        $form[$key] = array(
1260
          '#type' => 'checkbox',
1261
          '#title' => str_replace('_', ' ', check_plain(drupal_ucfirst($key))),
1262
          '#default_value' => isset($settings[$key]) ? $settings[$key] : '',
1263
          '#description' => isset($value['description']) ? check_plain($value['description']) : '',
1264
        );
1265
        break;
1266

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

    
1309
  return $form;
1310
}
1311

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

    
1327
  return ctools_context_get_placeholders_from_argument($arguments);
1328
}
1329

    
1330
/**
1331
 * Return the configuration settings for the CTools field.
1332
 */
1333
function ds_ctools_content($action = 'add', $entity_type = '', $field_name = '', $type_name = '', $subtype_name = '', $step = NULL) {
1334

    
1335
  ctools_include('modal');
1336
  ctools_include('ajax');
1337
  ctools_include('content');
1338
  ctools_include('object-cache');
1339

    
1340
  $commands = array();
1341
  $content_type = ctools_get_content_type($type_name);
1342
  $subtype = ctools_content_get_subtype($content_type, $subtype_name);
1343

    
1344
  if ($data = ctools_object_cache_get($field_name, $field_name)) {
1345
    $conf = $data;
1346
  }
1347
  else {
1348
    $conf = ctools_content_get_defaults($content_type, $subtype);
1349
  }
1350

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

    
1362
  // Get entity context.
1363
  $contexts = ds_get_entity_context($entity_type);
1364

    
1365
  $form_state = array(
1366
    'contexts' => $contexts,
1367
    'ajax' => TRUE,
1368
    'modal' => TRUE,
1369
    'modal return' => TRUE,
1370
    'field_name' => $field_name,
1371
  );
1372

    
1373
  // Call the content form.
1374
  $output = ctools_content_form($action, $form_info, $form_state, $content_type, $subtype_name, $subtype, $conf, $step);
1375

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

    
1402
  print ajax_render($commands);
1403
  ajax_footer();
1404
  exit;
1405
}
1406

    
1407
/**
1408
 * Handle the 'next' click on the add/edit field form wizard.
1409
 */
1410
function ds_ctools_content_next(&$form_state) {
1411
  ctools_object_cache_set($form_state['field_name'], $form_state['field_name'], $form_state['conf']);
1412
}
1413

    
1414
/**
1415
 * Select content.
1416
 *
1417
 * @param $contexts
1418
 *   A collection of contexts, usually the entity.
1419
 * @param $field_name
1420
 *   The name of the field.
1421
 * @param $action
1422
 *   The name of the action.
1423
 * @param $entity_type
1424
 *   The name of the entity type.
1425
 */
1426
function ds_ctools_content_select($contexts, $field_name, $action, $entity_type) {
1427

    
1428
  // Get content types.
1429
  $content_types = ctools_content_get_available_types($contexts);
1430

    
1431
  $categories = $category_names = $ordered = array();
1432

    
1433
  foreach ($content_types as $type_name => $subtypes) {
1434
    foreach ($subtypes as $subtype_name => $content_type) {
1435
      list($category_key, $category) = ds_ctools_get_category($content_type);
1436

    
1437
      if (empty($categories[$category_key])) {
1438
        $categories[$category_key] = array(
1439
          'title' => $category,
1440
          'content' => array(),
1441
        );
1442
        $category_names[$category_key] = $category;
1443
      }
1444

    
1445
      $content_title = filter_xss_admin($content_type['title']);
1446

    
1447
      // Ensure content with the same title doesn't overwrite each other.
1448
      while (isset($categories[$category_key]['content'][$content_title])) {
1449
        $content_title .= '-';
1450
      }
1451

    
1452
      $categories[$category_key]['content'][$content_title] = $content_type;
1453
      $categories[$category_key]['content'][$content_title]['type_name'] = $type_name;
1454
      $categories[$category_key]['content'][$content_title]['subtype_name'] = $subtype_name;
1455
    }
1456
  }
1457

    
1458
  // Now sort
1459
  natcasesort($category_names);
1460
  foreach ($category_names as $category => $name) {
1461
    $ordered[$category] = $categories[$category];
1462
  }
1463

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

    
1487
  // Create output.
1488
  $output = '<div id="ctools-content-selection">';
1489
  $output .= '<div id="ds-left">' . $left . '</div>';
1490
  $output .= '<div id="ds-right">' . $right . '</div>';
1491
  $output .= '</div>';
1492

    
1493
  return ctools_modal_command_display(t('Select content'), $output);
1494
}
1495

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

    
1515
  return array(preg_replace('/[^a-z0-9]/', '-', drupal_strtolower($category)), $category);
1516
}
1517

    
1518
/**
1519
 * Add fake field group value in.
1520
 */
1521
function _ds_field_group_field_ui_fix_notices($form, &$form_state) {
1522
  $field_group = array(
1523
    'group_name' => '',
1524
    'label' => '',
1525
  );
1526
  $form_state['values']['fields']['_add_new_group'] = $field_group;
1527
}
1528

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

    
1543
  $layout_options = array();
1544
  $ds_layouts = ds_get_layout_info();
1545
  $layout_options = array('' => t('- None -'));
1546
  foreach ($ds_layouts as $key => $layout) {
1547
    $optgroup = 'Display Suite';
1548

    
1549
    // Panels can not be used on Views fields and forms.
1550
    if (!empty($layout['module']) && $layout['module'] == 'panels' && isset($form_state['no_panels'])) {
1551
      continue;
1552
    }
1553

    
1554
    // Create new layout option group.
1555
    if (!empty($layout['module'])) {
1556
      $optgroup = drupal_ucfirst($layout['module']);
1557
    }
1558

    
1559
    if (!isset($layout_options[$optgroup])) {
1560
      $layout_options[$optgroup] = array();
1561
    }
1562

    
1563
    // Stack the layout.
1564
    $layout_options[$optgroup][$key] = $layout['label'];
1565
  }
1566

    
1567
  // If there is only one $optgroup, move it to the root.
1568
  if (count($layout_options) == 2) {
1569
    $options = $layout_options[$optgroup];
1570
    $layout_options = array_merge(array('' => t('- None -')), $options);
1571
  }
1572

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

    
1583
  ctools_include('export');
1584
  $layout = new stdClass();
1585
  $ds_layout_settings = ctools_export_crud_load_all('ds_layout_settings');
1586
  if (isset($ds_layout_settings[$form['#export_id']])) {
1587
    $layout = $ds_layout_settings[$form['#export_id']];
1588
  }
1589

    
1590
  if (!empty($layout) && isset($layout->layout) && isset($ds_layouts[$layout->layout]) && empty($layout->disabled)) {
1591
    $layout->settings = $layout->settings;
1592
    $layout->regions = $ds_layouts[$layout->layout]['regions'];
1593
    $form['#ds_layout'] = $layout;
1594
  }
1595

    
1596

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

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

    
1620
  // Load the layout preview form
1621
  $layout->layout_options = $layout_options;
1622
  _ds_field_ui_table_layouts_preview($form, $form_state, $ds_layouts, $layout, $entity_type, $bundle, $view_mode);
1623

    
1624
  if (!empty($layout) && isset($layout->regions)) {
1625

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

    
1643
    // Hide the fieldset in case of the reset layout.
1644
    if ($layout->layout === 'ds_reset') {
1645
      $form['additional_settings']['region_wrapper']['#access'] = FALSE;
1646
    }
1647

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

    
1657
    $form['additional_settings']['region_wrapper']['layout_wrapper'] = array(
1658
      '#type' => 'select',
1659
      '#options' => $wrapper_options,
1660
      '#title' => t('Layout wrapper'),
1661
      '#default_value' => isset($layout->settings['layout_wrapper']) ? $layout->settings['layout_wrapper'] : 'div',
1662
      '#weight' => 10,
1663
    );
1664

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

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

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

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

    
1726

    
1727

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

    
1738
    $classes_access = (user_access('admin_classes') && module_exists('ds_ui'));
1739
    $classes = _ds_classes();
1740
    if (!empty($classes)) {
1741

    
1742
      $form['additional_settings']['ds_classes']['layout_class'] = array(
1743
        '#type' => 'select',
1744
        '#multiple' => TRUE,
1745
        '#options' => $classes,
1746
        '#title' => t('Class for layout'),
1747
        '#default_value' => isset($layout->settings['classes']['layout_class']) ? $layout->settings['classes']['layout_class'] : '',
1748
      );
1749

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

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

    
1792
      if (!empty($options)) {
1793

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

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

    
1823
  $form['additional_settings']['ds_layouts']['old_layout'] = array(
1824
    '#type' => 'value',
1825
    '#value' => isset($layout->layout) ? $layout->layout : 0,
1826
  );
1827

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

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

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

    
1874
  $form['additional_settings']['ds_layouts']['preview'] = array(
1875
    '#type' => 'container',
1876
    '#prefix' => '<div id="ds_layout_wrapper">',
1877
    '#suffix' => '</div>',
1878
    '#weight' => -3,
1879
  );
1880

    
1881
  if (isset($layout->layout) || isset($form_state['values']['additional_settings']['layout'])) {
1882
    $layout_string = isset($form_state['values']['additional_settings']['layout']) ? $form_state['values']['additional_settings']['layout'] : $layout->layout;
1883
  }
1884

    
1885
  if (!empty($layout_string)) {
1886
    $chosen_layout = $ds_layouts[$layout_string];
1887

    
1888
    if (empty($chosen_layout['flexible'])) {
1889

    
1890
      $selected = '<strong>' . $chosen_layout['label'] . '</strong>';
1891
      $selected .= '<br/>' . t('The default template can be found in %path', array('%path' => $chosen_layout['path']));
1892
      $suggestions = t('Template suggestions') . ':<ul>';
1893
      $suggestions_array = array();
1894

    
1895
      $suggestions_array[0] = $layout_string . '--' . $entity_type;
1896
      $suggestions_array[2] = $layout_string . '--' . $entity_type . '-' . $bundle;
1897
      if (!isset($form_state['no_view_mode_suggestions']) && $view_mode != 'default') {
1898
        $suggestions_array[1] = $layout_string . '--' . $entity_type . '-' . $view_mode;
1899
        $suggestions_array[3] = $layout_string . '--' . $entity_type . '-' . $bundle . '-' . $view_mode;
1900
      }
1901

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

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

    
1918
      $form['additional_settings']['ds_layouts']['preview'] ['title'] = array(
1919
        '#markup' => '<div class="ds-layout-preview-title">' . $current_layout . '</div>',
1920
      );
1921
      $form['additional_settings']['ds_layouts']['preview'] ['image'] = array(
1922
        '#markup' => '<div class="ds-layout-preview-image"><img src="' . base_path() . $image . '"/></div>',
1923
      );
1924
      $form['additional_settings']['ds_layouts']['preview']['info'] = array(
1925
        '#type' => 'container',
1926
        '#attributes' => array(
1927
          'class' => array('ds-layout-preview-suggestion'),
1928
        ),
1929
      );
1930
      $form['additional_settings']['ds_layouts']['preview']['info']['suggestions'] = array(
1931
        '#markup' => '<p>' . $selected . '</p><p>' . t('!suggestions', array('!suggestions' => strtr($suggestions, '_', '-'))) . '</p>',
1932
      );
1933

    
1934
      if (!empty($chosen_layout['css'])) {
1935
        $disable_css = FALSE;
1936
        if (isset($layout->settings['layout_disable_css'])) {
1937
          $disable_css = $layout->settings['layout_disable_css'];
1938
        }
1939
        if (isset($form_state['values']) && $disable_css !== $form_state['values']['additional_settings']['ds_layouts']['preview']['info']['settings']['disable_css']) {
1940
          $disable_css = $form_state['values']['additional_settings']['ds_layouts']['preview']['info']['settings']['disable_css'];
1941
        }
1942

    
1943
        $form['additional_settings']['ds_layouts']['preview']['info']['settings']['disable_css'] = array(
1944
          '#type' => 'checkbox',
1945
          '#title' => t('Disable layout CSS styles'),
1946
          '#default_value' => $disable_css,
1947
        );
1948
      }
1949
    }
1950

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

    
1953
      // Get admin path.
1954
      $admin_path = _field_ui_bundle_admin_path($entity_type, $bundle);
1955
      if ($view_mode != 'form') {
1956
        $admin_path .= '/display';
1957
      }
1958
      else {
1959
        $admin_path .= '/fields';
1960
      }
1961

    
1962
      // If regions aren't set we don't have to move fields.
1963
      if (isset($layout->regions)) {
1964
        $url = 'admin/structure/ds/change-layout/' . $entity_type . '/' . $bundle . '/' . $view_mode . '/' . $layout_string . '?destination=' . $admin_path;
1965
        $form['#validate'][] = 'ds_field_ui_change_layout_validate';
1966
      }
1967
      else {
1968
        $url = $admin_path;
1969
      }
1970

    
1971
      if ($view_mode != 'default' && $view_mode != 'form') {
1972
        $url .= '/' . $view_mode;
1973
      }
1974

    
1975
      $form['layout_changed_url'] = array(
1976
        '#type' => 'value',
1977
        '#value' => $url,
1978
      );
1979

    
1980
      $form['#submit'][] = 'ds_field_ui_change_layout_submit';
1981
    }
1982
  }
1983
}
1984

    
1985
/**
1986
 * Ajax callback for _ds_field_ui_table_layouts_preview().
1987
 */
1988
function ds_field_ui_table_layouts_preview_callback($form, $form_state) {
1989
  return $form['additional_settings']['ds_layouts']['preview'];
1990
}
1991

    
1992
/**
1993
 * Form validation handler for _ds_field_ui_table_layouts_preview().
1994
 */
1995
function ds_field_ui_change_layout_validate(&$form, &$form_state) {
1996
  $key1 = array_search('ds_field_ui_layouts_save', $form['#submit']);
1997
  $key2 = array_search('ds_field_ui_fields_save', $form['#submit']);
1998
  unset($form['#submit'][$key1]);
1999
  unset($form['#submit'][$key2]);
2000
}
2001

    
2002
/**
2003
 * Form submission handler for _ds_field_ui_table_layouts_preview().
2004
 */
2005
function ds_field_ui_change_layout_submit($form, &$form_state) {
2006
  $values = $form_state['values'];
2007
  if (isset($values['additional_settings']['preview']['info']['settings']['disable_css'])) {
2008
    $disable_css = $values['additional_settings']['preview']['info']['settings']['disable_css'];
2009
  }
2010
  else {
2011
    $disable_css = FALSE;
2012
  }
2013

    
2014
  $record = db_select('ds_layout_settings')
2015
    ->fields('ds_layout_settings')
2016
    ->condition('entity_type', $values['ds_entity_type'])
2017
    ->condition('bundle', $values['ds_bundle'])
2018
    ->condition('view_mode', $values['ds_view_mode'])
2019
    ->execute()
2020
    ->fetchObject();
2021

    
2022
  $record->settings = unserialize($record->settings);
2023
  $record->settings['layout_disable_css'] = $disable_css;
2024

    
2025
  drupal_write_record('ds_layout_settings', $record, array('id'));
2026

    
2027
  unset($_GET['destination']);
2028
  global $base_url;
2029
  $url = $base_url . '/' . $values['layout_changed_url'];
2030
  $form_state['redirect'] = $url;
2031
}
2032

    
2033
/**
2034
 * Add the fields to the Field UI form.
2035
 *
2036
 * @param $entity_type
2037
 *   The name of the entity type.
2038
 * @param $bundle
2039
 *   The name of the bundle
2040
 * @param $view_mode
2041
 *   The name of the view_mode
2042
 * @param $form
2043
 *   A collection of form properties.
2044
 * @param $form_state
2045
 *   A collection of form_state properties.
2046
 */
2047
function _ds_field_ui_fields($entity_type, $bundle, $view_mode, &$form, &$form_state) {
2048

    
2049
  // Do not add the fields if there is no layout.
2050
  if (!isset($form['#ds_layout'])) {
2051
    return;
2052
  }
2053

    
2054
  // Get the fields and put them on the form.
2055
  $fields = ds_get_fields($entity_type, FALSE);
2056

    
2057
  // Ultimate alter on Field UI fields, only used for edge cases.
2058
  $context = array(
2059
    'entity_type' => $entity_type,
2060
    'bundle' => $bundle,
2061
    'view_mode' => $view_mode,
2062
  );
2063
  // Load views file if entity type is not ds_views.
2064
  // We need to cache the hook it's implementing.
2065
  if ($entity_type != 'ds_views' && module_exists('ds_extras') && variable_get('ds_extras_vd', FALSE)) {
2066
    module_load_include('inc', 'ds_extras', 'includes/ds_extras.vd');
2067
  }
2068
  drupal_alter('ds_fields_ui', $fields, $context);
2069

    
2070
  // Get field settings.
2071
  $field_settings = ds_get_field_settings($entity_type, $bundle, $view_mode, FALSE);
2072
  $form['#field_settings'] = $field_settings;
2073

    
2074
  $table = &$form['fields'];
2075
  $form['#ds_fields'] = array();
2076

    
2077
  $field_label_options = array(
2078
    'above' => t('Above'),
2079
    'inline' => t('Inline'),
2080
    'hidden' => t('<Hidden>'),
2081
  );
2082
  drupal_alter('ds_label_options', $field_label_options);
2083

    
2084
  // Regions for fields.
2085
  $field_regions = array();
2086
  if (isset($form['#ds_layout']->settings['fields'])) {
2087
    $field_regions = $form['#ds_layout']->settings['fields'];
2088
  }
2089

    
2090
  foreach ($fields as $key => $field) {
2091

    
2092
    // Check on ui_limit.
2093
    if (!empty($field['ui_limit'])) {
2094

    
2095
      $continue = TRUE;
2096
      foreach ($field['ui_limit'] as $limitation) {
2097
        list($limit_bundle, $limit_view_mode) = explode('|', $limitation);
2098
        if ($limit_bundle == '*' || $limit_bundle == $bundle) {
2099
          if ($limit_view_mode == '*' || $limit_view_mode == $view_mode) {
2100
            $continue = FALSE;
2101
          }
2102
        }
2103
      }
2104

    
2105
      if ($continue) {
2106
        continue;
2107
      }
2108
    }
2109

    
2110
    $form['#ds_fields'][] = $key;
2111

    
2112
    // Check on formatter settings.
2113
    if (isset($form_state['formatter_settings'][$key])) {
2114
      $field['formatter_settings'] = $form_state['formatter_settings'][$key];
2115
    }
2116
    elseif (isset($field_settings[$key]['formatter_settings'])) {
2117
      $field['formatter_settings'] = $field_settings[$key]['formatter_settings'];
2118
      $form_state['formatter_settings'][$key] = $field['formatter_settings'];
2119
    }
2120

    
2121
    if (!isset($field_settings[$key]['ft']) && isset($field_settings[$key]['ft'])) {
2122
      $form_state['formatter_settings'][$key]['ft'] = $field_settings[$key]['ft'];
2123
    }
2124

    
2125
    $value = isset($form_state['formatter_settings']) ? $form_state['formatter_settings'] : array();
2126

    
2127
    $hidden = array('hidden' => t('<Hidden>'));
2128
    $formatters = isset($field['properties']['formatters']) ? $hidden + $field['properties']['formatters'] : $hidden + array('default' => t('Default'));
2129

    
2130
    $table[$key] = array(
2131
      '#row_type' => 'field',
2132
      '#js_settings' => array('field'),
2133
      '#region_callback' => 'field_ui_display_overview_row_region',
2134
      '#attributes' => array('class' => array('draggable', 'tabledrag-leaf')),
2135
      'human_name' => array(
2136
        '#markup' => check_plain($field['title']),
2137
      ),
2138
      'weight' => array(
2139
        '#type' => 'textfield',
2140
        '#default_value' => isset($field_settings[$key]['weight']) ? $field_settings[$key]['weight'] : 0,
2141
        '#size' => 3,
2142
        '#attributes' => array('class' => array('field-weight')),
2143
      ),
2144
      'parent_wrapper' => array(
2145
        'parent' => array(
2146
          '#type' => 'select',
2147
          '#empty_value' => '',
2148
          '#options' => array(),
2149
          '#attributes' => array('class' => array('field-parent')),
2150
          '#parents' => array('fields', $key, 'parent'),
2151
        ),
2152
        'hidden_name' => array(
2153
          '#type' => 'hidden',
2154
          '#default_value' => $key,
2155
          '#attributes' => array('class' => array('field-name')),
2156
        ),
2157
      ),
2158
      'label' => array(
2159
        '#type' => 'select',
2160
        '#options' => $field_label_options,
2161
        '#default_value' => isset($field_settings[$key]['label']) ? $field_settings[$key]['label'] : 'hidden',
2162
      ),
2163
      'format' => array(
2164
        'type' => array(
2165
          '#type' => 'select',
2166
          '#options' => $formatters,
2167
          '#default_value' => isset($field_settings[$key]['format']) ? $field_settings[$key]['format'] : 'hidden',
2168
          '#attributes' => array('class' => array('field-formatter-type')),
2169
        ),
2170
      ),
2171
      'settings_summary' => array(),
2172
      'settings_edit' => array(),
2173
    );
2174

    
2175
    // Don't show summary or cogwheel in hidden region.
2176
    if (_ds_field_ui_check_hidden_region($key, $form_state, $field_regions)) {
2177
      continue;
2178
    }
2179

    
2180
    $field['name'] = $key;
2181
    $field['entity_type'] = $entity_type;
2182
    $field['bundle'] = $bundle;
2183
    $field['view_mode'] = $view_mode;
2184

    
2185
    if ($form_state['formatter_settings_edit'] == $key) {
2186
      $table[$key]['settings_summary']['#attributes']['colspan'] = 2;
2187
      $settings_form = ds_field_settings_form($field, $form_state, $form, $view_mode);
2188
      ds_field_row_form_format_construct($table, $key, $settings_form);
2189
    }
2190
    else {
2191
      // After saving, the settings are updated here as well. First we create
2192
      // the element for the table cell.
2193
      $summary = ds_field_settings_summary($field, $form_state, $form, $view_mode);
2194

    
2195
      if (isset($summary)) {
2196
        $table[$key]['settings_summary'] = $summary;
2197
        ds_field_row_form_format_summary_construct($table, $key);
2198
      }
2199
    }
2200
  }
2201

    
2202
  // Add fields submit handler.
2203
  $form['#submit'][] = 'ds_field_ui_fields_save';
2204
}
2205

    
2206
/**
2207
 * Alter the core field on the the Field UI form.
2208
 *
2209
 * @param $entity_type
2210
 *   The name of the entity type.
2211
 * @param $bundle
2212
 *   The name of the bundle
2213
 * @param $view_mode
2214
 *   The name of the view_mode
2215
 * @param $form
2216
 *   A collection of form properties.
2217
 * @param $form_state
2218
 *   A collection of form_state properties.
2219
 */
2220
function _ds_field_ui_core_fields($entity_type, $bundle, $view_mode, &$form, &$form_state) {
2221
  $entity_type = $form['#entity_type'];
2222
  $bundle = $form['#bundle'];
2223
  $view_mode = $form['#view_mode'];
2224

    
2225
  // Gather type information.
2226
  $instances = field_info_instances($entity_type, $bundle);
2227

    
2228
  $field_types = field_info_field_types();
2229
  $extra_fields = field_info_extra_fields($entity_type, $bundle, 'display');
2230

    
2231
  $table = &$form['fields'];
2232

    
2233
  // Regions for fields.
2234
  $field_regions = array();
2235
  if (isset($form['#ds_layout']->settings['fields'])) {
2236
    $field_regions = $form['#ds_layout']->settings['fields'];
2237
  }
2238

    
2239
  // Field rows.
2240
  foreach ($instances as $key => $instance) {
2241

    
2242
    // Don't show summary or cogwheel in hidden region.
2243
    if (_ds_field_ui_check_hidden_region($key, $form_state, $field_regions)) {
2244
      $table[$key]['settings_summary']['#markup'] = '';
2245
      $table[$key]['settings_edit'] = array();
2246
      continue;
2247
    }
2248

    
2249
    $field = field_info_field($instance['field_name']);
2250
    $display = $instance['display'][$view_mode];
2251

    
2252
    // Check the currently selected formatter, and merge persisted values for
2253
    // formatter settings.
2254
    if (isset($form_state['values']['fields'][$key]['type'])) {
2255
      $formatter_type = $form_state['values']['fields'][$key]['type'];
2256
    }
2257
    else {
2258
      $formatter_type = $display['type'];
2259
    }
2260

    
2261
    $settings = $display['settings'];
2262
    if (isset($form_state['formatter_settings'][$key])) {
2263
      $settings = array_merge($settings, $form_state['formatter_settings'][$key]);
2264
    }
2265
    $settings += field_info_formatter_settings($formatter_type);
2266

    
2267
    // Import field settings and merge with Field API settings.
2268
    if (!isset($form_state['formatter_settings'][$key]) && !empty($form['#field_settings'][$key]['formatter_settings']['ft'])) {
2269
      $form_state['formatter_settings'][$key] = $settings;
2270
      $form_state['formatter_settings'][$key]['ft'] = $form['#field_settings'][$key]['formatter_settings']['ft'];
2271
    }
2272

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

    
2277
    $instance['display'][$view_mode]['type'] = $formatter_type;
2278
    $formatter = field_info_formatter_types($formatter_type);
2279
    $instance['display'][$view_mode]['module'] = $formatter['module'];
2280
    $instance['display'][$view_mode]['settings'] = $settings;
2281

    
2282
    // Base button element for the various formatter settings actions.
2283
    $base_button = array(
2284
      '#submit' => array(
2285
        'field_ui_display_overview_multistep_submit',
2286
      ),
2287
      '#ajax' => array(
2288
        'callback' => 'field_ui_display_overview_multistep_js',
2289
        'wrapper' => 'field-display-overview-wrapper',
2290
        'effect' => 'fade',
2291
      ),
2292
      '#field_name' => $key,
2293
    );
2294

    
2295
    if ($form_state['formatter_settings_edit'] == $key) {
2296
      $formatter_type = $form_state['complete form']['fields'][$key]['format']['type']['#default_value'];
2297
      $formatter = field_info_formatter_types($formatter_type);
2298
      $instance['display'][$view_mode]['type'] = $formatter_type;
2299
      $instance['display'][$view_mode]['module'] = $formatter['module'];
2300
      $instance['display'][$view_mode]['settings'] = $settings + field_info_formatter_settings($formatter_type);
2301
      $function = $formatter['module'] . '_field_formatter_settings_form';
2302

    
2303
      // Add the default formatter settings if any.
2304
      $settings_form = array();
2305
      if (function_exists($function)) {
2306
        $settings_form = $function($field, $instance, $view_mode, $form, $form_state);
2307
      }
2308

    
2309
      // Add the field templates form when needed
2310
      if (module_exists('ds_extras') && variable_get('ds_extras_field_template', FALSE)) {
2311
        $context = array(
2312
          'instance' => $instance,
2313
          'view_mode' => $view_mode,
2314
        );
2315

    
2316
        // Load the form
2317
        module_load_include('inc', 'ds_extras', 'includes/ds_extras.admin');
2318
        if (!is_array($settings_form)) $settings_form = array();
2319
        ds_extras_field_template_settings_form($settings_form, $form_state, $context);
2320
      }
2321

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

    
2334
      if ($settings_form) {
2335
        $table[$key]['format']['#cell_attributes'] = array('colspan' => 3);
2336
        $table[$key]['format']['settings_edit_form'] = array(
2337
          '#type' => 'container',
2338
          '#attributes' => array('class' => array('field-formatter-settings-edit-form')),
2339
          '#parents' => array('fields', $key, 'settings_edit_form'),
2340
          'label' => array(
2341
            '#markup' => t('Format settings:') . ' <span class="formatter-name">' . $formatter['label'] . '</span>',
2342
          ),
2343
          'settings' => $settings_form,
2344
          'actions' => array(
2345
            '#type' => 'actions',
2346
            'save_settings' => $base_button + array(
2347
              '#type' => 'submit',
2348
              '#name' => $key . '_formatter_settings_update',
2349
              '#value' => t('Update'),
2350
              '#op' => 'update',
2351
            ),
2352
            'cancel_settings' => $base_button + array(
2353
              '#type' => 'submit',
2354
              '#name' => $key . '_formatter_settings_cancel',
2355
              '#value' => t('Cancel'),
2356
              '#op' => 'cancel',
2357
              // Do not check errors for the 'Cancel' button, but make sure we
2358
              // get the value of the 'formatter type' select.
2359
              '#limit_validation_errors' => array(array('fields', $key, 'type')),
2360
            ),
2361
          ),
2362
        );
2363
        $table[$key]['#attributes']['class'][] = 'field-formatter-settings-editing';
2364
        $table[$key]['format']['type']['#attributes']['class'] = array('element-invisible');
2365
      }
2366
    }
2367
    else {
2368
      $summary = module_invoke($formatter['module'], 'field_formatter_settings_summary', $field, $instance, $view_mode);
2369

    
2370
      // Allow other modules to alter the formatter summary.
2371
      $context = array(
2372
        'module' => $formatter['module'],
2373
        'formatter' => $formatter,
2374
        'field' => $field,
2375
        'instance' => $instance,
2376
        'view_mode' => $view_mode,
2377
      );
2378
      drupal_alter('field_formatter_settings_summary', $summary, $context);
2379

    
2380
      if (module_exists('ds_extras') && variable_get('ds_extras_field_template', FALSE)) {
2381
        module_load_include('inc', 'ds_extras', 'includes/ds_extras.admin');
2382

    
2383
        // Field template summary
2384
        $functions = module_invoke_all('ds_field_theme_functions_info');
2385
        $default_field_function = variable_get('ft-default', 'theme_field');
2386
        $field_function = isset($form_state['formatter_settings'][$key]['ft']['func']) ? $form_state['formatter_settings'][$key]['ft']['func'] : $default_field_function;
2387

    
2388
        if (!empty($summary)) {
2389
          $summary .= '<br />';
2390
        }
2391
        $summary .= 'Field template: ' . check_plain($functions[$field_function]) . '<br />';
2392
      }
2393

    
2394
      if (!empty($summary)) {
2395
        $table[$key]['settings_summary'] = array();
2396
        $table[$key]['settings_edit'] = array();
2397

    
2398
        $table[$key]['settings_summary'] = array(
2399
          '#markup' => '<div class="field-formatter-summary">' . $summary . '</div>',
2400
          '#cell_attributes' => array('class' => array('field-formatter-summary-cell')),
2401
        );
2402
        // Render the other part of the summary
2403
        ds_field_row_form_format_summary_construct($table, $key);
2404
      }
2405
    }
2406
  }
2407
}
2408

    
2409
/**
2410
 * Helper function to check if we are in a hidden region or not.
2411
 */
2412
function _ds_field_ui_check_hidden_region($key, $form_state, $field_regions) {
2413
  $continue = FALSE;
2414
  if (isset($form_state['input']['fields'][$key]['region'])) {
2415
    if ($form_state['input']['fields'][$key]['region'] == 'hidden') {
2416
      $continue = TRUE;
2417
    }
2418
  }
2419
  elseif (!isset($field_regions[$key]) || $field_regions[$key] == 'hidden') {
2420
    $continue = TRUE;
2421
  }
2422

    
2423
  return $continue;
2424
}
2425

    
2426
/**
2427
 * Helper function for building the formatter settings.
2428
 */
2429
function ds_field_row_form_format_construct(&$table, $key, $settings_form) {
2430

    
2431
  $base_button = array(
2432
    '#submit' => array(
2433
      'field_ui_display_overview_multistep_submit',
2434
    ),
2435
    '#validate' => array(
2436
      'ds_field_ui_fields_validate',
2437
    ),
2438
    '#ajax' => array(
2439
      'callback' => 'field_ui_display_overview_multistep_js',
2440
      'wrapper' => 'field-display-overview-wrapper',
2441
      'effect' => 'fade',
2442
    ),
2443
    '#field_name' => $key,
2444
  );
2445
  $table[$key]['format']['settings_edit'] = array(
2446
    '#type' => 'container',
2447
    '#attributes' => array('class' => array('field-formatter-settings-edit-form')),
2448
    '#parents' => array('fields', $key, 'settings_edit_form'),
2449
    '#weight' => -5,
2450
    // Create a settings form where hooks can pick in.
2451
    'settings' => $settings_form,
2452
    'actions' => array(
2453
      '#type' => 'actions',
2454
      'save_settings' => $base_button + array(
2455
        '#type' => 'submit',
2456
        '#name' => $key . '_formatter_settings_update',
2457
        '#value' => t('Update'),
2458
        '#op' => 'update',
2459
      ),
2460
      'cancel_settings' => $base_button + array(
2461
        '#type' => 'submit',
2462
        '#name' => $key . '_formatter_settings_cancel',
2463
        '#value' => t('Cancel'),
2464
        '#op' => 'cancel',
2465
        // Do not check errors for the 'Cancel' button.
2466
        '#limit_validation_errors' => array(),
2467
      ),
2468
    ),
2469
  );
2470
  $table[$key]['#attributes']['class'][] = 'field-formatter-settings-editing';
2471
  $table[$key]['format']['type']['#attributes']['class'] = array('element-invisible');
2472
}
2473

    
2474
/**
2475
 * Helper function for formatter summary settings.
2476
 */
2477
function ds_field_row_form_format_summary_construct(&$table, $key) {
2478

    
2479
  $base_button = array(
2480
    '#submit' => array('field_ui_display_overview_multistep_submit'),
2481
    '#ajax' => array(
2482
      'callback' => 'field_ui_display_overview_multistep_js',
2483
      'wrapper' => 'field-display-overview-wrapper',
2484
      'effect' => 'fade',
2485
    ),
2486
    '#field_name' => $key,
2487
  );
2488

    
2489
  // Add the configure button.
2490
  $table[$key]['settings_edit'] = $base_button + array(
2491
    '#type' => 'image_button',
2492
    '#name' => $key . '_formatter_settings_edit',
2493
    '#src' => 'misc/configure.png',
2494
    '#attributes' => array('class' => array('field-formatter-settings-edit'), 'alt' => t('Edit')),
2495
    '#op' => 'edit',
2496
    // Do not check errors for the 'Edit' button.
2497
    '#limit_validation_errors' => array(),
2498
    '#prefix' => '<div class="field-formatter-settings-edit-wrapper">',
2499
    '#suffix' => '</div>',
2500
  );
2501
}
2502

    
2503
/**
2504
 * Add tab for adding new fields on the fly.
2505
 *
2506
 * @param $entity_type
2507
 *   The name of the entity type.
2508
 * @param $bundle
2509
 *   The name of the bundle
2510
 * @param $view_mode
2511
 *   The name of the view_mode
2512
 * @param $form
2513
 *   A collection of form properties.
2514
 * @param $form_state
2515
 *   A collection of form_state properties.
2516
 */
2517
function _ds_field_ui_custom_fields($entity_type, $bundle, $view_mode, &$form, $form_state) {
2518

    
2519
  $form['additional_settings']['add_custom_fields'] = array(
2520
    '#type' => 'fieldset',
2521
    '#title' => t('Custom fields'),
2522
    '#description' => t('Click on one of the buttons to create a new field.') . '<p></p>',
2523
    '#access' => user_access('admin_fields'),
2524
  );
2525

    
2526
  // Include the CTools tools that we need.
2527
  ctools_include('ajax');
2528
  ctools_include('modal');
2529

    
2530
  // Add CTools' javascript to the page.
2531
  ctools_modal_add_js();
2532

    
2533
  $field_types = array(
2534
    'custom_field' => t('Add a code field'),
2535
    'manage_ctools' => t('Add a dynamic field'),
2536
  );
2537
  $field_types['manage_block'] = t('Add a block field');
2538
  $field_types['manage_preprocess'] = t('Add a preprocess field');
2539

    
2540
  foreach ($field_types as $field_key => $field_title) {
2541

    
2542
    $form['ctools_add_field_' . $field_key . '_url'] = array(
2543
      '#type' => 'hidden',
2544
      '#attributes' => array('class' => array('ctools_add_field_' . $field_key . '-url')),
2545
      '#value' => url('admin/structure/ds/nojs/add_field/' . $field_key),
2546
    );
2547

    
2548
    $form['additional_settings']['add_custom_fields']['ctools_add_field_' . $field_key] = array(
2549
      '#type' => 'button',
2550
      '#value' => $field_title,
2551
      '#attributes' => array('class' => array('ctools-use-modal')),
2552
      '#id' => 'ctools_add_field_' . $field_key,
2553
    );
2554
  }
2555
  $form['additional_settings']['add_custom_fields']['manage_fields'] = array(
2556
    '#type' => 'link',
2557
    '#title' => 'Manage fields',
2558
    '#href' => 'admin/structure/ds/fields',
2559
    '#prefix' => '<div>',
2560
    '#suffix' => '</div>',
2561
  );
2562
}
2563

    
2564
/**
2565
 * Utility function to check if we need to save anything for this field.
2566
 */
2567
function _ds_field_valid($key, $field, &$form_state, $view_mode = 'default') {
2568
  $continue = FALSE;
2569

    
2570
  // Ignore the Field group module and the region to block plugin.
2571
  if ($key == '_add_new_group' || $key == '_add_new_field' || $key == '_add_new_block_region') {
2572
    $continue = TRUE;
2573
  }
2574

    
2575
  // If the field is in hidden region, do not save. Check if the
2576
  // field has a type key which means it's from Field API and
2577
  // we need to reset that type to 'hidden' so it doesn't get
2578
  // fired by Field API in the frontend.
2579
  if (isset($field['region']) && $field['region'] == 'hidden') {
2580
    if (isset($field['type']) && $view_mode != 'form') {
2581
      $form_state['values']['fields'][$key]['type'] = 'hidden';
2582
    }
2583

    
2584
    // In case of a form, fields will be set with #access to FALSE.
2585
    if ($view_mode != 'form') {
2586
      $continue = TRUE;
2587
    }
2588
  }
2589

    
2590
  return $continue;
2591
}
2592

    
2593
/**
2594
 * Utility function to return CSS classes.
2595
 */
2596
function _ds_classes($name = 'ds_classes_regions') {
2597
  static $classes = array();
2598

    
2599
  if (!isset($classes[$name])) {
2600
    $classes[$name] = array();
2601
    $custom_classes = trim(variable_get($name, ''));
2602
    if (!empty($custom_classes)) {
2603
      $classes[$name][''] = t('None');
2604
      $custom_classes = explode("\n", $custom_classes);
2605
      foreach ($custom_classes as $key => $value) {
2606
        $classes_splitted = explode("|", $value);
2607
        $key = trim($classes_splitted[0]);
2608
        $friendly_name = isset($classes_splitted[1]) ? trim($classes_splitted[1]) : $key;
2609
        $classes[$name][check_plain($key)] = $friendly_name;
2610
      }
2611
    }
2612
    $name_clone = $name; // Prevent the name from being changed.
2613
    drupal_alter('ds_classes', $classes[$name], $name_clone);
2614
  }
2615

    
2616
  return $classes[$name];
2617
}
2618

    
2619
/**
2620
 * Utility function to sort a multidimensional array by a value in a sub-array.
2621
 *
2622
 * @param $a
2623
 *   The array to sort.
2624
 * @param $subkey
2625
 *   The subkey to sort by.
2626
 */
2627
function _ds_sort_fields($a, $subkey) {
2628
  foreach ($a as $k => $v) {
2629
    if (isset($v[$subkey])) {
2630
      $b[$k] = $v[$subkey];
2631
    }
2632
  }
2633
  asort($b);
2634
  foreach ($b as $key => $val) {
2635
    $c[$key] = $a[$key];
2636
  }
2637
  return $c;
2638
}