Projet

Général

Profil

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

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

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
    else {
778
      $record->settings['layout_disable_css'] = FALSE;
779
    }
780

    
781
    $record->settings = $record->settings;
782

    
783
    // Let other modules alter the layout settings.
784
    drupal_alter('ds_layout_settings', $record, $form_state);
785

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

    
794
    // Clear entity info cache.
795
    cache_clear_all('entity_info', 'cache', TRUE);
796
  }
797
}
798

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

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

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

    
830
  if (empty($form_state['layout_saved'])) {
831
    return;
832
  }
833

    
834
  $field_settings = array();
835

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

    
840
    // Field settings.
841
    $field_values = $form_state['values']['fields'][$field];
842

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

    
848
    // Build settings.
849
    $settings = array();
850
    $settings['weight'] = $field_values['weight'];
851
    $settings['label'] = $field_values['label'];
852
    $settings['format'] = $field_values['format']['type'];
853

    
854
    // Any formatter settings.
855
    if (isset($form_state['formatter_settings'][$field])) {
856
      $settings['formatter_settings'] = $form_state['formatter_settings'][$field];
857
    }
858

    
859
    $field_settings[$field] = $settings;
860
  }
861

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

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

    
876
  // Clear the ds_fields cache.
877
  cache_clear_all('ds_fields:', 'cache', TRUE);
878
  cache_clear_all('ds_field_settings', 'cache');
879
}
880

    
881
/**
882
 * Clone a fields layout.
883
 */
884
function ds_field_ui_layout_clone($form, &$form_state) {
885

    
886
  $clone = $form_state['values']['additional_settings']['clone'];
887
  $entity_type = $form['#entity_type'];
888
  $bundle = $form['#bundle'];
889
  $view_mode = $form['#view_mode'];
890

    
891
  ctools_include('export');
892
  $layout = ctools_export_crud_load('ds_layout_settings', $clone);
893

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

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

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

    
918
    // Let other modules alter the layout settings.
919
    drupal_alter('ds_layout_settings', $record, $form_state);
920

    
921
    // Save layout record.
922
    drupal_write_record('ds_layout_settings', $record);
923

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

    
928
    // Clear entity info cache.
929
    cache_clear_all('entity_info', 'cache', TRUE);
930

    
931
    // Show message.
932
    drupal_set_message(t('The layout has been cloned.'));
933

    
934
  }
935
  else {
936
    drupal_set_message(t('No layout was cloned.'));
937
  }
938
}
939

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

    
948
  $settings = field_bundle_settings($entity_type, $bundle);
949

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

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

    
968
  // Save the settings.
969
  field_bundle_settings($entity_type, $bundle, $settings);
970
}
971

    
972
/**
973
 * Implements hook_field_formatter_settings_form().
974
 */
975
function ds_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
976

    
977
  $display = $instance['display'][$view_mode];
978
  $settings = $display['settings'];
979

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

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

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

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

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

    
1059
  return $summary;
1060
}
1061

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

    
1073
  $summary = '';
1074

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

    
1080
  if (module_exists('ds_extras') && variable_get('ds_extras_field_template', FALSE)) {
1081
    module_load_include('inc', 'ds_extras', 'includes/ds_extras.admin');
1082

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

    
1089
      $summary .= 'Field template: ' . check_plain($functions[$field_function]) . '<br />';
1090
    }
1091
  }
1092

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

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

    
1120
  if (empty($summary)) {
1121
    return NULL; // no summary return nothing
1122
  }
1123

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

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

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

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

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

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

    
1188
  return $form;
1189
}
1190

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

    
1200
    // Ignore Field Formatter conditions.
1201
    if ($key == 'conditions') {
1202
      continue;
1203
    }
1204

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

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

    
1222
  return $summary;
1223
}
1224

    
1225
/**
1226
 * Implements hook_ds_field_settings_form().
1227
 */
1228
function ds_ds_field_settings_form($field) {
1229
  $form = array();
1230

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

    
1233
  if (empty($field['properties']['settings'])) {
1234
    return $form;
1235
  }
1236

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

    
1239
    switch ($value['type']) {
1240

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

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

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

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

    
1312
  return $form;
1313
}
1314

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

    
1330
  return ctools_context_get_placeholders_from_argument($arguments);
1331
}
1332

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

    
1338
  ctools_include('modal');
1339
  ctools_include('ajax');
1340
  ctools_include('content');
1341
  ctools_include('object-cache');
1342

    
1343
  $commands = array();
1344
  $content_type = ctools_get_content_type($type_name);
1345
  $subtype = ctools_content_get_subtype($content_type, $subtype_name);
1346

    
1347
  if ($data = ctools_object_cache_get($field_name, $field_name)) {
1348
    $conf = $data;
1349
  }
1350
  else {
1351
    $conf = ctools_content_get_defaults($content_type, $subtype);
1352
  }
1353

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

    
1365
  // Get entity context.
1366
  $contexts = ds_get_entity_context($entity_type);
1367

    
1368
  $form_state = array(
1369
    'contexts' => $contexts,
1370
    'ajax' => TRUE,
1371
    'modal' => TRUE,
1372
    'modal return' => TRUE,
1373
    'field_name' => $field_name,
1374
  );
1375

    
1376
  // Call the content form.
1377
  $output = ctools_content_form($action, $form_info, $form_state, $content_type, $subtype_name, $subtype, $conf, $step);
1378

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

    
1405
  print ajax_render($commands);
1406
  ajax_footer();
1407
  exit;
1408
}
1409

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

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

    
1431
  // Get content types.
1432
  $content_types = ctools_content_get_available_types($contexts);
1433

    
1434
  $categories = $category_names = $ordered = array();
1435

    
1436
  foreach ($content_types as $type_name => $subtypes) {
1437
    foreach ($subtypes as $subtype_name => $content_type) {
1438
      list($category_key, $category) = ds_ctools_get_category($content_type);
1439

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

    
1448
      $content_title = filter_xss_admin($content_type['title']);
1449

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

    
1455
      $categories[$category_key]['content'][$content_title] = $content_type;
1456
      $categories[$category_key]['content'][$content_title]['type_name'] = $type_name;
1457
      $categories[$category_key]['content'][$content_title]['subtype_name'] = $subtype_name;
1458
    }
1459
  }
1460

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

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

    
1490
  // Create output.
1491
  $output = '<div id="ctools-content-selection">';
1492
  $output .= '<div id="ds-left">' . $left . '</div>';
1493
  $output .= '<div id="ds-right">' . $right . '</div>';
1494
  $output .= '</div>';
1495

    
1496
  return ctools_modal_command_display(t('Select content'), $output);
1497
}
1498

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

    
1518
  return array(preg_replace('/[^a-z0-9]/', '-', drupal_strtolower($category)), $category);
1519
}
1520

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

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

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

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

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

    
1562
    if (!isset($layout_options[$optgroup])) {
1563
      $layout_options[$optgroup] = array();
1564
    }
1565

    
1566
    // Stack the layout.
1567
    $layout_options[$optgroup][$key] = $layout['label'];
1568
  }
1569

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

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

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

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

    
1599

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

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

    
1623
  // Load the layout preview form
1624
  $layout->layout_options = $layout_options;
1625
  _ds_field_ui_table_layouts_preview($form, $form_state, $ds_layouts, $layout, $entity_type, $bundle, $view_mode);
1626

    
1627
  if (!empty($layout) && isset($layout->regions)) {
1628

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

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

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

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

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

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

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

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

    
1729

    
1730

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

    
1741
    $classes_access = (user_access('admin_classes') && module_exists('ds_ui'));
1742
    $classes = _ds_classes();
1743
    if (!empty($classes)) {
1744

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

    
1753
      foreach (array_keys($layout->regions) as $region) {
1754
        $form['additional_settings']['ds_classes'][$region] = array(
1755
          '#type' => 'select',
1756
          '#multiple' => TRUE,
1757
          '#options' => $classes,
1758
          '#title' => t('Class for @region', array('@region' => $region)),
1759
          '#default_value' => isset($layout->settings['classes'][$region]) ? $layout->settings['classes'][$region] : '',
1760
        );
1761
      }
1762
      if ($classes_access) {
1763
        $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())));
1764
      }
1765
      elseif (user_access('admin_classes')) {
1766
        $form['additional_settings']['ds_classes']['info'] = array('#markup' => l(t('To manage region and field CSS classes, the Display Suite UI module should be enabled.'), 'admin/modules', array('query' => drupal_get_destination(), 'fragment' => 'edit-modules-display-suite')));
1767
      }
1768
    }
1769
    else {
1770
      if ($classes_access) {
1771
        $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>');
1772
      }
1773
      else {
1774
        $form['additional_settings']['ds_classes']['#access'] = FALSE;
1775
      }
1776
    }
1777
  }
1778
  else {
1779

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

    
1798
      if (!empty($options)) {
1799

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

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

    
1829
  $form['additional_settings']['ds_layouts']['old_layout'] = array(
1830
    '#type' => 'value',
1831
    '#value' => isset($layout->layout) ? $layout->layout : 0,
1832
  );
1833

    
1834
  // Add validate and submit handlers. Layout needs be first so
1835
  // we can reset the type key for Field API fields.
1836
  $form['#validate'][] = 'ds_field_ui_layouts_validate';
1837
  $submit = $form['#submit'];
1838
  $form['#submit'] = array('ds_field_ui_layouts_save');
1839
  $form['#submit'] = array_merge($form['#submit'], $submit);
1840
}
1841

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

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

    
1880
  $form['additional_settings']['ds_layouts']['preview'] = array(
1881
    '#type' => 'container',
1882
    '#prefix' => '<div id="ds_layout_wrapper">',
1883
    '#suffix' => '</div>',
1884
    '#weight' => -3,
1885
  );
1886

    
1887
  if (isset($layout->layout) || isset($form_state['values']['additional_settings']['layout'])) {
1888
    $layout_string = isset($form_state['values']['additional_settings']['layout']) ? $form_state['values']['additional_settings']['layout'] : $layout->layout;
1889
  }
1890

    
1891
  if (!empty($layout_string)) {
1892
    $chosen_layout = $ds_layouts[$layout_string];
1893

    
1894
    if (empty($chosen_layout['flexible'])) {
1895

    
1896
      $selected = '<strong>' . $chosen_layout['label'] . '</strong>';
1897
      $selected .= '<br/>' . t('The default template can be found in %path', array('%path' => $chosen_layout['path']));
1898
      $suggestions = t('Template suggestions') . ':<ul>';
1899
      $suggestions_array = array();
1900

    
1901
      $suggestions_array[0] = $layout_string . '--' . $entity_type;
1902
      $suggestions_array[2] = $layout_string . '--' . $entity_type . '-' . $bundle;
1903
      $suggestions_array[4] = $layout_string . '--' . $entity_type . '--{id}';
1904
      if (!isset($form_state['no_view_mode_suggestions']) && $view_mode != 'default') {
1905
        $suggestions_array[1] = $layout_string . '--' . $entity_type . '-' . $view_mode;
1906
        $suggestions_array[3] = $layout_string . '--' . $entity_type . '-' . $bundle . '-' . $view_mode;
1907
      }
1908

    
1909
      ksort($suggestions_array);
1910
      $suggestions .= '<ul><li>' . implode('.tpl.php</li><li>', $suggestions_array) . '.tpl.php</li></ul>';
1911
    }
1912
    else {
1913
      $suggestions = '';
1914
      $selected = t('You have selected the flexible %layout_label layout.', array('%layout_label' => $chosen_layout['label'], '%path' => $chosen_layout['path']));
1915
    }
1916

    
1917
    if (isset($form_state['values']['additional_settings']['layout']) || (!empty($layout) && isset($layout->regions))) {
1918
      $fallback_image = drupal_get_path('module', 'ds') . '/images/preview.png';
1919
      $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');
1920
      $image = (isset($chosen_layout['image']) && !empty($chosen_layout['image'])) ? $chosen_layout['path'] . '/' . $layout_string . '.png' : $fallback_image;
1921
      if (isset($chosen_layout['panels']) && !empty($chosen_layout['panels']['icon'])) {
1922
        $image = $chosen_layout['panels']['path'] . '/' . $chosen_layout['panels']['icon'];
1923
      }
1924

    
1925
      $form['additional_settings']['ds_layouts']['preview'] ['title'] = array(
1926
        '#markup' => '<div class="ds-layout-preview-title">' . $current_layout . '</div>',
1927
      );
1928
      $form['additional_settings']['ds_layouts']['preview'] ['image'] = array(
1929
        '#markup' => '<div class="ds-layout-preview-image"><img src="' . base_path() . $image . '"/></div>',
1930
      );
1931
      $form['additional_settings']['ds_layouts']['preview']['info'] = array(
1932
        '#type' => 'container',
1933
        '#attributes' => array(
1934
          'class' => array('ds-layout-preview-suggestion'),
1935
        ),
1936
      );
1937
      $form['additional_settings']['ds_layouts']['preview']['info']['suggestions'] = array(
1938
        '#markup' => '<p>' . $selected . '</p><p>' . t('!suggestions', array('!suggestions' => strtr($suggestions, '_', '-'))) . '</p>',
1939
      );
1940

    
1941
      if (!empty($chosen_layout['css'])) {
1942
        $disable_css = FALSE;
1943
        if (isset($layout->settings['layout_disable_css'])) {
1944
          $disable_css = $layout->settings['layout_disable_css'];
1945
        }
1946

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

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

    
1957
      // Get admin path.
1958
      $admin_path = _field_ui_bundle_admin_path($entity_type, $bundle);
1959
      if ($view_mode != 'form') {
1960
        $admin_path .= '/display';
1961
      }
1962
      else {
1963
        $admin_path .= '/fields';
1964
      }
1965

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

    
1975
      if ($view_mode != 'default' && $view_mode != 'form') {
1976
        $url .= '/' . $view_mode;
1977
      }
1978

    
1979
      $form['layout_changed_url'] = array(
1980
        '#type' => 'value',
1981
        '#value' => $url,
1982
      );
1983

    
1984
      $form['#submit'][] = 'ds_field_ui_change_layout_submit';
1985
    }
1986
  }
1987
}
1988

    
1989
/**
1990
 * Ajax callback for _ds_field_ui_table_layouts_preview().
1991
 */
1992
function ds_field_ui_table_layouts_preview_callback($form, $form_state) {
1993
  return $form['additional_settings']['ds_layouts']['preview'];
1994
}
1995

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

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

    
2018
  $record = db_select('ds_layout_settings')
2019
    ->fields('ds_layout_settings')
2020
    ->condition('entity_type', $values['ds_entity_type'])
2021
    ->condition('bundle', $values['ds_bundle'])
2022
    ->condition('view_mode', $values['ds_view_mode'])
2023
    ->execute()
2024
    ->fetchObject();
2025

    
2026
  $record->settings = unserialize($record->settings);
2027
  $record->settings['layout_disable_css'] = $disable_css;
2028

    
2029
  drupal_write_record('ds_layout_settings', $record, array('id'));
2030

    
2031
  unset($_GET['destination']);
2032
  global $base_url;
2033
  $url = $base_url . '/' . $values['layout_changed_url'];
2034
  $form_state['redirect'] = $url;
2035
}
2036

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

    
2053
  // Do not add the fields if there is no layout.
2054
  if (!isset($form['#ds_layout'])) {
2055
    return;
2056
  }
2057

    
2058
  // Get the fields and put them on the form.
2059
  $fields = ds_get_fields($entity_type, FALSE);
2060

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

    
2074
  // Get field settings.
2075
  $field_settings = ds_get_field_settings($entity_type, $bundle, $view_mode, FALSE);
2076
  $form['#field_settings'] = $field_settings;
2077

    
2078
  $table = &$form['fields'];
2079
  $form['#ds_fields'] = array();
2080

    
2081
  $field_label_options = array(
2082
    'above' => t('Above'),
2083
    'inline' => t('Inline'),
2084
    'hidden' => t('<Hidden>'),
2085
  );
2086
  drupal_alter('ds_label_options', $field_label_options);
2087

    
2088
  // Regions for fields.
2089
  $field_regions = array();
2090
  if (isset($form['#ds_layout']->settings['fields'])) {
2091
    $field_regions = $form['#ds_layout']->settings['fields'];
2092
  }
2093

    
2094
  foreach ($fields as $key => $field) {
2095

    
2096
    // Check on ui_limit.
2097
    if (!empty($field['ui_limit'])) {
2098

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

    
2109
      if ($continue) {
2110
        continue;
2111
      }
2112
    }
2113

    
2114
    $form['#ds_fields'][] = $key;
2115

    
2116
    // Check on formatter settings.
2117
    if (isset($form_state['formatter_settings'][$key])) {
2118
      $field['formatter_settings'] = $form_state['formatter_settings'][$key];
2119
    }
2120
    elseif (isset($field_settings[$key]['formatter_settings'])) {
2121
      $field['formatter_settings'] = $field_settings[$key]['formatter_settings'];
2122
      $form_state['formatter_settings'][$key] = $field['formatter_settings'];
2123
    }
2124

    
2125
    if (!isset($field_settings[$key]['ft']) && isset($field_settings[$key]['ft'])) {
2126
      $form_state['formatter_settings'][$key]['ft'] = $field_settings[$key]['ft'];
2127
    }
2128

    
2129
    $value = isset($form_state['formatter_settings']) ? $form_state['formatter_settings'] : array();
2130

    
2131
    $hidden = array('hidden' => t('<Hidden>'));
2132
    $formatters = isset($field['properties']['formatters']) ? $hidden + $field['properties']['formatters'] : $hidden + array('default' => t('Default'));
2133

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

    
2179
    // Don't show summary or cogwheel in hidden region.
2180
    if (_ds_field_ui_check_hidden_region($key, $form_state, $field_regions)) {
2181
      continue;
2182
    }
2183

    
2184
    $field['name'] = $key;
2185
    $field['entity_type'] = $entity_type;
2186
    $field['bundle'] = $bundle;
2187
    $field['view_mode'] = $view_mode;
2188

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

    
2199
      if (isset($summary)) {
2200
        $table[$key]['settings_summary'] = $summary;
2201
        ds_field_row_form_format_summary_construct($table, $key);
2202
      }
2203
    }
2204
  }
2205

    
2206
  // Add fields submit handler.
2207
  $form['#submit'][] = 'ds_field_ui_fields_save';
2208
}
2209

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

    
2229
  // Gather type information.
2230
  $instances = field_info_instances($entity_type, $bundle);
2231

    
2232
  $field_types = field_info_field_types();
2233
  $extra_fields = field_info_extra_fields($entity_type, $bundle, 'display');
2234

    
2235
  $table = &$form['fields'];
2236

    
2237
  // Regions for fields.
2238
  $field_regions = array();
2239
  if (isset($form['#ds_layout']->settings['fields'])) {
2240
    $field_regions = $form['#ds_layout']->settings['fields'];
2241
  }
2242

    
2243
  // Field rows.
2244
  foreach ($instances as $key => $instance) {
2245

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

    
2253
    $field = field_info_field($instance['field_name']);
2254
    $display = $instance['display'][$view_mode];
2255

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

    
2265
    $settings = $display['settings'];
2266
    if (isset($form_state['formatter_settings'][$key])) {
2267
      $settings = array_merge($settings, $form_state['formatter_settings'][$key]);
2268
    }
2269
    $settings += field_info_formatter_settings($formatter_type);
2270

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

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

    
2281
    $instance['display'][$view_mode]['type'] = $formatter_type;
2282
    $formatter = field_info_formatter_types($formatter_type);
2283
    $instance['display'][$view_mode]['module'] = $formatter['module'];
2284
    $instance['display'][$view_mode]['settings'] = $settings;
2285

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

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

    
2307
      // Add the default formatter settings if any.
2308
      $settings_form = array();
2309
      if (function_exists($function)) {
2310
        $settings_form = $function($field, $instance, $view_mode, $form, $form_state);
2311
      }
2312

    
2313
      // Add the field templates form when needed
2314
      if (module_exists('ds_extras') && variable_get('ds_extras_field_template', FALSE)) {
2315
        $context = array(
2316
          'instance' => $instance,
2317
          'view_mode' => $view_mode,
2318
        );
2319

    
2320
        // Load the form
2321
        module_load_include('inc', 'ds_extras', 'includes/ds_extras.admin');
2322
        if (!is_array($settings_form)) $settings_form = array();
2323
        ds_extras_field_template_settings_form($settings_form, $form_state, $context);
2324
      }
2325

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

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

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

    
2384
      if (module_exists('ds_extras') && variable_get('ds_extras_field_template', FALSE)) {
2385
        module_load_include('inc', 'ds_extras', 'includes/ds_extras.admin');
2386

    
2387
        // Field template summary
2388
        $functions = module_invoke_all('ds_field_theme_functions_info');
2389
        $default_field_function = variable_get('ft-default', 'theme_field');
2390
        $field_function = isset($form_state['formatter_settings'][$key]['ft']['func']) ? $form_state['formatter_settings'][$key]['ft']['func'] : $default_field_function;
2391

    
2392
        if (!empty($summary)) {
2393
          $summary .= '<br />';
2394
        }
2395
        $summary .= 'Field template: ' . check_plain($functions[$field_function]) . '<br />';
2396
      }
2397

    
2398
      if (!empty($summary)) {
2399
        $table[$key]['settings_summary'] = array();
2400
        $table[$key]['settings_edit'] = array();
2401

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

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

    
2427
  return $continue;
2428
}
2429

    
2430
/**
2431
 * Helper function for building the formatter settings.
2432
 */
2433
function ds_field_row_form_format_construct(&$table, $key, $settings_form) {
2434

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

    
2478
/**
2479
 * Helper function for formatter summary settings.
2480
 */
2481
function ds_field_row_form_format_summary_construct(&$table, $key) {
2482

    
2483
  $base_button = array(
2484
    '#submit' => array('field_ui_display_overview_multistep_submit'),
2485
    '#ajax' => array(
2486
      'callback' => 'field_ui_display_overview_multistep_js',
2487
      'wrapper' => 'field-display-overview-wrapper',
2488
      'effect' => 'fade',
2489
    ),
2490
    '#field_name' => $key,
2491
  );
2492

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

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

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

    
2530
  // Include the CTools tools that we need.
2531
  ctools_include('ajax');
2532
  ctools_include('modal');
2533

    
2534
  // Add CTools' javascript to the page.
2535
  ctools_modal_add_js();
2536

    
2537
  $field_types = array(
2538
    'custom_field' => t('Add a code field'),
2539
    'manage_ctools' => t('Add a dynamic field'),
2540
  );
2541
  $field_types['manage_block'] = t('Add a block field');
2542
  $field_types['manage_preprocess'] = t('Add a preprocess field');
2543

    
2544
  foreach ($field_types as $field_key => $field_title) {
2545

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

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

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

    
2574
  // Ignore the Field group module and the region to block plugin.
2575
  if ($key == '_add_new_group' || $key == '_add_new_field' || $key == '_add_new_block_region') {
2576
    $continue = TRUE;
2577
  }
2578

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

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

    
2594
  return $continue;
2595
}
2596

    
2597
/**
2598
 * Utility function to return CSS classes.
2599
 */
2600
function _ds_classes($name = 'ds_classes_regions') {
2601
  static $classes = array();
2602

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

    
2620
  return $classes[$name];
2621
}
2622

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