content_multigroup.admin.inc in Content Construction Kit (CCK) 6.3
Implementation of node type administration functions for content multigroup.
File
modules/content_multigroup/content_multigroup.admin.incView source
<?php
/**
* @file
* Implementation of node type administration functions for content multigroup.
*/
/**
* Helper function to build the multiple values options for multigroups.
*/
function content_multigroup_multiple_values() {
return array(
//'' => t('N/A'),
1 => t('Unlimited'),
0 => 1,
) + drupal_map_assoc(range(2, 10));
}
/**
* Validation for creating/moving fields and groups on the
* Manage Fields screen.
*/
function content_multigroup_field_overview_form_validate($form, &$form_state) {
$form_values = $form_state['values'];
$type_name = $form['#type_name'];
$fields = array();
$groups = array();
$group = $form_values['_add_new_group'];
if (array_filter(array(
$group['label'],
$group['group_name'],
))) {
$group['settings'] = field_group_default_settings($group['group_type']);
$validation = fieldgroup_validate_name($group, $form['#type_name']);
// If there's something wrong with the new group,
// don't bother doing any more validation, further
// processing will be stopped by the fieldgroup module.
if (!empty($validation['errors'])) {
return;
}
$group['group_name'] = $validation['group_name'];
$new_group_name = $group['group_name'];
$groups['_add_new_group'] = $group;
}
// See if we have fields moving into or out of a Multigroup.
// Set any fields to use the new name here so they will get processed
// correctly by the fieldgroup module when saved.
$group_rows = array();
foreach ($form_values as $key => $values) {
if ($values['parent'] == '_add_new_group') {
$values['parent'] = $new_group_name;
$form_values[$key] = $values;
}
if (!empty($form[$key]['#row_type']) && $form[$key]['#row_type'] == 'group') {
// Gather up info about all groups.
$group_name = $form_values[$key]['group']['group_name'];
$groups[$group_name] = $form_values[$key]['group'];
$group_rows[$group_name] = $group_name;
}
if (!empty($form[$key]['#row_type']) && $form[$key]['#row_type'] == 'field') {
if ($values['prev_parent'] != $values['parent']) {
// Gather up fields that have moved in or out of a group.
$fields[$key] = $form_values[$key]['field'];
}
}
}
$rebuild = FALSE;
// Test that a group was not moved into a multigroup, an invalid combination.
foreach ($groups as $key => $values) {
if (in_array($key, $group_rows)) {
$parent = $form_values[$key]['parent'];
$parent_info = !empty($parent) ? $form_values[$parent] : array();
if (!empty($parent) && $parent_info['group']['group_type'] == 'multigroup') {
$error_message = t('You cannot place any kind of group inside a multigroup. The group @name was moved back to where it started.', array(
'@name' => $key,
));
form_set_value($form[$key]['weight'], $form[$key]['weight']['#default_value'], $form_state);
form_set_value($form[$key]['parent'], $form[$key]['parent']['#default_value'], $form_state);
drupal_set_message($error_message, 'error');
}
}
}
// Synchronize the multiple value values for all fields in a group, they must be the same.
// Also ensure that fields moved into multigroups are fields that are allowed.
// In some cases, it may not be safe to move a field back out of a multigroup because
// it will behave differently elsewhere, so check that too.
foreach ($fields as $field_name => $field) {
$new_group = $form_values[$field_name]['parent'];
$old_group = $form_values[$field_name]['prev_parent'];
if (!empty($new_group) && isset($groups[$new_group]) && $groups[$new_group]['group_type'] == 'multigroup') {
$allowed_in = content_multigroup_allowed_in($field, $groups[$new_group]);
if (!$allowed_in['allowed']) {
form_set_error($field_name, $allowed_in['message']);
}
else {
if (!empty($allowed_in['message'])) {
drupal_set_message($allowed_in['message']);
}
module_load_include('inc', 'content', 'includes/content.crud');
$content_type = content_types($type_name);
$group_multiple = $groups[$new_group]['settings']['multigroup']['multiple'];
$multiple_values = content_multigroup_multiple_values();
$field = $content_type['fields'][$field_name];
$field['multiple'] = $group_multiple;
$field = content_field_instance_collapse($field);
content_field_instance_update($field, FALSE);
$rebuild = TRUE;
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(
'%field' => $field['label'],
'%multiple' => $multiple_values[$group_multiple],
'%group' => $groups[$new_group]['label'],
)));
}
}
elseif (!empty($old_group) && isset($groups[$old_group]) && $groups[$old_group]['group_type'] == 'multigroup') {
$allowed_out = content_multigroup_allowed_out($field, $groups[$old_group]);
if (!$allowed_out['allowed']) {
form_set_error($field_name, $allowed_out['message']);
}
elseif (!empty($allowed_out['message'])) {
drupal_set_message($allowed_out['message']);
}
}
}
// Clear caches and rebuild menu only if any field has been updated.
if ($rebuild) {
content_clear_type_cache(TRUE);
menu_rebuild();
}
}
/**
* Helper function for deciding if a field is
* allowed into a Multigroup.
*/
function content_multigroup_allowed_in($field, $group) {
if ($group['group_type'] != 'multigroup') {
return array(
'allowed' => TRUE,
'message' => '',
);
}
// We can't allow fields with more multiple values than the group has
// to be moved into it.
$max_existing = content_max_delta($field['field_name']);
$group_multiple = $group['settings']['multigroup']['multiple'];
$multiple_values = content_multigroup_multiple_values();
if ($group_multiple != 1 && $max_existing > $group_multiple) {
return array(
'allowed' => FALSE,
'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_multiple],
)),
);
}
// Fields that handle their own multiple values may not have the same values
// in Multigroup fields and normal fields. We don't know if they will work or not.
// Adding a hook here where widgets that handle their own multiple values
// that will work correctly in Multigroups can allow their fields in.
if (content_handle('widget', 'multiple values', $field) != CONTENT_HANDLE_CORE) {
$allowed_widgets = array(
'optionwidgets_select',
'optionwidgets_buttons',
'optionwidgets_onoff',
'nodereference_buttons',
'nodereference_select',
'userreference_buttons',
'userreference_select',
);
$allowed_widgets = array_merge($allowed_widgets, module_invoke_all('content_multigroup_allowed_widgets'));
if (!in_array($field['widget']['type'], $allowed_widgets)) {
return array(
'allowed' => FALSE,
'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'],
)),
);
}
}
// Allow other modules to intervene.
// Any failure will prevent this action.
foreach (module_implements('content_multigroup_allowed_in') as $module) {
$function = $module . '_content_multigroup_allowed_in';
$result = $function($field, $group);
if ($result['allowed'] === FALSE) {
return array(
'allowed' => FALSE,
'message' => $result['message'],
);
}
}
$message = t('You are moving the field %field into a Multigroup.', array(
'%field' => $field['widget']['label'],
));
return array(
'allowed' => TRUE,
'message' => $message,
);
}
/**
* Helper function for deciding if a field is
* allowed out of a Multigroup.
*/
function content_multigroup_allowed_out($field, $group) {
if ($group['group_type'] != 'multigroup') {
return array(
'allowed' => TRUE,
'message' => '',
);
}
// Optionwidgets do not behave the same in a Multigroup field as out of it.
// In a Multigroup the same option can be selected multiple times,
// but that is not possible in a normal group.
// Adding a hook here where widgets that handle their own multiple values
// can indicate their fields should not be removed from Multigroups.
$max_existing = content_max_delta($field['field_name']);
$no_remove_widgets = array(
'optionwidgets_select',
'optionwidgets_buttons',
'optionwidgets_onoff',
'nodereference_buttons',
'nodereference_select',
'userreference_buttons',
'userreference_select',
);
$no_remove_widgets = array_merge($no_remove_widgets, module_invoke_all('content_multigroup_no_remove_widgets'));
if (in_array($field['widget']['type'], $no_remove_widgets) && $max_existing > 0) {
return array(
'allowed' => FALSE,
'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'],
)),
);
}
// Allow other modules to intervene.
// Any failure will prevent this action.
foreach (module_implements('content_multigroup_allowed_out') as $module) {
$function = $module . '_content_multigroup_allowed_out';
$result = $function($field, $group);
if ($result['allowed'] === FALSE) {
return array(
'allowed' => FALSE,
'message' => $result['message'],
);
}
}
$message = t('You are moving the field %field out of a Multigroup.', array(
'%field' => $field['widget']['label'],
));
return array(
'allowed' => TRUE,
'message' => $message,
);
}
/**
* Alter the basic field settings form.
*
* It should not be possible to choose a widget type that is not compatible
* with multigroups.
*/
function content_multigroup_field_basic_form(&$form, &$form_state) {
$field_name = $form['basic']['field_name']['#value'];
$type_name = $form['type_name']['#value'];
// Ignore this field if it is not part of a field group.
if (!($group_name = fieldgroup_get_group($type_name, $field_name))) {
return;
}
// Retrieve information about the group the field is in.
$groups = fieldgroup_groups($type_name);
$group = $groups[$group_name];
// Ignore this field if it is not part of a multigroup.
if ($group['group_type'] != 'multigroup') {
return;
}
// Retrieve information about the field itself.
$field = content_fields($field_name, $type_name);
// Check if the widget can be moved out of the multigroup.
$allowed_out = content_multigroup_allowed_out($field, $group);
if (!$allowed_out['allowed']) {
$form['basic']['widget_type']['#disabled'] = TRUE;
$form['basic']['widget_type']['#suffix'] = '<div class="warning">' . t('The widget type cannot be changed because the field %field already has data created and this widget stores data differently in a Standard group than in a Multigroup. Allowing this change could result in the loss of data.', array(
'%field' => $field['widget']['label'],
)) . '</div>';
return;
}
// Remove from the list of available widgets those that are not
// compatible with multigroups.
$widget_types = _content_widget_types();
foreach (array_keys($form['basic']['widget_type']['#options']) as $widget_type) {
if ($field['widget']['type'] != $widget_type) {
$field_copy = $field;
$field_copy['widget']['type'] = $widget_type;
$field_copy['widget']['module'] = $widget_types[$widget_type]['module'];
$allowed_in = content_multigroup_allowed_in($field_copy, $group);
if (!$allowed_in['allowed']) {
unset($form['basic']['widget_type']['#options'][$widget_type]);
}
}
}
}
/**
* Alter the "Display fields" form.
*
* Add an additional selector for setting multigroup field display format.
*/
function content_multigroup_display_overview_form(&$form, &$form_state) {
$type_name = $form['#type_name'];
$contexts_selector = $form['#contexts'];
// Gather type information.
$content_type = content_types($type_name);
// The content module stops building the form if the type has no fields.
if (empty($content_type['fields'])) {
return;
}
$groups = array();
$groups = fieldgroup_groups($type_name);
$contexts = content_build_modes($contexts_selector);
$all_contexts = content_build_modes();
// Multigroups, extra values.
$label_options = array(
'above' => t('Above'),
'hidden' => t('<Hidden>'),
);
$options = array(
'simple' => t('Simple'),
'fieldset' => t('Fieldset'),
'fieldset_collapsible' => t('Fieldset - collapsible'),
'fieldset_collapsed' => t('Fieldset - collapsed'),
'hr' => t('Horizontal line'),
'table-single' => t('Table - Single column'),
'table-multiple' => t('Table - Multiple columns'),
'ul' => t('Unordered List'),
);
foreach ($groups as $group_name => $group) {
if ($group['group_type'] != 'multigroup') {
continue;
}
$subgroup_settings = isset($group['settings']['multigroup']['subgroup']) ? $group['settings']['multigroup']['subgroup'] : array();
$subgroup_name = $group_name . '_subgroup';
$form['#fields'] = array_merge(array(
$subgroup_name,
), $form['#fields']);
$form[$subgroup_name] = array(
'human_name' => array(
'#value' => t('[Subgroup format]'),
),
'weight' => array(
'#type' => 'value',
'#value' => -20,
),
'parent' => array(
'#type' => 'value',
'#value' => $group_name,
),
'subgroup' => array(
'#type' => 'value',
'#value' => 1,
),
);
if ($contexts_selector == 'basic') {
$form[$subgroup_name]['label'] = array(
'#type' => 'select',
'#options' => $label_options,
'#default_value' => isset($subgroup_settings['label']) ? $subgroup_settings['label'] : 'above',
);
}
// Allow a format selection for contexts on the current tab.
// Store other contexts as hidden values so they don't get lost.
foreach ($all_contexts as $key => $title) {
if (array_key_exists($key, $contexts)) {
$form[$subgroup_name][$key]['format'] = array(
'#type' => 'select',
'#options' => $options,
'#default_value' => isset($subgroup_settings[$key]['format']) ? $subgroup_settings[$key]['format'] : 'fieldset',
);
$form[$subgroup_name][$key]['exclude'] = array(
'#type' => 'value',
'#value' => 0,
);
}
else {
$form[$subgroup_name][$key]['format'] = array(
'#type' => 'hidden',
'#value' => isset($subgroup_settings[$key]['format']) ? $subgroup_settings[$key]['format'] : 'fieldset',
);
$form[$subgroup_name][$key]['exclude'] = array(
'#type' => 'value',
'#value' => 0,
);
}
}
}
$form['#submit'] = array_merge(array(
'content_multigroup_display_overview_form_submit',
), $form['#submit']);
}
/**
* Submit handler for the display overview form.
*
* Do this in pre_save so we catch it before the content module
* tries to use our 'field'.
*/
function content_multigroup_display_overview_form_submit($form, &$form_state) {
$groups = fieldgroup_groups($form['#type_name']);
//$reset_cache = FALSE;
// Find any subgroups we inserted into the display fields form,
// save our settings, and remove them from $form_state.
foreach ($form_state['values'] as $key => $values) {
if (in_array($key, $form['#fields']) && !empty($values['parent']) && !empty($values['subgroup'])) {
$group_name = $values['parent'];
$group = $groups[$group_name];
unset($values['subgroup'], $values['parent']);
// We have some numeric keys here, so we can't use array_merge.
foreach ($values as $k => $v) {
$form_state['values'][$group_name]['settings']['multigroup']['subgroup'][$k] = $v;
}
// Remove the subgroup from $form_state.
unset($form_state['values'][$key]);
}
}
}
/**
* Alter the Fieldgroup edit form to add Multigroup settings.
*/
function content_multigroup_group_edit_form(&$form, &$form_state) {
$type_name = $form['#content_type']['type'];
$group_name = $form['group_name']['#default_value'];
$content_type = content_types($type_name);
$groups = fieldgroup_groups($type_name);
$group = $groups[$group_name];
if ($group['group_type'] != 'multigroup') {
return;
}
module_load_include('inc', 'content', 'includes/content.admin');
module_load_include('inc', 'content', 'includes/content.crud');
$form['group_type'] = array(
'#type' => 'hidden',
'#value' => $group['group_type'],
);
$form['settings']['multigroup'] = array(
'#type' => 'fieldset',
'#title' => t('Multigroup settings'),
'#collapsed' => FALSE,
'#collapsible' => TRUE,
);
if (isset($group['settings']['multigroup']['subgroup'])) {
// Preserve subgroup display settings.
$form['settings']['multigroup']['subgroup'] = array(
'#type' => 'value',
'#value' => $group['settings']['multigroup']['subgroup'],
);
}
$form['settings']['multigroup']['multiple-columns'] = array(
'#type' => 'checkbox',
'#title' => t('Multiple columns'),
'#default_value' => isset($group['settings']['multigroup']['multiple-columns']) ? $group['settings']['multigroup']['multiple-columns'] : 0,
'#description' => t('Enable this option to render each field on a separate column on the node edit form.'),
);
$form['settings']['multigroup']['required'] = array(
'#type' => 'checkbox',
'#title' => t('Required'),
'#default_value' => !empty($group['settings']['multigroup']['required']) ? $group['settings']['multigroup']['required'] : 0,
'#description' => t('Enable this option to require a minimum of one collection of fields in this Multigroup.'),
);
$description = t('Number of times to repeat the collection of Multigroup fields.') . ' ';
$description .= t("'Unlimited' will provide an 'Add more' button so the users can add items as many times as they like.") . ' ';
$description .= t('All fields in this group will automatically be set to allow this number of values.');
$group_multiple = isset($group['settings']['multigroup']['multiple']) ? $group['settings']['multigroup']['multiple'] : 1;
$form['settings']['multigroup']['multiple'] = array(
'#type' => 'select',
'#title' => t('Number of repeats'),
'#options' => content_multigroup_multiple_values(),
'#default_value' => $group_multiple,
'#description' => $description,
);
$form['settings']['multigroup']['labels'] = array(
'#type' => 'fieldset',
'#title' => t('Labels'),
'#description' => t("Labels for each subgroup of fields. Labels can be hidden or shown in various contexts using the 'Display fields' screen."),
);
if ($group_multiple < 2) {
$group_multiple = 0;
}
for ($i = 0; $i < 10; $i++) {
$form['settings']['multigroup']['labels'][$i] = array(
'#type' => 'textfield',
'#title' => t('Subgroup %number label', array(
'%number' => $i + 1,
)),
'#default_value' => isset($group['settings']['multigroup']['labels'][$i]) ? $group['settings']['multigroup']['labels'][$i] : '',
);
}
$form['#validate'][] = 'content_multigroup_group_edit_form_validate';
$form['#submit'][] = 'content_multigroup_group_edit_form_submit';
}
/**
* Validate the Fieldgroup edit form.
*/
function content_multigroup_group_edit_form_validate($form, &$form_state) {
$form_values = $form_state['values'];
$group_type = $form_values['group_type'];
if ($group_type != 'multigroup') {
return;
}
$content_type = $form['#content_type'];
$groups = fieldgroup_groups($content_type['type']);
$group = $groups[$form_values['group_name']];
foreach ($group['fields'] as $field_name => $data) {
// Make sure we don't set the multiple values to a number that
// would result in lost data.
$max_existing = content_max_delta($field_name);
if ($form_values['settings']['multigroup']['multiple'] != 1 && $max_existing > $form_values['settings']['multigroup']['multiple']) {
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,
)));
}
}
}
/**
* Submit the Fieldgroup edit form.
*
* Update multiple values of fields contained in Multigroups.
*/
function content_multigroup_group_edit_form_submit($form, &$form_state) {
$form_values = $form_state['values'];
$group_type = $form_values['group_type'];
if ($group_type != 'multigroup') {
return;
}
module_load_include('inc', 'content', 'includes/content.crud');
$content_type = $form['#content_type'];
$groups = fieldgroup_groups($content_type['type']);
$group = $groups[$form_values['group_name']];
$group_fields = array_intersect_key($content_type['fields'], $group['fields']);
if (!empty($group_fields)) {
foreach ($group_fields as $field_name => $field) {
$field['multiple'] = $form_values['settings']['multigroup']['multiple'];
$field = content_field_instance_collapse($field);
content_field_instance_update($field, FALSE);
}
content_clear_type_cache(TRUE);
menu_rebuild();
}
}
Functions
Name | Description |
---|---|
content_multigroup_allowed_in | Helper function for deciding if a field is allowed into a Multigroup. |
content_multigroup_allowed_out | Helper function for deciding if a field is allowed out of a Multigroup. |
content_multigroup_display_overview_form | Alter the "Display fields" form. |
content_multigroup_display_overview_form_submit | Submit handler for the display overview form. |
content_multigroup_field_basic_form | Alter the basic field settings form. |
content_multigroup_field_overview_form_validate | Validation for creating/moving fields and groups on the Manage Fields screen. |
content_multigroup_group_edit_form | Alter the Fieldgroup edit form to add Multigroup settings. |
content_multigroup_group_edit_form_submit | Submit the Fieldgroup edit form. |
content_multigroup_group_edit_form_validate | Validate the Fieldgroup edit form. |
content_multigroup_multiple_values | Helper function to build the multiple values options for multigroups. |