Index: theme/content.css
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/cck/theme/content.css,v
retrieving revision 1.12.2.3
diff -u -r1.12.2.3 content.css
--- theme/content.css 22 Aug 2008 22:10:57 -0000 1.12.2.3
+++ theme/content.css 1 Sep 2008 18:19:40 -0000
@@ -51,14 +51,13 @@
}
/* 'Manage fields' overview */
-table.content-field-overview, table.content-field-overview fieldset table {
- width:100%;
+tr.content-add-new .tabledrag-changed {
+ display: none;
}
-table.content-field-overview td {
- width:14%;
+tr.content-add-new .description {
+ margin-bottom:0;
}
-.content-field-overview-empty {
- text-align:center;
+.content-default-value, .form-item input.content-default-value.error {
+ color: #999;
}
-
Index: modules/fieldgroup/fieldgroup.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/cck/modules/fieldgroup/fieldgroup.module,v
retrieving revision 1.79.2.15
diff -u -r1.79.2.15 fieldgroup.module
--- modules/fieldgroup/fieldgroup.module 1 Sep 2008 13:05:59 -0000 1.79.2.15
+++ modules/fieldgroup/fieldgroup.module 1 Sep 2008 18:19:40 -0000
@@ -351,8 +351,9 @@
'#value' => _fieldgroup_field_get_group($content_type['type'], $form['field_name']['#value']),
);
}
- elseif ($form_id == 'content_admin_field_overview_form' && !empty($form['#groups'])) {
- $form['#submit'][] = 'fieldgroup_content_overview_form_submit';
+ elseif ($form_id == 'content_admin_field_overview_form') {
+ $form['#validate'][] = 'fieldgroup_field_overview_form_validate';
+ $form['#submit'][] = 'fieldgroup_field_overview_form_submit';
}
elseif ($form_id == 'content_admin_display_overview_form' && !empty($form['#groups'])) {
$form['#submit'][] = 'fieldgroup_display_overview_form_submit';
@@ -365,16 +366,61 @@
}
}
-function fieldgroup_content_overview_form_submit($form, &$form_state) {
+function fieldgroup_field_overview_form_validate($form, &$form_state) {
+ $form_values = $form_state['values'];
+ $group = $form_values['_add_new_group'];
+
+ // Fail validation if attempt to nest fields under a new group without a label.
+ if (!$group['label']) {
+ foreach ($form_values as $key => $values) {
+ if ($values['parent'] == '_add_new_group') {
+ form_set_error('_add_new_group][label', t('Add new group: you need to provide a label.'));
+ break;
+ }
+ }
+ }
+}
+
+function fieldgroup_field_overview_form_submit($form, &$form_state) {
$form_values = $form_state['values'];
$type_name = $form['#type_name'];
+
+ // Create new group if needed.
+ if (!empty($form_values['_add_new_group']['label'])) {
+ $group = $form_values['_add_new_group'];
+ $group['settings'] = _field_group_default_settings();
+ $new_group_name = fieldgroup_save_group($type_name, $group);
+ }
+
+ // Parse incoming rows.
+ $add_field_rows = array('_add_new_field', '_add_existing_field');
+ $field_rows = array_merge($form['#fields'], $add_field_rows);
foreach ($form_values as $key => $values) {
- // Update field parenting.
- if (in_array($key, $form['#fields'])) {
+ // If 'field' row: update field parenting.
+ if (in_array($key, $field_rows)) {
+ // If newly added fields were added to a group:
+ if (in_array($key, $add_field_rows)) {
+ // We replace the '_add_*_field' key with the actual name of
+ // the field that got added.
+ // content_admin_field_overview_form_submit() placed those
+ // in $form_state['fields_added'] for us.
+ if (isset($form_state['fields_added'][$key])) {
+ $key = $form_state['fields_added'][$key];
+ }
+ else {
+ // No field was actually created : skip to next row.
+ continue;
+ }
+ }
+ // If the field was added to the newly created group, replace the
+ // '_add_new_group' value with the actual name of the group.
+ $parent = ($values['parent'] == '_add_new_group' && isset($new_group_name)) ? $new_group_name : $values['parent'];
// TODO: check the parent group does exist ?
- fieldgroup_update_fields(array('field_name' => $key, 'group' => $values['parent'], 'type_name' => $type_name));
+ fieldgroup_update_fields(array('field_name' => $key, 'group' => $parent, 'type_name' => $type_name));
}
- // Update groups weights.
+
+ // If 'group' row: update groups weights
+ // (possible newly created group has already been taken care of).
elseif (in_array($key, $form['#groups'])) {
db_query("UPDATE {". fieldgroup_tablename() ."} SET weight = %d WHERE type_name = '%s' AND group_name = '%s'",
$values['weight'], $type_name, $key);
@@ -384,6 +430,17 @@
cache_clear_all('fieldgroup_data', content_cache_tablename());
}
+function _field_group_default_settings() {
+ $settings = array(
+ 'form' => array('style' => 'fieldset', 'description' => ''),
+ 'display' => array('description' => '', 'label' => 'above'),
+ );
+ foreach (array_keys(_content_admin_display_contexts(CONTENT_CONTEXTS_SIMPLE)) as $key) {
+ $settings['display'][$key] = 'fieldset';
+ }
+ return $settings;
+}
+
function fieldgroup_display_overview_form_submit($form, &$form_state) {
$form_values = $form_state['values'];
$groups = fieldgroup_groups($form['#type_name']);
@@ -526,7 +583,7 @@
function fieldgroup_save_group($type_name, $group) {
$groups = fieldgroup_groups($type_name);
- if (!isset($groups[$group['group_name']])) {
+ if (!isset($group['group_name']) || !isset($groups[$group['group_name']])) {
// Accept group name from programmed submissions if valid.
if (!empty($group['group_name'])) {
$group_name = $group['group_name'];
@@ -550,14 +607,15 @@
db_query("INSERT INTO {". fieldgroup_tablename() ."} (type_name, group_name, label, settings, weight)
VALUES ('%s', '%s', '%s', '%s', %d)", $type_name, $group_name, $group['label'], serialize($group['settings']), $group['weight']);
cache_clear_all('fieldgroup_data', content_cache_tablename());
- return SAVED_NEW;
+ return $group_name;
}
else {
+ $group_name = $group['group_name'];
db_query("UPDATE {". fieldgroup_tablename() ."} SET label = '%s', settings = '%s', weight = %d ".
"WHERE type_name = '%s' AND group_name = '%s'",
- $group['label'], serialize($group['settings']), $group['weight'], $type_name, $group['group_name']);
+ $group['label'], serialize($group['settings']), $group['weight'], $type_name, $group_name);
cache_clear_all('fieldgroup_data', content_cache_tablename());
- return SAVED_UPDATED;
+ return $group_name;
}
}
Index: includes/content.admin.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/cck/includes/content.admin.inc,v
retrieving revision 1.181.2.34
diff -u -r1.181.2.34 content.admin.inc
--- includes/content.admin.inc 1 Sep 2008 14:38:12 -0000 1.181.2.34
+++ includes/content.admin.inc 1 Sep 2008 18:19:40 -0000
@@ -111,22 +111,18 @@
$fields = $type['fields'];
$field_types = _content_field_types();
- if (empty($fields) && empty($form_state['post'])) {
- drupal_set_message(t('There are no fields configured for this content type. You can !link.', array(
- '!link' => l(t('Add a new field'), str_replace('/fields', '/add_field', $_GET['q'])))), 'warning');
- }
-
$extra = $type['extra'];
$groups = $group_options = array();
if (module_exists('fieldgroup')) {
$groups = fieldgroup_groups($type['type']);
$group_options = _fieldgroup_groups_label($type['type']);
+ // Add the ability to group under the newly created row.
+ $group_options['_add_new_group'] = '_add_new_group';
}
- // Rows in this table are essentially nested, but for the simplicity of
- // theme and submit functions, we keep them in a flat array, and use a
- // $dummy render structure to figure the right display order.
- $dummy = array();
+ // Store the default weights as we meet them, to be able to put the
+ //'add new' rows after them.
+ $weights = array();
$form = array(
'#tree' => TRUE,
@@ -142,8 +138,8 @@
foreach ($fields as $name => $field) {
$weight = $field['widget']['weight'];
$form[$name] = array(
- 'human_name' => array('#value' => check_plain($field['widget']['label'])),
- 'name' => array('#value' => $field['field_name']),
+ 'label' => array('#value' => check_plain($field['widget']['label'])),
+ 'field_name' => array('#value' => $field['field_name']),
'type' => array('#value' => t($field_types[$field['type']]['label'])),
'configure' => array('#value' => l(t('Configure'), 'admin/content/node-type/'. $type['url_str'] .'/fields/'. $field['field_name'])),
'remove' => array('#value' => l(t('Remove'), 'admin/content/node-type/'. $type['url_str'] .'/fields/'. $field['field_name'] .'/remove')),
@@ -151,114 +147,289 @@
'parent' => array('#type' => 'select', '#options' => $group_options, '#default_value' => ''),
'hidden_name' => array('#type' => 'hidden', '#default_value' => $field['field_name']),
'#leaf' => TRUE,
+ '#row_type' => 'field',
);
- $dummy[$name] = array('#weight' => $weight, '#value' => $name .' ');
if ($field['locked']) {
$form[$name]['configure'] = array('#value' => t('Locked'));
$form[$name]['remove'] = array();
$form[$name]['#disabled_row'] = true;
}
+ $weights[] = $weight;
}
// Groups.
foreach ($groups as $name => $group) {
$weight = $group['weight'];
$form[$name] = array(
- 'human_name' => array('#value' => check_plain($group['label'])),
- 'name' => array('#value' => $group['group_name']),
- 'type' => array(),
+ 'label' => array('#value' => check_plain($group['label'])),
+ 'group_name' => array('#value' => $group['group_name']),
'configure' => array('#value' => l(t('Configure'), 'admin/content/node-type/'. $type['url_str'] .'/groups/'. $group['group_name'])),
'remove' => array('#value' => l(t('Remove'), 'admin/content/node-type/'. $type['url_str'] .'/groups/'. $group['group_name'] .'/remove')),
'weight' => array('#type' => 'textfield', '#default_value' => $weight),
'parent' => array('#type' => 'hidden', '#default_value' => ''),
'hidden_name' => array('#type' => 'hidden', '#default_value' => $group['group_name']),
'#root' => TRUE,
+ '#row_type' => 'group',
);
- $dummy[$name] = array('#weight' => $weight, '#value' => $name .' ');
// Adjust child fields rows.
foreach ($group['fields'] as $field_name => $field) {
- $form[$field_name]['#depth'] = 1;
$form[$field_name]['parent']['#default_value'] = $name;
- $dummy[$name][$field_name] = $dummy[$field_name];
- unset($dummy[$field_name]);
}
+ $weights[] = $weight;
}
// Non-CCK 'fields'.
foreach ($extra as $name => $label) {
$weight = $extra[$name]['weight'];
$form[$name] = array(
- 'human_name' => array('#value' => t($extra[$name]['label'])),
- 'name' => array('#value' => isset($extra[$name]['description']) ? $extra[$name]['description'] : ''),
- 'type' => array(),
- 'configure' => array(),
- 'remove' => array(),
+ 'label' => array('#value' => t($extra[$name]['label'])),
+ 'description' => array('#value' => isset($extra[$name]['description']) ? $extra[$name]['description'] : ''),
'weight' => array('#type' => 'textfield', '#default_value' => $weight),
'parent' => array('#type' => 'hidden', '#default_value' => ''),
'hidden_name' => array('#type' => 'hidden', '#default_value' => $name),
'#leaf' => TRUE,
'#root' => TRUE,
'#disabled_row' => TRUE,
- '#extra_field' => TRUE,
+ '#row_type' => 'extra',
+ );
+ $weights[] = $weight;
+ }
+
+ // Additional row : add new field.
+ $weight = max($weights) + 1;
+ $field_type_options = content_field_type_options();
+ $widget_type_options = content_widget_type_options(NULL, TRUE);
+ array_unshift($field_type_options, t('- Select a field type -'));
+ array_unshift($widget_type_options, t('- Select a widget -'));
+ if ($field_type_options && $widget_type_options) {
+ $name = '_add_new_field';
+ $form[$name] = array(
+ 'label' => array(
+ '#type' => 'textfield',
+ '#size' => 15,
+ '#description' => t('Human-readable name.'),
+ ),
+ 'field_name' => array(
+ '#type' => 'textfield',
+ '#field_prefix' => 'field_',
+ '#size' => 15,
+ '#description' => t('Machine-readable name.'),
+ // '#description' => t('Machine-readable name, cannot be changed.'),
+ ),
+ 'type' => array(
+ '#type' => 'select',
+ '#options' => $field_type_options,
+ '#description' => t('Type of data to store.'),
+ ),
+ 'widget_type' => array(
+ '#type' => 'select',
+ '#options' => $widget_type_options,
+ '#description' => t('Form element to edit the data.'),
+ ),
+ 'weight' => array('#type' => 'textfield', '#default_value' => $weight),
+ 'parent' => array('#type' => 'select', '#options' => $group_options, '#default_value' => ''),
+ 'hidden_name' => array('#type' => 'hidden', '#default_value' => $name),
+ '#leaf' => TRUE,
+ '#add_new' => TRUE,
+ '#row_type' => $name,
+ );
+ }
+
+ // Additional row : add existing field.
+ $existing_field_options = content_existing_field_options($type_name);
+ if ($existing_field_options && $widget_type_options) {
+ $weight++;
+ array_unshift($existing_field_options, t('- Select an existing field -'));
+ $name = '_add_existing_field';
+ $form[$name] = array(
+ 'label' => array(
+ '#type' => 'textfield',
+ '#size' => 15,
+ '#description' => t('Human-readable name.'),
+ ),
+ 'field_name' => array(
+ '#type' => 'select',
+ '#options' => $existing_field_options,
+ '#description' => t('Field to share.'),
+ ),
+ 'widget_type' => array(
+ '#type' => 'select',
+ '#options' => $widget_type_options,
+ '#description' => t('Form element to edit the data.'),
+ ),
+ 'weight' => array('#type' => 'textfield', '#default_value' => $weight),
+ 'parent' => array('#type' => 'select', '#options' => $group_options, '#default_value' => ''),
+ 'hidden_name' => array('#type' => 'hidden', '#default_value' => $name),
+ '#leaf' => TRUE,
+ '#add_new' => TRUE,
+ '#row_type' => $name,
);
- $dummy[$name] = array('#weight' => $weight, '#value' => $name .' ');
}
- // Let drupal_render figure out the right order for the rows.
- $form['#order'] = explode(' ', trim(drupal_render($dummy)));
+ // Additional row : add new group.
+ if (module_exists('fieldgroup')) {
+ $weight++;
+ $name = '_add_new_group';
+ $form[$name] = array(
+ 'label' => array(
+ '#type' => 'textfield',
+ '#size' => 15,
+ '#description' => t('Human-readable name.'),
+ ),
+ 'weight' => array('#type' => 'textfield', '#default_value' => $weight),
+ 'parent' => array('#type' => 'hidden', '#default_value' => ''),
+ 'hidden_name' => array('#type' => 'hidden', '#default_value' => $name),
+ '#root' => TRUE,
+ '#add_new' => TRUE,
+ '#row_type' => $name,
+ );
+ }
$form['submit'] = array('#type' => 'submit', '#value' => t('Save'));
return $form;
}
/**
- * Theme the field overview table.
+ * Theme the field overview table.
*/
function theme_content_admin_field_overview_form($form) {
- if (empty($form['#order'])) {
- return;
+ // Put weight and parenting values into a $dummy render structure
+ // that will figure out the corresponding row order.
+ $dummy = array();
+ $field_rows = array_merge($form['#fields'], $form['#extra'], array('_add_new_field', '_add_existing_field'));
+ $group_rows = array_merge($form['#groups'], array('_add_new_group'));
+ // Group rows: account for weight.
+ if (module_exists('fieldgroup')) {
+ foreach ($group_rows as $name) {
+ $dummy[$name] = array('#weight' => $form[$name]['weight']['#value'], '#value' => $name .' ');
+ }
}
+ // Field rows : account for weight and parenting.
+ foreach ($field_rows as $name) {
+ $dummy[$name] = array('#weight' => $form[$name]['weight']['#value'], '#value' => $name .' ');
+ if (module_exists('fieldgroup')) {
+ if ($parent = $form[$name]['parent']['#value']) {
+ $form[$name]['#depth'] = 1;
+ $dummy[$parent][$name] = $dummy[$name];
+ unset($dummy[$name]);
+ }
+ }
+ }
+ $order = explode(' ', trim(drupal_render($dummy)));
+
+ // Fill the actual table rows.
$header = array(t('Label'), t('Weight'), t('Name'), t('Type'), t('Operations'));
$rows = array();
- foreach ($form['#order'] as $key) {
+ while ($order) {
$row = array();
+ $key = reset($order);
$element = &$form[$key];
+
+ // Only display the 'Add' separator if the 'add' rows are still
+ // at the end of the table.
+ if (!isset($added_separator)) {
+ $remaining_rows = array_diff($order, array('_add_new_field', '_add_existing_field', '_add_new_group'));
+ if (empty($remaining_rows) && empty($element['#depth'])) {
+ $rows[] = array('data' => array(array('data' => t('Add'), 'colspan' => 4, 'class' => 'region')), 'class' => 'tabledrag-leaf region');
+ $added_separator = TRUE;
+ }
+ }
+
$element['weight']['#attributes']['class'] = 'field-weight';
$element['parent']['#attributes']['class'] = 'group-parent';
$element['hidden_name']['#attributes']['class'] = 'field-name';
- if (in_array($key, $form['#groups'])) {
- $element['human_name']['#prefix'] = '';
- $element['human_name']['#suffix'] = '';
- }
- $row[] = theme('indentation', isset($element['#depth']) ? $element['#depth'] : 0) . drupal_render($element['human_name']);
- // tabledrag.js cell hiding doesn't work well with colspans in table rows,
- // so we add the cell to hide *before* the ones with colspans.
- $row[] = drupal_render($element['weight']) . drupal_render($element['parent']) . drupal_render($element['hidden_name']);
- if (isset($element['#extra_field'])) {
- $row[] = array('data' => drupal_render($element['name']), 'colspan' => 3);
- }
- else {
- $row[] = drupal_render($element['name']);
- $row[] = drupal_render($element['type']);
- $row[] = drupal_render($element['configure']) .' '. drupal_render($element['remove']);
+ $indent = theme('indentation', isset($element['#depth']) ? $element['#depth'] : 0);
+ switch ($element['#row_type']) {
+ case 'field':
+ $row[] = $indent . drupal_render($element['label']);
+ // tabledrag.js cell hiding doesn't work well with colspans in table rows,
+ // so we add the cell to hide *before* the ones with colspans.
+ $row[] = drupal_render($element['weight']) . drupal_render($element['parent']) . drupal_render($element['hidden_name']);
+ $row[] = drupal_render($element['field_name']);
+ $row[] = drupal_render($element['type']);
+ $row[] = drupal_render($element['configure']) .' '. drupal_render($element['remove']);
+ break;
+ case 'group':
+ $element['label']['#prefix'] = '';
+ $element['label']['#suffix'] = '';
+ $row[] = $indent . drupal_render($element['label']);
+ $row[] = drupal_render($element['weight']) . drupal_render($element['parent']) . drupal_render($element['hidden_name']);
+ $row[] = drupal_render($element['group_name']);
+ $row[] = '';
+ $row[] = drupal_render($element['configure']) .' '. drupal_render($element['remove']);
+ break;
+ case 'extra':
+ $row[] = $indent . drupal_render($element['label']);
+ $row[] = drupal_render($element['weight']) . drupal_render($element['parent']) . drupal_render($element['hidden_name']);
+ $row[] = array('data' => drupal_render($element['description']), 'colspan' => 3);
+ break;
+ case '_add_new_field';
+ $element['type']['#attributes'] = array('class' => 'content-field-type-select');
+ $element['widget_type']['#attributes'] = array('class' => 'content-widget-type-select');
+ if (empty($element['label']['#value'])) {
+ $element['label']['#value'] = t('New field');
+ $element['label']['#attributes'] = array('class' => 'content-default-value');
+ }
+ $row[] = $indent . drupal_render($element['label']);
+ $row[] = drupal_render($element['weight']) . drupal_render($element['parent']) . drupal_render($element['hidden_name']);
+ $row[] = drupal_render($element['field_name']);
+ $row[] = drupal_render($element['type']);
+ $row[] = drupal_render($element['widget_type']);
+ break;
+ case '_add_existing_field':
+ $element['field_name']['#attributes'] = array('class' => 'content-field-select');
+ $element['widget_type']['#attributes'] = array('class' => 'content-widget-type-select');
+ $element['label']['#attributes'] = array('class' => 'content-label-textfield');
+ if (empty($element['label']['#value'])) {
+ $element['label']['#value'] = t('Existing field');
+ $element['label']['#attributes']['class'] .= ' content-default-value';
+ }
+ $row[] = $indent . drupal_render($element['label']);
+ $row[] = drupal_render($element['weight']) . drupal_render($element['parent']) . drupal_render($element['hidden_name']);
+ $row[] = array('data' => drupal_render($element['field_name']), 'colspan' => 2);
+ $row[] = drupal_render($element['widget_type']);
+ break;
+ case '_add_new_group':
+ if (empty($element['label']['#value'])) {
+ $element['label']['#value'] = t('New group');
+ $element['label']['#attributes'] = array('class' => 'content-default-value');
+ }
+ $row[] = $indent . drupal_render($element['label']);
+ $row[] = drupal_render($element['weight']) . drupal_render($element['parent']) . drupal_render($element['hidden_name']);
+ $row[] = '';
+ $row[] = '';
+ $row[] = '';
+ break;
}
$class = 'draggable';
$class .= isset($element['#disabled_row']) ? ' menu-disabled' : '';
+ $class .= isset($element['#add_new']) ? ' content-add-new' : '';
$class .= isset($element['#leaf']) ? ' tabledrag-leaf' : '';
$class .= isset($element['#root']) ? ' tabledrag-root' : '';
$rows[] = array('data' => $row, 'class' => $class);
+
+ array_shift($order);
}
$output = theme('table', $header, $rows, array('id' => 'content-field-overview'));
-
+// drupal_add_tabledrag('content-field-overview', 'match', 'parent', 'group-parent', 'group-parent', 'field-name', FALSE, 1);
drupal_add_tabledrag('content-field-overview', 'match', 'parent', 'group-parent', 'group-parent', 'field-name', TRUE, 1);
+// drupal_add_tabledrag('content-field-overview', 'order', 'sibling', 'field-weight', NULL, NULL, FALSE);
drupal_add_tabledrag('content-field-overview', 'order', 'sibling', 'field-weight');
- // Hide the 'Save' button, show it when fields are swapped.
- $form['submit']['#attributes']['class'] = 'content-admin-field-overview-submit';
- drupal_add_js('if (Drupal.jsEnabled) { $(document).ready(function() { $(".content-admin-field-overview-submit").hide(); }); }', 'inline');
+ $js_fields = array();
+ foreach(array_keys(content_existing_field_options($form['#type_name'])) as $field_name) {
+ $field = content_fields($field_name);
+ $js_fields[$field_name] = array('label' => $field['widget']['label'], 'type' => $field['type']);
+ }
+
+ $js_setting = array(
+ 'contentWidgetTypes' => content_widget_type_options(),
+ 'contentFields' => $js_fields,
+ );
+ drupal_add_js($js_setting, 'setting');
drupal_add_js(drupal_get_path('module', 'content') .'/content.js');
$output .= drupal_render($form);
@@ -266,6 +437,118 @@
return $output;
}
+function content_admin_field_overview_form_validate($form, &$form_state) {
+ _content_admin_field_overview_form_validate_add_new($form, &$form_state);
+ _content_admin_field_overview_form_validate_add_existing($form, &$form_state);
+// form_set_error('', 'foo');
+}
+
+/**
+ * Helper function for content_admin_field_overview_form_validate.
+ *
+ * Validate the 'add new field' row.
+ */
+function _content_admin_field_overview_form_validate_add_new($form, &$form_state) {
+ $field = $form_state['values']['_add_new_field'];
+
+ // Validate if any information was provided in the 'add new field' row.
+ if (array_filter(array($field['label'], $field['field_name'], $field['type'], $field['widget_type']))) {
+ // No label.
+ if (!$field['label']) {
+ form_set_error('_add_new_field][label', t('Add new field: you need to provide a label.'));
+ }
+
+ // No field name.
+ if (!$field['field_name']) {
+ form_set_error('_add_new_field][field_name', t('Add new field: you need to provide a field name.'));
+ }
+ // Field name validation.
+ else {
+ $field_name = $field['field_name'];
+
+ // Add the 'field_' prefix.
+ if (substr($field_name, 0, 6) != 'field_') {
+ $field_name = 'field_'. $field_name;
+ form_set_value($form['_add_new_field']['field_name'], $field_name, $form_state);
+ }
+
+ // Invalid field name.
+ if (!preg_match('!^field_[a-z0-9_]+$!', $field_name)) {
+ form_set_error('_add_new_field][field_name', t('Add new field: the field name %field_name is invalid. The name must include only lowercase unaccentuated letters, numbers, and underscores.', array('%field_name' => $field_name)));
+ }
+ if (strlen($field_name) > 32) {
+ form_set_error('_add_new_field][field_name', t('Add new field: the field name %field_name is too long. The name is limited to 32 characters, including the \'field_\' prefix.', array('%field_name' => $field_name)));
+ }
+ if ($field_name == 'field_instance') {
+ form_set_error('_add_new_field][field_name', t("Add new field: the name 'field_instance' is a reserved name."));
+ }
+
+ // Field name already exists.
+ // We need to check inactive fields as well, so we can't use content_fields().
+ module_load_include('inc', 'content', 'includes/content.crud');
+ $fields = content_field_instance_read(array(), TRUE);
+ $used = FALSE;
+ foreach ($fields as $existing_field) {
+ $used |= ($existing_field['field_name'] == $field_name);
+ }
+ if ($used) {
+ form_set_error('_add_new_field][field_name', t('Add new field: the field name %field_name already exists.', array('%field_name' => $field_name)));
+ }
+ }
+
+ // No field type.
+ if (!$field['type']) {
+ form_set_error('_add_new_field][type', t('Add new field: you need to select a field type.'));
+ }
+
+ // No widget type.
+ if (!$field['widget_type']) {
+ form_set_error('_add_new_field][widget_type', t('Add new field: you need to select a widget.'));
+ }
+ // Wrong widget type.
+ elseif ($field['type']) {
+ $widget_types = content_widget_type_options($field['type']);
+ if (!isset($widget_types[$field['widget_type']])) {
+ form_set_error('_add_new_field][widget_type', t('Add new field: invalid widget.'));
+ }
+ }
+ }
+}
+
+/**
+ * Helper function for content_admin_field_overview_form_validate.
+ *
+ * Validate the 'add existing field' row.
+ */
+function _content_admin_field_overview_form_validate_add_existing($form, &$form_state) {
+ $field = $form_state['values']['_add_existing_field'];
+
+ // Validate if any information was provided in the 'add existing field' row.
+ if (array_filter(array($field['label'], $field['field_name'], $field['widget_type']))) {
+ // No label.
+ if (!$field['label']) {
+ form_set_error('_add_existing_field][label', t('Add existing field: you need to provide a label.'));
+ }
+
+ // No existing field.
+ if (!$field['field_name']) {
+ form_set_error('_add_existing_field][field_name', t('Add existing field: you need to select a field.'));
+ }
+
+ // No widget type.
+ if (!$field['widget_type']) {
+ form_set_error('_add_existing_field][widget_type', t('Add existing field: you need to select a widget.'));
+ }
+ // Wrong widget type.
+ elseif ($field['field_name'] && ($existing_field = content_fields($field['field_name']))) {
+ $widget_types = content_widget_type_options($existing_field['type']);
+ if (!isset($widget_types[$field['widget_type']])) {
+ form_set_error('_add_existing_field][widget_type', t('Add existing field: invalid widget.'));
+ }
+ }
+ }
+}
+
function content_admin_field_overview_form_submit($form, &$form_state) {
$form_values = $form_state['values'];
@@ -290,6 +573,49 @@
}
content_clear_type_cache();
+
+ // TODO : weights > 1000
+
+ // Create new field.
+ if (!empty($form_values['_add_new_field']['field_name'])) {
+ $field = $form_values['_add_new_field'];
+ $field['type_name'] = $form['#type_name'];
+
+ module_load_include('inc', 'content', 'includes/content.crud');
+ if (content_field_instance_create($field)) {
+ drupal_set_message(t('Created field %label.', array(
+ '%label' => $field['label'])));
+ $form_state['fields_added']['_add_new_field'] = $field['field_name'];
+ }
+ else {
+ drupal_set_message(t('There was a problem creating field %label.', array(
+ '%label' => $field['label'])));
+ }
+ }
+
+ // Add existing field.
+ if (!empty($form_values['_add_existing_field']['field_name'])) {
+ $field = $form_values['_add_existing_field'];
+ $field['type_name'] = $form['#type_name'];
+ $existing_field = content_fields($field['field_name']);
+
+ if ($existing_field['locked']) {
+ drupal_set_message(t('The field %label cannot be added to a content type because it is locked.',
+ array('%label' => $field['field_name'])));
+ }
+ else {
+ module_load_include('inc', 'content', 'includes/content.crud');
+ if (content_field_instance_create($field)) {
+ drupal_set_message(t('Added field %label.', array(
+ '%label' => $field['field_name'])));
+ $form_state['fields_added']['_add_existing_field'] = $field['field_name'];
+ }
+ else {
+ drupal_set_message(t('There was a problem adding field %label.', array(
+ '%label' => $field['field_name'])));
+ }
+ }
+ }
}
/**
@@ -316,11 +642,6 @@
}
$contexts = _content_admin_display_contexts($contexts_selector);
- // Rows in this table are essentially nested, but for the simplicity of
- // theme and submit functions, we keep them in a flat array, and use a
- // $dummy render structure to figure the right display order.
- $dummy = array();
-
$form = array(
'#tree' => TRUE,
'#type_name' => $type['type'],
@@ -342,7 +663,9 @@
$weight = $field['widget']['weight'];
$form[$name] = array(
- 'human_name' => array('#value' => check_plain($field['widget']['label'])), // OK
+ 'human_name' => array('#value' => check_plain($field['widget']['label'])),
+ 'weight' => array('#type' => 'value', '#value' => $weight),
+ 'parent' => array('#type' => 'value', '#value' => ''),
);
// Label
@@ -367,8 +690,6 @@
'#default_value' => isset($defaults[$key]['format']) ? $defaults[$key]['format'] : 'default',
);
}
-
- $dummy[$name] = array('#weight' => $weight, '#value' => $name .' ');
}
// Groups.
@@ -390,6 +711,7 @@
$form[$name] = array(
'human_name' => array('#value' => check_plain($group['label'])),
+ 'weight' => array('#type' => 'value', '#value' => $weight),
);
if ($contexts_selector == CONTENT_CONTEXTS_SIMPLE) {
$form[$name]['label'] = array(
@@ -405,18 +727,11 @@
'#default_value' => isset($defaults[$key]) ? $defaults[$key] : 'fieldset',
);
}
- $dummy[$name] = array('#weight' => $weight, '#value' => $name .' ');
- // Adjust child fields rows.
foreach ($group['fields'] as $field_name => $field) {
- $form[$field_name]['#depth'] = 1;
- $dummy[$name][$field_name] = $dummy[$field_name];
- unset($dummy[$field_name]);
+ $form[$field_name]['parent']['#value'] = $name;
}
}
- // Let drupal_render figure out the right order for the rows.
- $form['#order'] = explode(' ', trim(drupal_render($dummy)));
-
$form['submit'] = array('#type' => 'submit', '#value' => t('Save'));
return $form;
}
@@ -425,8 +740,32 @@
* Theme the display overview table.
*/
function theme_content_admin_display_overview_form($form) {
+ // Put weight and parenting values into a $dummy render structure
+ // that will figure out the corresponding row order.
+ $dummy = array();
+ $field_rows = $form['#fields'];
+ $group_rows = $form['#groups'];
+ // Group rows: account for weight.
+ if (module_exists('fieldgroup')) {
+ foreach ($group_rows as $name) {
+ $dummy[$name] = array('#weight' => $form[$name]['weight']['#value'], '#value' => $name .' ');
+ }
+ }
+ // Field rows : account for weight and parenting.
+ foreach ($field_rows as $name) {
+ $dummy[$name] = array('#weight' => $form[$name]['weight']['#value'], '#value' => $name .' ');
+ if (module_exists('fieldgroup')) {
+ if ($parent = $form[$name]['parent']['#value']) {
+ $form[$name]['#depth'] = 1;
+ $dummy[$parent][$name] = $dummy[$name];
+ unset($dummy[$name]);
+ }
+ }
+ }
+ $order = explode(' ', trim(drupal_render($dummy)));
+
$output = '';
- if (isset($form['#order'])) {
+ if (isset($order)) {
$contexts_selector = $form['#contexts'];
$contexts = _content_admin_display_contexts($contexts_selector);
$header = array(t('Field'));
@@ -438,7 +777,7 @@
}
$rows = array();
- foreach ($form['#order'] as $key) {
+ foreach ($order as $key) {
$row = array();
$element = &$form[$key];
if (in_array($key, $form['#groups'])) {
@@ -524,36 +863,59 @@
/**
* Return an array of widget type options for a field type.
+ *
+ * If no field type is provided, returns a nested array of
+ * all widget types, keyed by field type human name
*/
-function content_widget_type_options($field_type) {
+function content_widget_type_options($field_type = NULL, $by_label = FALSE) {
static $options;
if (!isset($options)) {
- $widget_types = _content_widget_types();
$options = array();
- foreach ($widget_types as $widget_type_name => $widget_type) {
+ foreach (_content_widget_types() as $widget_type_name => $widget_type) {
foreach($widget_type['field types'] as $widget_field_type) {
$options[$widget_field_type][$widget_type_name] = t($widget_type['label']);
}
}
}
- return !empty($options[$field_type]) ? $options[$field_type] : array();
+ if ($field_type) {
+ return !empty($options[$field_type]) ? $options[$field_type] : array();
+ }
+ elseif ($by_label) {
+ $field_types = _content_field_types();
+ $options_by_label = array();
+ foreach ($options as $field_type => $widgets) {
+ $options_by_label[t($field_types[$field_type]['label'])] = $widgets;
+ }
+ return $options_by_label;
+ }
+ else {
+ return $options;
+ }
}
-function _content_admin_field_add_existing(&$form_state, $type_name) {
- $output = '';
+/**
+ * Return an array of existing field to be added to a node type.
+ */
+function content_existing_field_options($type_name) {
$type = content_types($type_name);
$fields = content_fields();
- $form = array();
+ $field_types = _content_field_types();
$options = array();
foreach ($fields as $field) {
if (!isset($type['fields'][$field['field_name']]) && !$field['locked']) {
- $options[$field['field_name']] = t($field['widget']['label']) .' ('. $field['field_name'] .')';
+ $field_type = $field_types[$field['type']];
+ $options[$field['field_name']] = t('@type: @label (@field)', array('@type' => t($field_type['label']), '@label' => t($field['widget']['label']), '@field' => $field['field_name']));
}
}
- if ($options) {
+ return $options;
+}
+
+function _content_admin_field_add_existing(&$form_state, $type_name) {
+ $form = array();
+ if ($options = content_existing_field_options($type_name)) {
$form['existing'] = array(
'#type' => 'fieldset',
'#title' => t('Add existing field'),
Index: content.js
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/cck/content.js,v
retrieving revision 1.1
diff -u -r1.1 content.js
--- content.js 2 Mar 2008 23:18:08 -0000 1.1
+++ content.js 1 Sep 2008 18:19:38 -0000
@@ -1,20 +1,101 @@
// $Id: content.js,v 1.1 2008/03/02 23:18:08 yched Exp $
-/**
- * Show the Save button when fields are swapped.
- *
- * This behavior is dependent on the tableDrag behavior, since it uses the
- * objects initialized in that behavior to update the row.
- */
-Drupal.behaviors.cckFieldDrag = function(context) {
- var tableDrag = Drupal.tableDrag['content-field-overview']; // Get the tableDrag object.
-
- // Add a handler for when a row is dropped,
- // show Save button if the table has been changed.
- tableDrag.onDrop = function() {
- if (tableDrag.changed) {
- $('.content-admin-field-overview-submit').fadeIn('slow');
- }
- }
+
+Drupal.behaviors.cckManageFields = function(context) {
+ attachDefaultValues(context);
+ attachUpdateSelects(context);
+};
+
+/* (borrowed from quicksketch's webforms.module) */
+function attachDefaultValues(context) {
+ var fields = $('#content-field-overview .content-default-value', context);
+ var forms = fields.parents('form:first');
+ fields.each(function() {
+ this.defaultValue = this.value;
+ $(this).focus(function() {
+ if (this.value == this.defaultValue) {
+ this.value = '';
+ }
+ $(this).removeClass('content-default-value');
+ });
+ $(this).blur(function() {
+ if (this.value == '') {
+ $(this).addClass('content-default-value');
+ this.value = this.defaultValue;
+ }
+ });
+ });
+
+ // Clear all the form elements before submission.
+ forms.submit(function() {
+ fields.focus();
+ });
};
+function attachUpdateSelects(context) {
+ var widgetTypes = Drupal.settings.contentWidgetTypes;
+ var fields = Drupal.settings.contentFields;
+ console.log
+
+ // Store the default text of widget selects.
+ $('#content-field-overview .content-widget-type-select', context).each(function() {
+ this.initialValue = this.options[0].text;
+ });
+
+ // Field type select updates its widget select.
+ $('#content-field-overview .content-field-type-select', context).each(function() {
+ this.targetSelect = $('.content-widget-type-select', $(this).parents('tr'));
+
+ $(this).change(function() {
+ selectedFieldType = this.options[this.selectedIndex].value;
+ this.targetSelect.contentOptions((selectedFieldType in widgetTypes) ? widgetTypes[selectedFieldType] : [ ]);
+ });
+
+ $(this).trigger('change');
+ });
+
+ // Existing field select updates its widget select and label textfield.
+ $('#content-field-overview .content-field-select', context).each(function() {
+ this.targetSelect = $('.content-widget-type-select', $(this).parents('tr'));
+ this.targetTextfield = $('.content-label-textfield', $(this).parents('tr'));
+
+ $(this).change(function(e, updateText) {
+ updateText = (typeof(updateText) == 'undefined') ? true : updateText;
+ selectedField = this.options[this.selectedIndex].value;
+ selectedFieldType = (selectedField in fields) ? fields[selectedField].type : null;
+ // TODO : we should preseect the widget used by the original field.
+ this.targetSelect.contentOptions((selectedFieldType && (selectedFieldType in widgetTypes)) ? widgetTypes[selectedFieldType] : [ ]);
+
+ if (updateText) {
+ $(this.targetTextfield)
+ .attr('value', (selectedField in fields) ? fields[selectedField].label : '')
+ .focus().blur();
+ $(this).focus();
+ }
+ });
+
+ $(this).trigger('change', false);
+ });
+}
+
+jQuery.fn.contentOptions = function(options) {
+ return this.each(function() {
+ disabled = false;
+ if (options.length == 0) {
+ options = [this.initialValue];
+ disabled = true;
+ }
+
+ selectedValue = this.options[this.selectedIndex].value;
+
+ html = '';
+ jQuery.each(options, function(value, text) {
+ selected = (value == selectedValue) ? ' selected="selected"' : '';
+ html += '';
+ });
+
+ $(this)
+ .html(html)
+ .attr('disabled', disabled ? 'disabled' : '');
+ });
+}
\ No newline at end of file