~spreadubuntu/spreadubuntu/devel-drupal6

« back to all changes in this revision

Viewing changes to modules/cck/modules/content_multigroup/content_multigroup.module

  • Committer: ruben
  • Date: 2009-06-08 09:38:49 UTC
  • Revision ID: ruben@captive-20090608093849-s1qtsyctv2vwp1x1
SpreadUbuntu moving to Drupal6. Based on ubuntu-drupal theme and adding our modules

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
// $Id: content_multigroup.module,v 1.1.2.4 2008/10/22 11:02:41 yched Exp $
 
3
 
 
4
/**
 
5
 * @file
 
6
 * Create complex, repeating groups of CCK fields that work in unison.
 
7
 *
 
8
 * @See README.txt.
 
9
 *
 
10
 */
 
11
 
 
12
function content_multigroup_help($path, $arg) {
 
13
  switch ($path) {
 
14
    case ('admin/help#content_multigroup'):
 
15
      return t('The fields in a Standard group are independent of each other and each can have either single or multiple values. The fields in a Multigroup are treated as a repeating collection of single value fields.');
 
16
  }
 
17
}
 
18
 
 
19
/**
 
20
 * Implementation of hook_init().
 
21
 */
 
22
function content_multigroup_init() {
 
23
  drupal_add_css(drupal_get_path('module', 'content_multigroup') .'/content_multigroup.css');
 
24
}
 
25
 
 
26
/**
 
27
 * Implementation of hook_theme().
 
28
 */
 
29
function content_multigroup_theme() {
 
30
  return array(
 
31
    'content_multigroup_node_form' => array(
 
32
      'arguments' => array('element' => NULL),
 
33
    ),
 
34
    'content_multigroup_node_label' => array(
 
35
      'arguments' => array('text' => NULL),
 
36
    ),
 
37
    'content_multigroup_display_simple' => array(
 
38
      'arguments' => array('element' => NULL),
 
39
    ),
 
40
    'content_multigroup_display_hr' => array(
 
41
      'arguments' => array('element' => NULL),
 
42
    ),
 
43
    'content_multigroup_display_table' => array(
 
44
      'arguments' => array('element' => NULL),
 
45
    ),
 
46
  );
 
47
}
 
48
 
 
49
/**
 
50
 * Implementation of hook_fieldgroup_types().
 
51
 */
 
52
function content_multigroup_fieldgroup_types() {
 
53
  return array('multigroup' => t('Multigroup'));
 
54
}
 
55
 
 
56
/**
 
57
 * Implementation of hook_fieldgroup_default_settings().
 
58
 */
 
59
function content_multigroup_fieldgroup_default_settings($group_type) {
 
60
  if ($group_type == 'multigroup') {
 
61
    module_load_include('inc', 'content', 'includes/content.admin');
 
62
    $settings = array('multigroup' => array('multiple' => 1));
 
63
    foreach (array_keys(content_build_modes()) as $key) {
 
64
      $settings['multigroup']['display_settings'][$key]['format'] = 'fieldset';
 
65
    }
 
66
    return $settings;
 
67
  }
 
68
}
 
69
 
 
70
function content_multigroup_multiple_values() {
 
71
  return array(
 
72
    //'' => t('N/A'),
 
73
    1 => t('Unlimited'),
 
74
    0 => 1) + drupal_map_assoc(range(2, 10));
 
75
}
 
76
 
 
77
/**
 
78
 * Implementation of hook_menu().
 
79
 */
 
80
function content_multigroup_menu() {
 
81
  $items = array();
 
82
  // Callback for AHAH add more buttons.
 
83
  $items['content_multigroup/js_add_more'] = array(
 
84
    'page callback' => 'content_multigroup_add_more_js',
 
85
    'access arguments' => array('access content'),
 
86
    'type' => MENU_CALLBACK,
 
87
  );
 
88
  return $items;
 
89
}
 
90
 
 
91
/**
 
92
 * Implementation of hook_form_alter().
 
93
 */
 
94
function content_multigroup_form_alter(&$form, $form_state, $form_id) {
 
95
  // If this is a field edit form and the field is in a Multigroup,
 
96
  // override the multiple value settings.
 
97
  if ($form_id == 'content_field_edit_form' && isset($form['widget'])) {
 
98
    $content_type = content_types($form['type_name']['#value']);
 
99
    $groups = fieldgroup_groups($content_type['type']);
 
100
    $group_name = _fieldgroup_field_get_group($content_type['type'], $form['field_name']['#value']);
 
101
    $group = isset($groups[$group_name]) ? $groups[$group_name] : array();
 
102
    if (!empty($group) && $group['group_type'] == 'multigroup') {
 
103
      $form['field']['multiple']['#value'] = $group['settings']['multigroup']['multiple'];
 
104
      $form['field']['multiple']['#access'] = FALSE;
 
105
    }
 
106
  }
 
107
  elseif ($form_id == 'content_field_overview_form') {
 
108
    content_multigroup_field_overview_form($form, $form_state);
 
109
    $form['#validate'][] = 'content_multigroup_field_overview_form_validate';
 
110
  }
 
111
  elseif ($form_id == 'content_display_overview_form') {
 
112
    content_multigroup_display_overview_form($form, $form_state, $form_id);
 
113
    $form['#submit'] = array_merge(array('content_multigroup_display_overview_form_submit'), $form['#submit']);
 
114
  }
 
115
  elseif ($form_id == 'fieldgroup_group_edit_form') {
 
116
    return content_multigroup_group_edit_form($form, $form_state, $form_id);
 
117
  }
 
118
}
 
119
 
 
120
function content_multigroup_field_overview_form(&$form, &$form_state) {
 
121
  $options = fieldgroup_types();
 
122
  $options['standard'] = t('Standard');
 
123
  $options['multigroup'] = t('Multigroup');
 
124
  $form['_add_new_group']['group_type'] = array(
 
125
    '#type' => 'select',
 
126
    '#description' => t('Type of group.'),
 
127
    '#options' => $options,
 
128
    '#default_value' => 'standard',
 
129
  );
 
130
}
 
131
 
 
132
/**
 
133
 * Validation for creating/moving fields and groups on the
 
134
 * Manage Fields screen.
 
135
 */
 
136
function content_multigroup_field_overview_form_validate($form, &$form_state) {
 
137
  $form_values = $form_state['values'];
 
138
 
 
139
  $type_name = $form['#type_name'];
 
140
  $fields = array();
 
141
  $groups = array();
 
142
 
 
143
  $group = $form_values['_add_new_group'];
 
144
  if (array_filter(array($group['label'], $group['group_name']))) {
 
145
 
 
146
    $group['settings'] = field_group_default_settings($form_values['_add_new_group']['group_type']);
 
147
    $group = $form_values['_add_new_group'];
 
148
    $validation = fieldgroup_validate_name($group, $form['#type_name']);
 
149
 
 
150
    // If there's something wrong with the new group,
 
151
    // don't bother doing any more validation, further
 
152
    // processing will be stopped by the fieldgroup module.
 
153
    if (!empty($validation['errors'])) {
 
154
      return;
 
155
    }
 
156
    $group['group_name'] = $validation['group_name'];
 
157
    $new_group_name = $group['group_name'];
 
158
    $groups['_add_new_group'] = $group;
 
159
  }
 
160
 
 
161
  // See if we have fields moving into or out of a Multigroup.
 
162
  // Set any fields to use the new name here so they will get processed
 
163
  // correctly by the fieldgroup module when saved.
 
164
  foreach ($form_values as $key => $values) {
 
165
    if ($values['parent'] == '_add_new_group') {
 
166
      $values['parent'] = $new_group_name;
 
167
      $form_values[$key] = $values;
 
168
    }
 
169
 
 
170
    if (!empty($form[$key]['#row_type']) && $form[$key]['#row_type'] == 'group') {
 
171
      // Gather up info about all groups.
 
172
      $group_name = $form_values[$key]['group']['group_name'];
 
173
      $groups[$group_name] = $form_values[$key]['group'];
 
174
    }
 
175
    if (!empty($form[$key]['#row_type']) && $form[$key]['#row_type'] == 'field') {
 
176
      if ($values['prev_parent'] != $values['parent']) {
 
177
        // Gather up fields that have moved in or out of a group.
 
178
        $fields[$key] = $form_values[$key]['field'];
 
179
      }
 
180
    }
 
181
  }
 
182
 
 
183
  if (!empty($fields)) {
 
184
    foreach ($fields as $field_name => $field) {
 
185
      $new_group = $form_values[$field_name]['parent'];
 
186
      $old_group = $form_values[$field_name]['prev_parent'];
 
187
      if (!empty($new_group) && isset($groups[$new_group]) && $groups[$new_group]['group_type'] == 'multigroup') {
 
188
        $allowed_in = content_multigroup_allowed_in($field, $groups[$new_group]);
 
189
        if (!$allowed_in['allowed']) {
 
190
          form_set_error($field_name, $allowed_in['message']);
 
191
        }
 
192
        else {
 
193
          if (!empty($allowed_in['message'])) {
 
194
            drupal_set_message($allowed_in['message']);
 
195
          }
 
196
          module_load_include('inc', 'content', 'includes/content.crud');
 
197
          $content_type = content_types($type_name);
 
198
          $multiple = $groups[$new_group]['settings']['multigroup']['multiple'];
 
199
          $multiple_values = content_multigroup_multiple_values();
 
200
          $field = $content_type['fields'][$field_name];
 
201
          $field['multiple'] = $multiple;
 
202
          $field = content_field_instance_collapse($field);
 
203
          content_field_instance_update($field);
 
204
          drupal_set_message(t('The field %field has been updated to use %multiple values, to match the multiple value setting of the Multigroup %group.', array(
 
205
            '%field' => $field['label'], '%multiple' => $multiple_values[$multiple], '%group' => $groups[$new_group]['label'])));
 
206
        }
 
207
      }
 
208
      elseif (!empty($old_group) && isset($groups[$old_group]) && $groups[$old_group]['group_type'] == 'multigroup') {
 
209
        $allowed_out = content_multigroup_allowed_out($field, $groups[$old_group]);
 
210
        if (!$allowed_out['allowed']) {
 
211
          form_set_error($field_name, $allowed_out['message']);
 
212
        }
 
213
        elseif (!empty($allowed_out['message'])) {
 
214
          drupal_set_message($allowed_out['message']);
 
215
        }
 
216
      }
 
217
    }
 
218
  }
 
219
}
 
220
 
 
221
/**
 
222
 * Helper function for deciding if a field is
 
223
 * allowed into a Multigroup.
 
224
 */
 
225
function content_multigroup_allowed_in($field, $group) {
 
226
  if ($group['group_type'] != 'multigroup') {
 
227
    return array('allowed' => TRUE, 'message' => '');
 
228
  }
 
229
 
 
230
  // We can't allow fields with more multiple values than the group has
 
231
  // to be moved into it.
 
232
  $max_existing = content_max_delta($field['field_name']);
 
233
  $group_max = $group['settings']['multigroup']['multiple'];
 
234
  $multiple_values = content_multigroup_multiple_values();
 
235
  if ($group_max != 1 && $max_existing > $group_max) {
 
236
    return array(
 
237
      'allowed' => FALSE,
 
238
      'message' => t('This change is not allowed. The field %field already has %multiple values in the database but the group %group only allows %group_max. Making this change would result in the loss of data.', array('%field' => $field['widget']['label'], '%multiple' => $max_existing, '%group' => $group['label'], '%group_max' => $multiple_values[$group_max]))
 
239
    );
 
240
  }
 
241
 
 
242
  // Fields that handle their own multiple values may not have the same values
 
243
  // in Multigroup fields and normal fields. We don't know if they will work or not.
 
244
 
 
245
  // Adding a hook here where widgets that handle their own multiple values
 
246
  // that will work correctly in Multigroups can allow their fields in.
 
247
 
 
248
  if (content_handle('widget', 'multiple values', $field) != CONTENT_HANDLE_CORE) {
 
249
    $allowed_widgets = array(
 
250
      'optionwidgets_select',
 
251
      'optionwidgets_buttons',
 
252
      'optionwidgets_onoff',
 
253
      'nodereference_buttons',
 
254
      'nodereference_select',
 
255
      'userreference_buttons',
 
256
      'userreference_select',
 
257
      );
 
258
    $allowed_widgets = array_merge($allowed_widgets, module_invoke_all('content_multigroup_allowed_widgets'));
 
259
    if (!in_array($field['widget']['type'], $allowed_widgets)) {
 
260
      return array(
 
261
        'allowed' => FALSE,
 
262
        'message' => t('This change is not allowed. The field %field handles multiple values differently than the Content module. Making this change could result in the loss of data.', array('%field' => $field['widget']['label']))
 
263
      );
 
264
    }
 
265
  }
 
266
 
 
267
  // Allow other modules to intervene.
 
268
  // Any failure will prevent this action.
 
269
  foreach (module_implements('content_multigroup_allowed_in') as $module) {
 
270
    $function = $module .'_content_multigroup_allowed_in';
 
271
    $result = $function($field, $group);
 
272
    if ($result['allowed'] === FALSE) {
 
273
      return array('allowed' => FALSE, 'message' => $result['message']);
 
274
    }
 
275
  }
 
276
 
 
277
  $message = t('You are moving the field %field into a Multigroup.', array('%field' => $field['widget']['label']));
 
278
  return array('allowed' => TRUE, 'message' => $message);
 
279
}
 
280
 
 
281
/**
 
282
 * Helper function for deciding if a field is
 
283
 * allowed out of a Multigroup.
 
284
 */
 
285
function content_multigroup_allowed_out($field, $group) {
 
286
  if ($group['group_type'] != 'multigroup') {
 
287
    return array('allowed' => TRUE, 'message' => '');
 
288
  }
 
289
  // Optionwidgets do not behave the same in a Multigroup field as out of it.
 
290
  // In a Multigroup the same option can be selected multiple times,
 
291
  // but that is not possible in a normal group.
 
292
 
 
293
  // Adding a hook here where widgets that handle their own multiple values
 
294
  // can indicate their fields should not be removed from Multigroups.
 
295
 
 
296
  $max_existing = content_max_delta($field['field_name']);
 
297
  $no_remove_widgets = array(
 
298
      'optionwidgets_select',
 
299
      'optionwidgets_buttons',
 
300
      'optionwidgets_onoff',
 
301
      'nodereference_buttons',
 
302
      'nodereference_select',
 
303
      'userreference_buttons',
 
304
      'userreference_select',
 
305
      );
 
306
  $no_remove_widgets = array_merge($no_remove_widgets, module_invoke_all('content_multigroup_no_remove_widgets'));
 
307
  if (in_array($field['widget']['type'], $no_remove_widgets) && $max_existing > 0) {
 
308
    return array(
 
309
      'allowed' => FALSE,
 
310
      'message' => t('This change is not allowed. The field %field already has data created and uses a widget that stores data differently in a Standard group than in a Multigroup. Making this change could result in the loss of data.', array('%field' => $field['widget']['label']))
 
311
    );
 
312
  }
 
313
 
 
314
  // Allow other modules to intervene.
 
315
  // Any failure will prevent this action.
 
316
  foreach (module_implements('content_multigroup_allowed_out') as $module) {
 
317
    $function = $module .'_content_multigroup_allowed_out';
 
318
    $result = $function($field, $group);
 
319
    if ($result['allowed'] === FALSE) {
 
320
      return array('allowed' => FALSE, 'message' => $result['message']);
 
321
    }
 
322
  }
 
323
 
 
324
  $message = t('You are moving the field %field out of a Multigroup.', array('%field' => $field['widget']['label']));
 
325
  return array('allowed' => TRUE, 'message' => $message);
 
326
}
 
327
 
 
328
/**
 
329
 * Menu callback; presents a listing of fields display settings for a content type.
 
330
 *
 
331
 * Add an additional selector for setting multigroup field display format.
 
332
 */
 
333
function content_multigroup_display_overview_form(&$form, &$form_state) {
 
334
 
 
335
  $type_name = $form['#type_name'];
 
336
  $contexts_selector = $form['#contexts'];
 
337
 
 
338
  // Gather type information.
 
339
  $type = content_types($type_name);
 
340
  $field_types = _content_field_types();
 
341
  $fields = $type['fields'];
 
342
 
 
343
  $groups = $group_options = array();
 
344
  if (module_exists('fieldgroup')) {
 
345
    $groups = fieldgroup_groups($type['type']);
 
346
    $group_options = _fieldgroup_groups_label($type['type']);
 
347
  }
 
348
  $contexts = content_build_modes($contexts_selector);
 
349
 
 
350
  // Multigroups, extra values.
 
351
  $label_options = array(
 
352
    'above' => t('Above'),
 
353
    'hidden' => t('<Hidden>'),
 
354
  );
 
355
  $options = array(
 
356
    'none' => t('none'),
 
357
    'fieldset' => t('Fieldset'),
 
358
    'hr' => t('Horizontal line'),
 
359
    //'table' => t('Table'), // TODO add this later
 
360
    'hidden' => t('<Hidden>'),
 
361
  );
 
362
  foreach ($groups as $name => $group) {
 
363
    if ($group['group_type'] != 'multigroup') {
 
364
      continue;
 
365
    }
 
366
    $defaults = $group['settings']['multigroup']['display_settings'];
 
367
 
 
368
    $form_name = $name .'_subgroup';
 
369
    $form['#fields'] = array_merge(array($form_name), $form['#fields']);
 
370
    $form[$form_name] = array(
 
371
      'human_name' => array('#value' => t('[Subgroup format]')),
 
372
      'weight' => array('#type' => 'value', '#value' => -20),
 
373
      'parent' => array('#type' => 'value', '#value' => $name),
 
374
    );
 
375
    if ($contexts_selector == 'basic') {
 
376
      $form[$form_name]['label'] = array(
 
377
        '#type' => 'select',
 
378
        '#options' => $label_options,
 
379
        '#default_value' => isset($defaults['label']) ? $defaults['label'] : 'above',
 
380
      );
 
381
    }
 
382
    foreach ($contexts as $key => $title) {
 
383
      $form[$form_name][$key]['format'] = array(
 
384
        '#type' => 'select',
 
385
        '#options' => $options,
 
386
        '#default_value' => isset($defaults[$key]) ? $defaults[$key] : 'fieldset',
 
387
      );
 
388
    }
 
389
  }
 
390
  return $form;
 
391
}
 
392
 
 
393
/**
 
394
 * Submit handler for the display overview form.
 
395
 *
 
396
 * Do this in pre_save so we catch it before the content module
 
397
 * tries to use our 'field'.
 
398
 */
 
399
function content_multigroup_display_overview_form_submit($form, &$form_state) {
 
400
  $form_values = $form_state['values'];
 
401
 
 
402
  // Find any groups we inserted into the display fields form,
 
403
  // save our settings, and remove them from $form_state.
 
404
  foreach ($form_values as $key => $values) {
 
405
    if (in_array($key, $form['#fields']) && substr($key, -9) == '_subgroup') {
 
406
      $group_name = str_replace('_subgroup', '', $key);
 
407
      $groups = fieldgroup_groups($form['#type_name']);
 
408
      $group = $groups[$group_name];
 
409
 
 
410
      // We have some numeric keys here, so we can't use array_merge.
 
411
      foreach ($values as $k => $v) {
 
412
        $group['settings']['multigroup']['display_settings'][$k] = $v;
 
413
      }
 
414
      fieldgroup_save_group($form['#type_name'], $group);
 
415
 
 
416
      // Make sure group information is immediately updated.
 
417
      cache_clear_all('fieldgroup_data', content_cache_tablename());
 
418
      fieldgroup_groups('', FALSE, TRUE);
 
419
      unset($form_state['values'][$key]);
 
420
    }
 
421
  }
 
422
}
 
423
 
 
424
/**
 
425
 * Alter the Fieldgroup edit form
 
426
 * to add Multigroup settings.
 
427
 */
 
428
function content_multigroup_group_edit_form(&$form, &$form_state) {
 
429
  $type_name = $form['#content_type']['type'];
 
430
  $group_name = $form['group_name']['#default_value'];
 
431
 
 
432
  $content_type = content_types($type_name);
 
433
  $groups = fieldgroup_groups($content_type['type']);
 
434
  $group = $groups[$group_name];
 
435
 
 
436
  if ($group['group_type'] != 'multigroup') {
 
437
    return;
 
438
  }
 
439
 
 
440
  module_load_include('inc', 'content', 'includes/content.admin');
 
441
  module_load_include('inc', 'content', 'includes/content.crud');
 
442
  $form['group_type'] = array(
 
443
    '#type' => 'hidden',
 
444
    '#value' => $group['group_type'],
 
445
    );
 
446
  $form['settings']['multigroup'] = array(
 
447
    '#type' => 'fieldset',
 
448
    '#title' => t('Other settings'),
 
449
    '#collapsed' => FALSE,
 
450
    '#collapsible' => TRUE,
 
451
  );
 
452
 
 
453
  $description = t('Number of times to repeat the collection of Multigroup fields.') . ' ';
 
454
  $description .= t("'Unlimited' will provide an 'Add more' button so the users can add repeat it as many times as they like.") . ' ';
 
455
  $description .= t('All fields in this group will automatically be set to allow this number of values.');
 
456
 
 
457
  $multiple = isset($group['settings']['multigroup']['multiple']) ? $group['settings']['multigroup']['multiple'] : 1;
 
458
  $form['settings']['multigroup']['multiple'] = array(
 
459
    '#tree' => TRUE,
 
460
    '#type' => 'select',
 
461
    '#title' => t('Number of repeats'),
 
462
    '#options' => content_multigroup_multiple_values(),
 
463
    '#default_value' => $multiple,
 
464
    '#description' => $description,
 
465
  );
 
466
 
 
467
  $form['settings']['multigroup']['labels'] = array(
 
468
    '#type' => 'fieldset',
 
469
    '#title' => t('Labels'),
 
470
    '#description' => t("Labels for each subgroup of fields. Labels can be hidden or shown in various contexts using the 'Display fields' screen."),
 
471
  );
 
472
  if ($multiple < 2) {
 
473
    $multiple = 0;
 
474
  }
 
475
  for ($i = 0; $i < 10; $i++) {
 
476
    $form['settings']['multigroup']['labels'][$i] = array(
 
477
      '#type' => 'textfield',
 
478
      '#title' => t('Subgroup %number label', array('%number' => $i + 1)),
 
479
      '#default_value' => isset($group['settings']['multigroup']['labels'][$i]) ? $group['settings']['multigroup']['labels'][$i] : '',
 
480
    );
 
481
  }
 
482
 
 
483
  $form['#validate'][] = 'content_multigroup_group_edit_form_validate';
 
484
  $form['#submit'][] = 'content_multigroup_group_edit_form_submit';
 
485
  return $form;
 
486
}
 
487
 
 
488
/**
 
489
 * Validate the Fieldgroup edit form.
 
490
 */
 
491
function content_multigroup_group_edit_form_validate($form, &$form_state) {
 
492
  $form_values = $form_state['values'];
 
493
  $group_type = $form_values['group_type'];
 
494
  if ($group_type != 'multigroup') {
 
495
    return;
 
496
  }
 
497
  $content_type = $form['#content_type'];
 
498
  $groups = fieldgroup_groups($content_type['type']);
 
499
  $group = $groups[$form_values['group_name']];
 
500
  foreach ($group['fields'] as $field_name => $data) {
 
501
    // Make sure we don't set the multiple values to a number that
 
502
    // would result in lost data.
 
503
    $max_existing = content_max_delta($field_name);
 
504
    if ($form_values['settings']['multigroup']['multiple'] != 1
 
505
      && $max_existing > $form_values['settings']['multigroup']['multiple']) {
 
506
      form_set_error('settings][multigroup][multiple', t('The field %field in this group already has %multiple values in the database. To prevent the loss of data you cannot set the number of Multigroup values to less than this.', array('%field' => $data['label'], '%multiple' => $max_existing)));
 
507
    }
 
508
  }
 
509
}
 
510
 
 
511
/**
 
512
 * Submit the Fieldgroup edit form.
 
513
 *
 
514
 * Update multiple values of fields contained in Multigroups.
 
515
 */
 
516
function content_multigroup_group_edit_form_submit($form, &$form_state) {
 
517
  $form_values = $form_state['values'];
 
518
  $group_type = $form_values['group_type'];
 
519
  if ($group_type != 'multigroup') {
 
520
    return;
 
521
  }
 
522
  module_load_include('inc', 'content', 'includes/content.crud');
 
523
  $content_type = $form['#content_type'];
 
524
  $groups = fieldgroup_groups($content_type['type']);
 
525
  $group = $groups[$form_values['group_name']];
 
526
  $multiple = $form_values['settings']['multigroup']['multiple'];
 
527
  foreach ($group['fields'] as $field_name => $data) {
 
528
    $field = $content_type['fields'][$field_name];
 
529
    $field['multiple'] = $multiple;
 
530
    $field = content_field_instance_collapse($field);
 
531
    content_field_instance_update($field);
 
532
  }
 
533
}
 
534
 
 
535
/**
 
536
 * Implementation of hook_fieldgroup_form().
 
537
 *
 
538
 * Align the delta values of each field in the Multigroup.
 
539
 *
 
540
 * Swap the field name and delta for each Multigroup so we can
 
541
 * d-n-d each collection of fields as a single delta item.
 
542
 */
 
543
function content_multigroup_fieldgroup_form(&$form, &$form_state, $form_id, $group) {
 
544
  if ($group['group_type'] != 'multigroup' ||
 
545
    !empty($form[$group['group_name']]['#access']) || empty($form[$group['group_name']])) {
 
546
    return;
 
547
  }
 
548
 
 
549
  $node = $form['#node'];
 
550
  $fields = $group['fields'];
 
551
  $content_fields = content_fields();
 
552
  $group_name = $group['group_name'];
 
553
 
 
554
  // Use the first field in the group to get the item counts.
 
555
  $first_field_name = array_shift(array_keys($group['fields']));
 
556
  $first_field = isset($content_fields[$first_field_name]) ? $content_fields[$first_field_name] : array();
 
557
  $first_field_items = isset($node->$first_field_name) ? $node->$first_field_name : array();
 
558
 
 
559
  $group['multiple'] = $group['settings']['multigroup']['multiple'];
 
560
  switch ($group['multiple']) {
 
561
    case 0:
 
562
      $max = 0;
 
563
      break;
 
564
    case 1:
 
565
      // Is this a new node?
 
566
      if (empty($first_field_items)) {
 
567
        $max = 1;
 
568
      }
 
569
      else {
 
570
        $filled_items = content_set_empty($first_field, $first_field_items);
 
571
        $current_item_count = isset($form_state['item_count'][$group_name])
 
572
                            ? $form_state['item_count'][$group_name]
 
573
                            : count($first_field_items);
 
574
        // We always want at least one empty icon for the user to fill in.
 
575
        $max = ($current_item_count > count($filled_items))
 
576
              ? $current_item_count - 1
 
577
              : count($filled_items);
 
578
      }
 
579
      break;
 
580
    default:
 
581
      $max = $group['multiple'] - 1;
 
582
      break;
 
583
  }
 
584
 
 
585
  $form[$group_name]['#theme'] = 'content_multigroup_node_form';
 
586
  $form[$group_name]['#multiple'] = !empty($max);
 
587
  $form[$group_name]['#type_name'] = $group['type_name'];
 
588
  $form[$group_name]['#group_name'] = $group_name;
 
589
  $form[$group_name]['#group_label'] = $group['label'];
 
590
  $form[$group_name]['#element_validate'] = array('content_multigroup_node_form_validate');
 
591
  $form[$group_name]['#tree'] = TRUE;
 
592
 
 
593
  for ($delta = 0; $delta <= $max; $delta++) {
 
594
    content_multigroup_group_form($form, $form_state, $group, $delta);
 
595
  }
 
596
 
 
597
  // Unset the original group field values now that we've moved them.
 
598
  foreach ($fields as $field_name => $field) {
 
599
    unset($form[$group_name][$field_name]);
 
600
  }
 
601
 
 
602
  if ($add_more = content_multigroup_add_more($form, $form_state, $group)) {
 
603
    $form[$group_name] += $add_more;
 
604
  }
 
605
}
 
606
 
 
607
/**
 
608
 * Create a new delta value for the group.
 
609
 *
 
610
 * Called in form_alter and by AHAH add more.
 
611
 */
 
612
function content_multigroup_group_form(&$form, &$form_state, $group, $delta) {
 
613
  if ($group['group_type'] != 'multigroup' ||
 
614
    !empty($form[$group['group_name']]['#access']) || empty($form[$group['group_name']])) {
 
615
    return;
 
616
  }
 
617
  module_load_include('inc', 'content', 'includes/content.node_form');
 
618
 
 
619
  $node = $form['#node'];
 
620
  $fields = $group['fields'];
 
621
  $content_fields = content_fields();
 
622
  $group_name = $group['group_name'];
 
623
  $group['multiple'] = $group['settings']['multigroup']['multiple'];
 
624
  $form[$group_name]['#fields'] = array_keys($group['fields']);
 
625
 
 
626
  foreach ($fields as $field_name => $group_field) {
 
627
    if (empty($form[$group_name][$delta])) {
 
628
      $form[$group_name] += array($delta => array($field_name => array()));
 
629
    }
 
630
    else {
 
631
      $form[$group_name][$delta][$field_name] = array();
 
632
    }
 
633
 
 
634
    $form[$group_name][$delta]['_weight'] = array(
 
635
      '#type' => 'weight',
 
636
      '#delta' => $delta, // this 'delta' is the 'weight' element's property
 
637
      '#default_value' => $delta,
 
638
      '#weight' => 100,
 
639
    );
 
640
    $form[$group_name][$delta]['_delta'] = array(
 
641
      '#type' => 'hidden',
 
642
      '#value' => $delta,
 
643
    );
 
644
 
 
645
 
 
646
    $field = $content_fields[$field_name];
 
647
 
 
648
    // Make each field into a pseudo single value field
 
649
    // with the right delta value.
 
650
    $field['multiple'] = FALSE;
 
651
 
 
652
    // Make sure new fields after the first have an 'empty' option.
 
653
    $field['required'] = $delta > 0 ? FALSE : $field['required'];
 
654
 
 
655
    $form['#field_info'][$field_name] = $field;
 
656
    $node_copy = drupal_clone($node);
 
657
 
 
658
    // Set the form '#node' to the delta value we want so the Content
 
659
    // module will feed the right $items to the field module in
 
660
    // content_field_form().
 
661
 
 
662
    // There may be missing delta values for fields that were
 
663
    // never created, so check first.
 
664
    if (!empty($node->$field_name) && count($node->$field_name) >= $delta + 1) {
 
665
      $node_copy->$field_name = array($delta => $node->{$field_name}[$delta]);
 
666
    }
 
667
    else {
 
668
      $node_copy->$field_name = array($delta => NULL);
 
669
    }
 
670
    $form['#node'] = $node_copy;
 
671
    $field_form = content_field_form($form, $form_state, $field, $delta);
 
672
 
 
673
    // Place the new $field_form into the $delta position in the group form.
 
674
    if (content_handle('widget', 'multiple values', $field) == CONTENT_HANDLE_CORE) {
 
675
      $value = array_key_exists($delta, $field_form[$field_name]) ? $delta : 0;
 
676
      $form[$group_name][$delta][$field_name] = $field_form[$field_name][$value];
 
677
    }
 
678
    else {
 
679
      $form[$group_name][$delta][$field_name] = $field_form[$field_name];
 
680
    }
 
681
    $form[$group_name][$delta][$field_name]['#weight'] = $field['widget']['weight'];
 
682
 
 
683
    // Add in our validation step, and make sure it preceeds other
 
684
    // processing so we can massage the element back to the normal position.
 
685
    if (empty($form[$group_name][$delta][$field_name]['#element_validate'])) {
 
686
      $form[$group_name][$delta][$field_name]['#element_validate'] = array();
 
687
    }
 
688
    array_unshift($form[$group_name][$delta][$field_name]['#element_validate'], 'content_multigroup_node_item_validate');
 
689
  }
 
690
 
 
691
  // Reset the form '#node' back to its original value.
 
692
  $form['#node'] = $node;
 
693
 
 
694
  return $form;
 
695
}
 
696
 
 
697
/**
 
698
 * Swap transposed field/delta values back
 
699
 * to their normal positions in the node.
 
700
 */
 
701
function content_multigroup_node_item_validate($element, &$form_state) {
 
702
  static $weights = array();
 
703
 
 
704
  //dsm($form_state['values']);
 
705
  $form_values = $form_state['values'];
 
706
  $field_name = array_pop($element['#parents']);
 
707
  $delta = array_pop($element['#parents']);
 
708
  $group_name = array_pop($element['#parents']);
 
709
 
 
710
  // Identify the new delta value for each field.
 
711
 
 
712
  // Find the original delta values for this group, save as static value
 
713
  // because the group will acquire and lose values while we process it.
 
714
  if (!array_key_exists($group_name, $weights)) {
 
715
    $items = $form_state['values'][$group_name];
 
716
    $weights[$group_name] = array();
 
717
    foreach ($items as $count => $value) {
 
718
      // Allow for the possibility of matching _weights and missing deltas.
 
719
      $weight = floatval($value['_weight']);
 
720
      $old_delta = intval($value['_delta']);
 
721
      if (empty($weights[$group_name][$weight]) || !in_array($old_delta, $weights[$group_name][$weight])) {
 
722
        $weights[$group_name][$weight][] = $old_delta;
 
723
      }
 
724
    }
 
725
    ksort($weights[$group_name]);
 
726
  }
 
727
  $count = 0;
 
728
  foreach ($weights[$group_name] as $weight => $values) {
 
729
    foreach ($values as $old_delta) {
 
730
      if ($old_delta === $delta) {
 
731
        $delta = $count;
 
732
        //dsm('moving delta values: '.$group_name.'>'.$field_name.'>'.'from '. $old_delta .' to '. $delta);
 
733
        break 2;
 
734
      }
 
735
      $count++;
 
736
    }
 
737
  }
 
738
  // We figured out what the new order for the fields is,
 
739
  // so set the value for the new delta.
 
740
 
 
741
  // We move these new values back up to the top level of the
 
742
  // node and out of the group so the Content module will find and
 
743
  // save the new values and so they don't get mixed into the
 
744
  // remaining, unaltered, values in the group.
 
745
  array_push($element['#parents'], $field_name);
 
746
  array_push($element['#parents'], $delta);
 
747
 
 
748
  // It's very important to use $form_values instead of $element['#value']
 
749
  // here, because $element['#value'] is sometimes missing changes
 
750
  // made in #element_validate processing done by other modules.
 
751
  $value = isset($form_values[$group_name][$delta][$field_name]) ? $form_values[$group_name][$delta][$field_name] : NULL;
 
752
 
 
753
  // Fields that use optionwidgets have an extra array level in the value
 
754
  // because of the optionwidgets transposition that forces a delta value
 
755
  // into the result array. This works fine when a delta value is between
 
756
  // the field name and the field value, as in normal nodes, but not when
 
757
  // we reverse the field and the delta, so in this case we need to
 
758
  // promote the nested delta value back up to the field level.
 
759
  if (is_array($value) && content_multigroup_uses_optionwidgets($field_name, $element['#type_name'])) {
 
760
    $value = array_shift($value);
 
761
  }
 
762
 
 
763
  //dsm('setting value of '. $field_name.'>'.$delta);
 
764
  //dsm($value);
 
765
  form_set_value($element, $value, $form_state);
 
766
}
 
767
 
 
768
/**
 
769
 * Helper function for identifying fields that use
 
770
 * optionwidgets transpositions.
 
771
 */
 
772
function content_multigroup_uses_optionwidgets($field_name, $type_name) {
 
773
  static $optionwidgets;
 
774
  if (empty($optionwidgets)) {
 
775
    $optionwidgets = array(
 
776
      'optionwidgets_select',
 
777
      'optionwidgets_buttons',
 
778
      'optionwidgets_onoff',
 
779
      'nodereference_buttons',
 
780
      'nodereference_select',
 
781
      'userreference_buttons',
 
782
      'userreference_select',
 
783
      );
 
784
    // Add hook where other widgets that use optionwidgets can announce it.
 
785
    $optionwidgets = array_merge($optionwidgets, module_invoke_all('content_multigroup_uses_optionwidgets'));
 
786
  }
 
787
 
 
788
  $types = content_types($type_name);
 
789
  $fields = $types['fields'];
 
790
  $field = $fields[$field_name];
 
791
  if (in_array($field['widget']['type'], $optionwidgets)) {
 
792
    return TRUE;
 
793
  }
 
794
  return FALSE;
 
795
}
 
796
 
 
797
/**
 
798
 * Validation for the whole node group.
 
799
 */
 
800
function content_multigroup_node_form_validate($element, $form_state) {
 
801
  // We moved all the new field values out of the field group
 
802
  // and up to the top level of the node, now get rid of the
 
803
  // original group values.
 
804
  form_set_value($element, NULL, $form_state);
 
805
  return;
 
806
}
 
807
 
 
808
/**
 
809
 * Implementation of hook_fieldgroup_view().
 
810
 */
 
811
function content_multigroup_fieldgroup_view(&$node, &$element, $group, $context) {
 
812
  if ($group['group_type'] != 'multigroup') {
 
813
    return;
 
814
  }
 
815
 
 
816
  $group_name = $group['group_name'];
 
817
  $node_copy = drupal_clone($node);
 
818
  $max = $group['settings']['multigroup']['multiple'];
 
819
 
 
820
  $count = 0;
 
821
  foreach ($group['fields'] as $field_name => $field) {
 
822
    $count = max($count, count($node->$field_name));
 
823
  }
 
824
 
 
825
  $group['multiple'] = isset($group['settings']['multigroup']['multiple']) ? $group['settings']['multigroup']['multiple'] : 1;
 
826
  $labels = isset($group['settings']['multigroup']['labels']) ? $group['settings']['multigroup']['labels'] : array();
 
827
  $format = isset($group['settings']['multigroup']['display_settings'][$context]['format']) ? $group['settings']['multigroup']['display_settings'][$context]['format'] : 'fieldset';
 
828
  $show_label = isset($group['settings']['multigroup']['display_settings']['label']) ? $group['settings']['multigroup']['display_settings']['label'] : 'above';
 
829
 
 
830
  switch ($group['multiple']) {
 
831
    case 0:
 
832
      $max = 0;
 
833
      break;
 
834
    case 1:
 
835
      $max = $count;
 
836
      break;
 
837
    default:
 
838
      $max = $group['multiple'];
 
839
      break;
 
840
  }
 
841
 
 
842
  for ($delta = 0; $delta < $max; $delta++) {
 
843
    $element[$delta] = array('#weight' => $delta);
 
844
 
 
845
    $label = !empty($labels[$delta]) && $show_label == 'above' ? $labels[$delta] : '';
 
846
 
 
847
    foreach ($group['fields'] as $field_name => $field) {
 
848
 
 
849
      // Create a pseudo node that only has the value we want
 
850
      // in this group and pass it to the formatter.
 
851
      if (isset($node->content[$field_name])) {
 
852
        $node_copy->content[$field_name]['field']['items'] = array(
 
853
          $delta => isset($node->content[$field_name]['field']['items'][$delta]) ? $node->content[$field_name]['field']['items'][$delta] : NULL,
 
854
          );
 
855
        $element[$delta][$field_name] = $node_copy->content[$field_name];
 
856
        $element[$delta][$field_name]['#delta'] = $delta;
 
857
      }
 
858
    }
 
859
    switch ($format) {
 
860
      case 'table':
 
861
        $element[$delta]['#theme'] = 'content_multigroup_display_table';
 
862
        $element[$delta]['#title'] = $label;
 
863
        break;
 
864
      case 'fieldset':
 
865
        $element[$delta]['#type'] = 'fieldset';
 
866
        $element[$delta]['#title'] = $label;
 
867
        break;
 
868
      case 'hr':
 
869
        $element[$delta]['#theme'] = 'content_multigroup_display_hr';
 
870
        $element[$delta]['#title'] = $label;
 
871
        break;
 
872
      default:
 
873
        $element[$delta]['#theme'] = 'content_multigroup_display_simple';
 
874
        $element[$delta]['#title'] = $label;
 
875
        break;
 
876
    }
 
877
 
 
878
  }
 
879
 
 
880
  foreach ($group['fields'] as $field_name => $field) {
 
881
    if (isset($element[$field_name])) {
 
882
      unset($element[$field_name]);
 
883
    }
 
884
  }
 
885
}
 
886
 
 
887
/**
 
888
 * Theme an individual form element.
 
889
 *
 
890
 * Combine multiple values into a table with drag-n-drop reordering.
 
891
 */
 
892
function theme_content_multigroup_node_form($element) {
 
893
  $output = '';
 
894
  if ($element['#multiple'] >= 1) {
 
895
    $table_id = $element['#group_name'] .'_values';
 
896
    $order_class = $element['#group_name'] .'-delta-order';
 
897
 
 
898
    $header = array(
 
899
      array(
 
900
        'data' => '',
 
901
        'colspan' => 2
 
902
      ),
 
903
      t('Order'),
 
904
    );
 
905
    $rows = array();
 
906
    $groups = fieldgroup_groups($element['#type_name']);
 
907
    $group = $groups[$element['#group_name']];
 
908
    $labels = isset($group['settings']['multigroup']['labels']) ? $group['settings']['multigroup']['labels'] : array();
 
909
    $multiple = isset($group['settings']['multigroup']['multiple']) ? $group['settings']['multigroup']['multiple'] : 1;
 
910
 
 
911
    $i = 0;
 
912
    foreach (element_children($element) as $delta => $key) {
 
913
      if ($key !== $element['#group_name'] .'_add_more') {
 
914
        $label = !empty($labels[$i]) ? theme('content_multigroup_node_label', $labels[$i]) : '';
 
915
        $element[$key]['_weight']['#attributes']['class'] = $order_class;
 
916
        $delta_element = drupal_render($element[$key]['_weight']);
 
917
        $cells = array(
 
918
          array('data' => '', 'class' => 'content-multiple-drag'),
 
919
          $label . drupal_render($element[$key]),
 
920
          array('data' => $delta_element, 'class' => 'delta-order'),
 
921
        );
 
922
        $rows[] = array(
 
923
          'data' => $cells,
 
924
          // TODO Tablesort drag n drop is not working with complex
 
925
          // field validation. The fields appear to work correctly,
 
926
          // but element validation seems to get missed or confused
 
927
          // causing validation errors. Need to investigate why.
 
928
          'class' => 'draggable',
 
929
        );
 
930
      }
 
931
      $i++;
 
932
    }
 
933
 
 
934
    $output .= theme('table', $header, $rows, array('id' => $table_id, 'class' => 'content-multiple-table'));
 
935
    $output .= $element['#description'] ? '<div class="description">'. $element['#description'] .'</div>' : '';
 
936
    $output .= drupal_render($element[$element['#group_name'] .'_add_more']);
 
937
 
 
938
    drupal_add_tabledrag($table_id, 'order', 'sibling', $order_class);
 
939
  }
 
940
  else {
 
941
    foreach (element_children($element) as $key) {
 
942
      $output .= drupal_render($element[$key]);
 
943
    }
 
944
  }
 
945
 
 
946
  return $output;
 
947
}
 
948
 
 
949
function content_multigroup_add_more(&$form, &$form_state, $group) {
 
950
  // Add AHAH add more button, if not working with a programmed form.
 
951
  $multiple = $group['settings']['multigroup']['multiple'];
 
952
  $form_element = array();
 
953
  if ($multiple != 1 || !empty($form['#programmed'])) {
 
954
    return $form_element;
 
955
  }
 
956
  else {
 
957
    // Make sure the form is cached so ahah can work.
 
958
    $form['#cache'] = TRUE;
 
959
    $content_type = content_types($group['type_name']);
 
960
    $group_name = $group['group_name'];
 
961
    $group_name_css = str_replace('_', '-', $group_name);
 
962
 
 
963
    $form_element[$group_name .'_add_more'] = array(
 
964
      '#type' => 'submit',
 
965
      '#name' => $group_name .'_add_more',
 
966
      '#value' => t('Add more values'),
 
967
      '#weight' => $multiple + 1,
 
968
      // Submit callback for disabled JavaScript. drupal_get_form() might get
 
969
      // the form from the cache, so we can't rely on content_form_alter()
 
970
      // including this file. Therefore, call a proxy function to do this.
 
971
      '#submit' => array('content_multigroup_add_more_submit_proxy'),
 
972
      '#ahah' => array(
 
973
        'path' => 'content_multigroup/js_add_more/'. $content_type['url_str'] .'/'. $group_name,
 
974
        'wrapper' => $group_name_css .'-items',
 
975
        'method' => 'replace',
 
976
        'effect' => 'fade',
 
977
      ),
 
978
      // When JS is disabled, the content_add_more_submit handler will find
 
979
      // the relevant field using these entries.
 
980
      '#group_name' => $group_name,
 
981
      '#type_name' => $group['type_name'],
 
982
    );
 
983
 
 
984
    // Add wrappers for the group and 'more' button.
 
985
    // TODO: could be simplified ?
 
986
    $form_element['#prefix'] = '<div class="clear-block" id="'. $group_name_css .'-add-more-wrapper"><div id="'. $group_name_css .'-items">';
 
987
    $form_element[$group_name .'_add_more']['#prefix'] = '<div class="content-add-more">';
 
988
    $form_element[$group_name .'_add_more']['#suffix'] =  '</div></div></div>';
 
989
  }
 
990
  return $form_element;
 
991
}
 
992
 
 
993
/**
 
994
 * Submit handler to add more choices to a content form. This handler is used when
 
995
 * JavaScript is not available. It makes changes to the form state and the
 
996
 * entire form is rebuilt during the page reload.
 
997
 */
 
998
function content_multigroup_add_more_submit($form, &$form_state) {
 
999
  // Set the form to rebuild and run submit handlers.
 
1000
  node_form_submit_build_node($form, $form_state);
 
1001
  $group_name = $form_state['clicked_button']['#group_name'];
 
1002
  $type_name = $form_state['clicked_button']['#type_name'];
 
1003
 
 
1004
  // Make the changes we want to the form state.
 
1005
  if ($form_state['values'][$group_name][$group_name .'_add_more']) {
 
1006
    $form_state['item_count'][$group_name] = count($form_state['values'][$group_name]);
 
1007
  }
 
1008
}
 
1009
 
 
1010
/**
 
1011
 * Menu callback for AHAH addition of new empty widgets.
 
1012
 *
 
1013
 * Adapted from content_add_more_js to work with groups instead of fields.
 
1014
 */
 
1015
function content_multigroup_add_more_js($type_name_url, $group_name) {
 
1016
  $type = content_types($type_name_url);
 
1017
  $groups = fieldgroup_groups($type['type']);
 
1018
  $group = $groups[$group_name];
 
1019
  $group['multiple'] = $group['settings']['multigroup']['multiple'];
 
1020
 
 
1021
  if (($group['multiple'] != 1) || empty($_POST['form_build_id'])) {
 
1022
    // Invalid request.
 
1023
    drupal_json(array('data' => ''));
 
1024
    exit;
 
1025
  }
 
1026
 
 
1027
  // Retrieve the cached form.
 
1028
  $form_state = array('submitted' => FALSE);
 
1029
  $form_build_id = $_POST['form_build_id'];
 
1030
  $form = form_get_cache($form_build_id, $form_state);
 
1031
  if (!$form) {
 
1032
    // Invalid form_build_id.
 
1033
    drupal_json(array('data' => ''));
 
1034
    exit;
 
1035
  }
 
1036
 
 
1037
  // We don't simply return a new empty widget to append to existing ones, because
 
1038
  // - ahah.js won't simply let us add a new row to a table
 
1039
  // - attaching the 'draggable' behavior won't be easy
 
1040
  // So we resort to rebuilding the whole table of widgets including the existing ones,
 
1041
  // which makes us jump through a few hoops.
 
1042
 
 
1043
  // The form that we get from the cache is unbuilt. We need to build it so that
 
1044
  // _value callbacks can be executed and $form_state['values'] populated.
 
1045
  // We only want to affect $form_state['values'], not the $form itself
 
1046
  // (built forms aren't supposed to enter the cache) nor the rest of $form_data,
 
1047
  // so we use copies of $form and $form_data.
 
1048
  $form_copy = $form;
 
1049
  $form_state_copy = $form_state;
 
1050
  $form_copy['#post'] = array();
 
1051
  form_builder($_POST['form_id'], $form_copy, $form_state_copy);
 
1052
  // Just grab the data we need.
 
1053
  $form_state['values'] = $form_state_copy['values'];
 
1054
  // Reset cached ids, so that they don't affect the actual form we output.
 
1055
  form_clean_id(NULL, TRUE);
 
1056
 
 
1057
  // Sort the $form_state['values'] we just built *and* the incoming $_POST data
 
1058
  // according to d-n-d reordering.
 
1059
  unset($form_state['values'][$group_name][$group['group_name'] .'_add_more']);
 
1060
  foreach ($_POST[$group_name] as $delta => $item) {
 
1061
    $form_state['values'][$group_name][$delta]['_weight'] = $item['_weight'];
 
1062
    $form_state['values'][$group_name][$delta]['_delta'] = $item['_delta'];
 
1063
  }
 
1064
  $form_state['values'][$group_name] = _content_sort_items($group, $form_state['values'][$group_name]);
 
1065
  $_POST[$group_name] = _content_sort_items($group, $_POST[$group_name]);
 
1066
 
 
1067
  // Build our new form element for the whole group, asking for one more element.
 
1068
 
 
1069
  $form_state['item_count'] = array($group_name => count($_POST[$group_name]) + 1);
 
1070
  $delta = max(array_keys($_POST[$group_name])) + 1;
 
1071
  content_multigroup_group_form($form, $form_state, $group, $delta);
 
1072
 
 
1073
  // Save the new definition of the form.
 
1074
  $form_state['values'] = array();
 
1075
  form_set_cache($form_build_id, $form, $form_state);
 
1076
 
 
1077
  // Build the new form against the incoming $_POST values so that we can
 
1078
  // render the new element.
 
1079
  $_POST[$group_name][$delta]['_weight'] = $delta;
 
1080
  $form_state = array('submitted' => FALSE);
 
1081
  $form += array(
 
1082
    '#post' => $_POST,
 
1083
    '#programmed' => FALSE,
 
1084
  );
 
1085
  $form = form_builder($_POST['form_id'], $form, $form_state);
 
1086
 
 
1087
  // Render the new output.
 
1088
  $group_form = $form[$group_name];
 
1089
 
 
1090
  // We add a div around the new content to receive the ahah effect.
 
1091
  $group_form[$delta]['#prefix'] = '<div class="ahah-new-content">'. (isset($group_form[$delta]['#prefix']) ? $group_form[$delta]['#prefix'] : '');
 
1092
  $group_form[$delta]['#suffix'] = (isset($group_form[$delta]['#suffix']) ? $group_form[$delta]['#suffix'] : '') .'</div>';
 
1093
 
 
1094
  // If a newly inserted widget contains AHAH behaviors, they normally won't
 
1095
  // work because AHAH doesn't know about those - it just attaches to the exact
 
1096
  // form elements that were initially specified in the Drupal.settings object.
 
1097
  // The new ones didn't exist then, so we need to update Drupal.settings
 
1098
  // by ourselves in order to let AHAH know about those new form elements.
 
1099
  $javascript = drupal_add_js(NULL, NULL);
 
1100
  $output_js = isset($javascript['setting']) ? '<script type="text/javascript">jQuery.extend(Drupal.settings, '. drupal_to_js(call_user_func_array('array_merge_recursive', $javascript['setting'])) .');</script>' : '';
 
1101
 
 
1102
  $output = theme('status_messages') . drupal_render($group_form) . $output_js;
 
1103
  drupal_json(array('status' => TRUE, 'data' => $output));
 
1104
  exit;
 
1105
}
 
1106
 
 
1107
/**
 
1108
 * Theme the sub group label in the node form.
 
1109
 */
 
1110
function theme_content_multigroup_node_label($text) {
 
1111
  if (!empty($text)) {
 
1112
    return '<h3>'. check_plain($text) .'</h3>';
 
1113
  }
 
1114
}
 
1115
 
 
1116
function theme_content_multigroup_display_simple($element) {
 
1117
  $label = '';
 
1118
  if (!empty($element['#title'])) {
 
1119
    $label .= '<label class="content-multigroup">'. $element['#title'] .':</label>';
 
1120
  }
 
1121
  $output = $label;
 
1122
  foreach (element_children($element) as $key) {
 
1123
    $output .= drupal_render($element[$key]);
 
1124
  }
 
1125
  return $output;
 
1126
}
 
1127
 
 
1128
function theme_content_multigroup_display_hr($element) {
 
1129
  $label = '';
 
1130
  if (!empty($element['#title'])) {
 
1131
    $label .= '<label class="content-multigroup">'. $element['#title'] .':</label>';
 
1132
  }
 
1133
  $output = '<hr class="content-multigroup" />'. $label;
 
1134
  foreach (element_children($element) as $key) {
 
1135
    $output .= drupal_render($element[$key]);
 
1136
  }
 
1137
  return $output;
 
1138
}
 
1139
 
 
1140
function theme_content_multigroup_display_table($element) {
 
1141
  $label = '';
 
1142
  if (!empty($element['#title'])) {
 
1143
    $label .= '<label class="content-multigroup">'. $element['#title'] .':</label>';
 
1144
  }
 
1145
  $output = $label;
 
1146
  foreach (element_children($element) as $key) {
 
1147
    $output .= drupal_render($element[$key]);
 
1148
  }
 
1149
  return $output;
 
1150
}
 
 
b'\\ No newline at end of file'