#516138 by yched, KarenS, quicksketch, bangpound, et al.: CC-FREAKING-K IN CORE! OH YEAH! :D
parent
24289301ab
commit
e998857eb8
|
@ -100,6 +100,63 @@ function hook_fieldable_info_alter(&$info) {
|
|||
$info['node']['cacheable'] = FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose "pseudo-field" components on fieldable objects.
|
||||
*
|
||||
* Field UI's 'Manage fields' page lets users re-order fields, but also
|
||||
* non-field components. For nodes, that would be title, menu settings, or
|
||||
* other elements exposed by contributed modules through hook_form() or
|
||||
* hook_form_alter().
|
||||
*
|
||||
* Fieldable entities or contributed modules that want to have their components
|
||||
* supported should expose them using this hook, and use
|
||||
* field_attach_extra_weight() to retrieve the user-defined weight when
|
||||
* inserting the component.
|
||||
*
|
||||
* @param $bundle
|
||||
* The name of the bundle being considered.
|
||||
* @return
|
||||
* An array of 'pseudo-field' components. The keys are the name of the element
|
||||
* as it appears in the form structure. The values are arrays with the
|
||||
* following key/value pairs:
|
||||
* - label: The human readable name of the component.
|
||||
* - description: A short description of the component contents.
|
||||
* - weight: The default weight of the element.
|
||||
* - view: (optional) The name of the element as it appears in the rendered
|
||||
* structure, if different from the name in the form.
|
||||
*/
|
||||
function hook_field_extra_fields($bundle) {
|
||||
$extra = array();
|
||||
|
||||
if ($type = node_type_get_type($bundle)) {
|
||||
if ($type->has_title) {
|
||||
$extra['title'] = array(
|
||||
'label' => $type->title_label,
|
||||
'description' => t('Node module element.'),
|
||||
'weight' => -5,
|
||||
);
|
||||
}
|
||||
if ($bundle == 'poll' && module_exists('poll')) {
|
||||
$extra['title'] = array(
|
||||
'label' => t('Poll title'),
|
||||
'description' => t('Poll module title.'),
|
||||
'weight' => -5,
|
||||
);
|
||||
$extra['choice_wrapper'] = array(
|
||||
'label' => t('Poll choices'),
|
||||
'description' => t('Poll module choices.'),
|
||||
'weight' => -4,
|
||||
);
|
||||
$extra['settings'] = array(
|
||||
'label' => t('Poll settings'),
|
||||
'description' => t('Poll module settings.'),
|
||||
'weight' => -3,
|
||||
);
|
||||
}
|
||||
}
|
||||
return $extra;
|
||||
}
|
||||
|
||||
/**
|
||||
* @} End of "ingroup field_fieldable_type"
|
||||
*/
|
||||
|
|
|
@ -457,6 +457,11 @@ function _field_invoke_multiple_default($op, $obj_type, $objects, &$a = NULL, &$
|
|||
function field_attach_form($obj_type, $object, &$form, &$form_state) {
|
||||
$form += (array) _field_invoke_default('form', $obj_type, $object, $form, $form_state);
|
||||
|
||||
// Add custom weight handling.
|
||||
list($id, $vid, $bundle) = field_attach_extract_ids($obj_type, $object);
|
||||
$form['#pre_render'][] = '_field_extra_weights_pre_render';
|
||||
$form['#extra_fields'] = field_extra_fields($bundle);
|
||||
|
||||
// Let other modules make changes to the form.
|
||||
foreach (module_implements('field_attach_form') as $module) {
|
||||
$function = $module . '_field_attach_form';
|
||||
|
@ -1043,6 +1048,11 @@ function field_attach_view($obj_type, $object, $build_mode = 'full') {
|
|||
|
||||
$output = _field_invoke_default('view', $obj_type, $object, $build_mode);
|
||||
|
||||
// Add custom weight handling.
|
||||
list($id, $vid, $bundle) = field_attach_extract_ids($obj_type, $object);
|
||||
$output['#pre_render'][] = '_field_extra_weights_pre_render';
|
||||
$output['#extra_fields'] = field_extra_fields($bundle);
|
||||
|
||||
// Let other modules make changes after rendering the view.
|
||||
drupal_alter('field_attach_view', $output, $obj_type, $object, $build_mode);
|
||||
|
||||
|
@ -1050,6 +1060,24 @@ function field_attach_view($obj_type, $object, $build_mode = 'full') {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the user-defined weight for a 'pseudo-field' component.
|
||||
*
|
||||
* @param $bundle
|
||||
* The bundle name.
|
||||
* @param $pseudo_field
|
||||
* The name of the 'pseudo-field'.
|
||||
* @return
|
||||
* The weight for the 'pseudo-field', respecting the user settings stored by
|
||||
* field.module.
|
||||
*/
|
||||
function field_attach_extra_weight($bundle, $pseudo_field) {
|
||||
$extra = field_extra_fields($bundle);
|
||||
if (isset($extra[$pseudo_field])) {
|
||||
return $extra[$pseudo_field]['weight'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement hook_node_prepare_translation.
|
||||
*
|
||||
|
@ -1084,7 +1112,7 @@ function field_attach_create_bundle($bundle) {
|
|||
|
||||
// Clear the cache.
|
||||
field_cache_clear();
|
||||
|
||||
menu_rebuild();
|
||||
foreach (module_implements('field_attach_create_bundle') as $module) {
|
||||
$function = $module . '_field_attach_create_bundle';
|
||||
$function($bundle);
|
||||
|
|
|
@ -637,8 +637,8 @@ function field_read_instances($params = array(), $include_additional = array())
|
|||
foreach ($params as $key => $value) {
|
||||
$query->condition('fci.' . $key, $value);
|
||||
}
|
||||
$query->condition('fc.active', 1);
|
||||
if (!isset($include_additional['include_inactive']) || !$include_additional['include_inactive']) {
|
||||
$query->condition('fc.active', 1);
|
||||
$query->condition('fci.widget_active', 1);
|
||||
}
|
||||
if (!isset($include_additional['include_deleted']) || !$include_additional['include_deleted']) {
|
||||
|
|
|
@ -43,11 +43,8 @@ function field_default_submit($obj_type, $object, $field, $instance, &$items, $f
|
|||
function field_default_insert($obj_type, $object, $field, $instance, &$items) {
|
||||
// _field_invoke() populates $items with an empty array if the $object has no
|
||||
// entry for the field, so we check on the $object itself.
|
||||
if (!property_exists($object, $field['field_name']) && !empty($instance['default_value_function'])) {
|
||||
$function = $instance['default_value_function'];
|
||||
if (drupal_function_exists($function)) {
|
||||
$items = $function($obj_type, $object, $field, $instance);
|
||||
}
|
||||
if (empty($object) || !property_exists($object, $field['field_name'])) {
|
||||
$items = field_get_default_value($obj_type, $object, $field, $instance);
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
|
|
@ -37,13 +37,9 @@ function field_default_form($obj_type, $object, $field, $instance, $items, &$for
|
|||
'instance' => $instance,
|
||||
);
|
||||
|
||||
// Populate widgets with default values if we're creating a new object.
|
||||
if (empty($items) && empty($id) && !empty($instance['default_value_function'])) {
|
||||
$items = array();
|
||||
$function = $instance['default_value_function'];
|
||||
if (drupal_function_exists($function)) {
|
||||
$items = $function($obj_type, $object, $field, $instance);
|
||||
}
|
||||
// Populate widgets with default values when creating a new object.
|
||||
if (empty($items) && empty($id)) {
|
||||
$items = field_get_default_value($obj_type, $object, $field, $instance);
|
||||
}
|
||||
|
||||
$form_element = array();
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
*/
|
||||
function _field_info_cache_clear() {
|
||||
_field_info_collate_types(TRUE);
|
||||
drupal_static_reset('field_build_modes');
|
||||
_field_info_collate_fields(TRUE);
|
||||
}
|
||||
|
||||
|
@ -263,6 +264,11 @@ function _field_info_prepare_instance($instance, $field) {
|
|||
// Make sure all expected instance settings are present.
|
||||
$instance['settings'] += field_info_instance_settings($field['type']);
|
||||
|
||||
// Set a default value for the instance.
|
||||
if (field_behaviors_widget('default value', $instance) == FIELD_BEHAVIOR_DEFAULT && !isset($instance['default_value'])) {
|
||||
$instance['default_value'] = NULL;
|
||||
}
|
||||
|
||||
// Fallback to default widget if widget type is not available.
|
||||
if (!field_info_widget_types($instance['widget']['type'])) {
|
||||
$instance['widget']['type'] = $field_type['default_widget'];
|
||||
|
|
|
@ -265,6 +265,32 @@ function field_associate_fields($module) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to get the default value for a field on an object.
|
||||
*
|
||||
* @param $obj_type
|
||||
* The type of $object; e.g. 'node' or 'user'.
|
||||
* @param $object
|
||||
* The object for the operation.
|
||||
* @param $field
|
||||
* The field structure.
|
||||
* @param $instance
|
||||
* The instance structure.
|
||||
*/
|
||||
function field_get_default_value($obj_type, $object, $field, $instance) {
|
||||
$items = array();
|
||||
if (!empty($instance['default_value_function'])) {
|
||||
$function = $instance['default_value_function'];
|
||||
if (drupal_function_exists($function)) {
|
||||
$items = $function($obj_type, $object, $field, $instance);
|
||||
}
|
||||
}
|
||||
elseif (!empty($instance['default_value'])) {
|
||||
$items = $instance['default_value'];
|
||||
}
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to filter out empty values.
|
||||
*
|
||||
|
@ -279,15 +305,15 @@ function field_associate_fields($module) {
|
|||
* TODO D7: poorly named...
|
||||
*/
|
||||
function field_set_empty($field, $items) {
|
||||
// Filter out empty values.
|
||||
$filtered = array();
|
||||
$function = $field['module'] . '_field_is_empty';
|
||||
// We ensure the function is loaded, but explicitly break if it is missing.
|
||||
drupal_function_exists($function);
|
||||
foreach ((array) $items as $delta => $item) {
|
||||
if (!$function($item, $field)) {
|
||||
$filtered[] = $item;
|
||||
if ($function($item, $field)) {
|
||||
unset($items[$delta]);
|
||||
}
|
||||
}
|
||||
return $filtered;
|
||||
return array_values($items);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -335,7 +361,7 @@ function _field_sort_items_value_helper($a, $b) {
|
|||
* Registry of available build modes.
|
||||
*/
|
||||
function field_build_modes($obj_type) {
|
||||
static $info;
|
||||
$info = &drupal_static(__FUNCTION__, array());
|
||||
|
||||
if (!isset($info[$obj_type])) {
|
||||
$info[$obj_type] = module_invoke_all('field_build_modes', $obj_type);
|
||||
|
@ -343,6 +369,63 @@ function field_build_modes($obj_type) {
|
|||
return $info[$obj_type];
|
||||
}
|
||||
|
||||
/**
|
||||
* Registry of pseudo-field components in a given bundle.
|
||||
*
|
||||
* @param $bundle_name
|
||||
* The bundle name.
|
||||
* @return
|
||||
* The array of pseudo-field elements in the bundle.
|
||||
*/
|
||||
function field_extra_fields($bundle_name) {
|
||||
$info = &drupal_static(__FUNCTION__, array());
|
||||
|
||||
if (empty($info)) {
|
||||
$info = array();
|
||||
$bundles = field_info_bundles();
|
||||
foreach ($bundles as $bundle => $bundle_label) {
|
||||
// Gather information about non-field object additions.
|
||||
$extra = module_invoke_all('field_extra_fields', $bundle);
|
||||
drupal_alter('field_extra_fields', $extra, $bundle);
|
||||
|
||||
// Add saved weights.
|
||||
foreach (variable_get("field_extra_weights_$bundle", array()) as $key => $value) {
|
||||
// Some stored entries might not exist anymore, for instance if uploads
|
||||
// have been disabled or vocabularies were deleted.
|
||||
if (isset($extra[$key])) {
|
||||
$extra[$key]['weight'] = $value;
|
||||
}
|
||||
}
|
||||
$info[$bundle] = $extra;
|
||||
}
|
||||
}
|
||||
if (array_key_exists($bundle_name, $info)) {
|
||||
return $info[$bundle_name];
|
||||
}
|
||||
else {
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre-render callback to adjust weights of non-field elements on objects.
|
||||
*/
|
||||
function _field_extra_weights_pre_render($elements) {
|
||||
if (isset($elements['#extra_fields'])) {
|
||||
foreach ($elements['#extra_fields'] as $key => $value) {
|
||||
// Some core 'fields' use a different key in node forms and in 'view'
|
||||
// render arrays. Ensure that we are not on a form first.
|
||||
if (!isset($elements['#build_id']) && isset($value['view']) && isset($elements[$value['view']])) {
|
||||
$elements[$value['view']]['#weight'] = $value['weight'];
|
||||
}
|
||||
elseif (isset($elements[$key])) {
|
||||
$elements[$key]['#weight'] = $value['weight'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the cached information; called in several places when field
|
||||
* information is changed.
|
||||
|
|
|
@ -28,28 +28,28 @@ function list_field_info() {
|
|||
'list' => array(
|
||||
'label' => t('List'),
|
||||
'description' => t('This field stores numeric keys from key/value lists of allowed values where the key is a simple alias for the position of the value, i.e. 0|First option, 1|Second option, 2|Third option.'),
|
||||
'settings' => array('allowed_values_function' => ''),
|
||||
'settings' => array('allowed_values' => '', 'allowed_values_function' => ''),
|
||||
'default_widget' => 'options_select',
|
||||
'default_formatter' => 'list_default',
|
||||
),
|
||||
'list_boolean' => array(
|
||||
'label' => t('Boolean'),
|
||||
'description' => t('This field stores simple on/off or yes/no options.'),
|
||||
'settings' => array('allowed_values_function' => ''),
|
||||
'settings' => array('allowed_values' => '', 'allowed_values_function' => ''),
|
||||
'default_widget' => 'options_select',
|
||||
'default_formatter' => 'list_default',
|
||||
),
|
||||
'list_number' => array(
|
||||
'label' => t('List (numeric)'),
|
||||
'description' => t('This field stores keys from key/value lists of allowed numbers where the stored numeric key has significance and must be preserved, i.e. \'Lifetime in days\': 1|1 day, 7|1 week, 31|1 month.'),
|
||||
'settings' => array('allowed_values_function' => ''),
|
||||
'settings' => array('allowed_values' => '', 'allowed_values_function' => ''),
|
||||
'default_widget' => 'options_select',
|
||||
'default_formatter' => 'list_default',
|
||||
),
|
||||
'list_text' => array(
|
||||
'label' => t('List (text)'),
|
||||
'description' => t('This field stores keys from key/value lists of allowed values where the stored key has significance and must be a varchar, i.e. \'US States\': IL|Illinois, IA|Iowa, IN|Indiana'),
|
||||
'settings' => array('allowed_values_function' => ''),
|
||||
'settings' => array('allowed_values' => '', 'allowed_values_function' => ''),
|
||||
'default_widget' => 'options_select',
|
||||
'default_formatter' => 'list_default',
|
||||
),
|
||||
|
@ -97,6 +97,131 @@ function list_field_schema($field) {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement hook_field_settings_form().
|
||||
*/
|
||||
function list_field_settings_form($field, $instance) {
|
||||
$settings = $field['settings'];
|
||||
|
||||
$form['allowed_values'] = array(
|
||||
'#type' => 'textarea',
|
||||
'#title' => t('Allowed values list'),
|
||||
'#default_value' => $settings['allowed_values'],
|
||||
'#required' => FALSE,
|
||||
'#rows' => 10,
|
||||
'#description' => '<p>' . t('The possible values this field can contain. Enter one value per line, in the format key|label. The key is the value that will be stored in the database, and must be a %type value. The label is optional, and the key will be used as the label if no label is specified.', array('%type' => $field['type'] == 'list_text' ? t('text') : t('numeric'))) . '</p>',
|
||||
'#element_validate' => array('list_allowed_values_validate'),
|
||||
'#list_field_type' => $field['type'],
|
||||
'#access' => empty($settings['allowed_values_function']),
|
||||
);
|
||||
|
||||
// Alter the description for allowed values depending on the widget type.
|
||||
if ($instance['widget']['type'] == 'options_onoff') {
|
||||
$form['allowed_values']['#description'] .= '<p>' . t("For a 'single on/off checkbox' widget, define the 'off' value first, then the 'on' value in the <strong>Allowed values</strong> section. Note that the checkbox will be labeled with the label of the 'on' value.") . '</p>';
|
||||
}
|
||||
elseif ($instance['widget']['type'] == 'options_buttons') {
|
||||
$form['allowed_values']['#description'] .= '<p>' . t("The 'checkboxes/radio buttons' widget will display checkboxes if the <em>Number of values</em> option is greater than 1 for this field, otherwise radios will be displayed.") . '</p>';
|
||||
}
|
||||
$form['allowed_values']['#description'] .= t('Allowed HTML tags in labels: @tags', array('@tags' => _field_filter_xss_display_allowed_tags()));
|
||||
|
||||
$form['allowed_values_function'] = array(
|
||||
'#type' => 'value',
|
||||
'#value' => $settings['allowed_values_function'],
|
||||
);
|
||||
$form['allowed_values_function_display'] = array(
|
||||
'#type' => 'item',
|
||||
'#title' => t('Allowed values list'),
|
||||
'#markup' => t('The value of this field is being determined by the %function function and may not be changed.', array('%function' => $settings['allowed_values_function'])),
|
||||
'#access' => !empty($settings['allowed_values_function']),
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an array of allowed values for this field.
|
||||
*/
|
||||
function list_allowed_values($field) {
|
||||
$allowed_values = drupal_static(__FUNCTION__, array());
|
||||
|
||||
if (isset($allowed_values[$field['field_name']])) {
|
||||
return $allowed_values[$field['field_name']];
|
||||
}
|
||||
|
||||
$allowed_values[$field['field_name']] = array();
|
||||
|
||||
$function = $field['settings']['allowed_values_function'];
|
||||
if (!empty($function) && drupal_function_exists($function)) {
|
||||
$allowed_values[$field['field_name']] = $function($field);
|
||||
}
|
||||
elseif (!empty($field['settings']['allowed_values'])) {
|
||||
$allowed_values[$field['field_name']] = list_allowed_values_list($field['settings']['allowed_values'], $field['type'] == 'list');
|
||||
}
|
||||
|
||||
return $allowed_values[$field['field_name']];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an array of the allowed values for this field.
|
||||
*
|
||||
* Explode a string with keys and labels separated with '|' and with each new
|
||||
* value on its own line.
|
||||
*
|
||||
* @param $string_values
|
||||
* The list of choices as a string.
|
||||
* @param $position_keys
|
||||
* Boolean value indicating whether to generate keys based on the position of
|
||||
* the value if a key is not manually specified, effectively generating
|
||||
* integer-based keys. This should only be TRUE for fields that have a type of
|
||||
* "list". Otherwise the value will be used as the key if not specified.
|
||||
*/
|
||||
function list_allowed_values_list($string_values, $position_keys = FALSE) {
|
||||
$allowed_values = array();
|
||||
|
||||
$list = explode("\n", $string_values);
|
||||
$list = array_map('trim', $list);
|
||||
$list = array_filter($list, 'strlen');
|
||||
foreach ($list as $key => $value) {
|
||||
// Sanitize the user input with a permissive filter.
|
||||
$value = field_filter_xss($value);
|
||||
|
||||
// Check for a manually specified key.
|
||||
if (strpos($value, '|') !== FALSE) {
|
||||
list($key, $value) = explode('|', $value);
|
||||
}
|
||||
// Otherwise see if we need to use the value as the key. The "list" type
|
||||
// will automatically convert non-keyed lines to integers.
|
||||
elseif (!$position_keys) {
|
||||
$key = $value;
|
||||
}
|
||||
$allowed_values[$key] = (isset($value) && $value !== '') ? $value : $key;
|
||||
}
|
||||
|
||||
return $allowed_values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Element validate callback; check that the entered values are valid.
|
||||
*/
|
||||
function list_allowed_values_validate($element, &$form_state) {
|
||||
$values = list_allowed_values_list($element['#value'], $element['#list_field_type'] == 'list');
|
||||
$field_type = $element['#list_field_type'];
|
||||
foreach ($values as $key => $value) {
|
||||
if ($field_type == 'list_number' && !is_numeric($key)) {
|
||||
form_error($element, t('The entered available values are not valid. Each key must be a valid integer or decimal.'));
|
||||
break;
|
||||
}
|
||||
elseif ($field_type == 'list_text' && strlen($key) > 255) {
|
||||
form_error($element, t('The entered available values are not valid. Each key must be a string less than 255 characters.'));
|
||||
break;
|
||||
}
|
||||
elseif ($field_type == 'list' && (!preg_match('/^-?\d+$/', $key))) {
|
||||
form_error($element, t('The entered available values are not valid. All specified keys must be integers.'));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement hook_field_validate().
|
||||
*
|
||||
|
@ -161,29 +286,3 @@ function theme_field_formatter_list_default($element) {
|
|||
function theme_field_formatter_list_key($element) {
|
||||
return $element['#item']['safe'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an array of the allowed values for this field.
|
||||
*
|
||||
* Call the allowed_values_function to retrieve the allowed
|
||||
* values array.
|
||||
*
|
||||
* TODO Rework this to create a method of selecting plugable allowed values lists.
|
||||
*/
|
||||
function list_allowed_values($field) {
|
||||
static $allowed_values;
|
||||
|
||||
if (isset($allowed_values[$field['field_name']])) {
|
||||
return $allowed_values[$field['field_name']];
|
||||
}
|
||||
|
||||
$allowed_values[$field['field_name']] = array();
|
||||
|
||||
if (isset($field['settings']['allowed_values_function'])) {
|
||||
$function = $field['settings']['allowed_values_function'];
|
||||
if (drupal_function_exists($function)) {
|
||||
$allowed_values[$field['field_name']] = $function($field);
|
||||
}
|
||||
}
|
||||
return $allowed_values[$field['field_name']];
|
||||
}
|
||||
|
|
|
@ -87,6 +87,82 @@ function number_field_schema($field) {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement hook_field_settings_form().
|
||||
*/
|
||||
function number_field_settings_form($field, $instance) {
|
||||
$settings = $field['settings'];
|
||||
$form = array();
|
||||
|
||||
if ($field['type'] == 'number_decimal') {
|
||||
$form['precision'] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('Precision'),
|
||||
'#options' => drupal_map_assoc(range(10, 32)),
|
||||
'#default_value' => $settings['precision'],
|
||||
'#description' => t('The total number of digits to store in the database, including those to the right of the decimal.'),
|
||||
);
|
||||
$form['scale'] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('Scale'),
|
||||
'#options' => drupal_map_assoc(range(0, 10)),
|
||||
'#default_value' => $settings['scale'],
|
||||
'#description' => t('The number of digits to the right of the decimal.'),
|
||||
);
|
||||
$form['decimal'] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('Decimal marker'),
|
||||
'#options' => array(
|
||||
'.' => 'decimal point',
|
||||
',' => 'comma',
|
||||
' ' => 'space',
|
||||
),
|
||||
'#default_value' => $settings['decimal'],
|
||||
'#description' => t('The character users will input to mark the decimal point in forms.'),
|
||||
);
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement hook_field_instance_settings_form().
|
||||
*/
|
||||
function number_field_instance_settings_form($field, $instance) {
|
||||
$settings = $instance['settings'];
|
||||
|
||||
$form['min'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Minimum'),
|
||||
'#default_value' => $settings['min'],
|
||||
'#description' => t('The minimum value that should be allowed in this field. Leave blank for no minimum.'),
|
||||
'#element_validate' => array('_element_validate_number'),
|
||||
);
|
||||
$form['max'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Maximum'),
|
||||
'#default_value' => $settings['max'],
|
||||
'#description' => t('The maximum value that should be allowed in this field. Leave blank for no maximum.'),
|
||||
'#element_validate' => array('_element_validate_number'),
|
||||
);
|
||||
$form['prefix'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Prefix'),
|
||||
'#default_value' => $settings['prefix'],
|
||||
'#size' => 60,
|
||||
'#description' => t("Define a string that should be prefixed to the value, like '$ ' or '€ '. Leave blank for none. Separate singular and plural values with a pipe ('pound|pounds')."),
|
||||
);
|
||||
$form['suffix'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Suffix'),
|
||||
'#default_value' => $settings['suffix'],
|
||||
'#size' => 60,
|
||||
'#description' => t("Define a string that should suffixed to the value, like ' m', ' kb/s'. Leave blank for none. Separate singular and plural values with a pipe ('pound|pounds')."),
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement hook_field_validate().
|
||||
*
|
||||
|
|
|
@ -128,6 +128,51 @@ function text_field_schema($field) {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement hook_field_settings_form().
|
||||
*/
|
||||
function text_field_settings_form($field, $instance) {
|
||||
$settings = $field['settings'];
|
||||
|
||||
$form['max_length'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Maximum length'),
|
||||
'#default_value' => $settings['max_length'],
|
||||
'#required' => FALSE,
|
||||
'#description' => t('The maximum length of the field in characters. Leave blank for an unlimited size.'),
|
||||
'#element_validate' => array('_element_validate_integer_positive'),
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement hook_field_instance_settings_form().
|
||||
*/
|
||||
function text_field_instance_settings_form($field, $instance) {
|
||||
$settings = $instance['settings'];
|
||||
|
||||
$form['text_processing'] = array(
|
||||
'#type' => 'radios',
|
||||
'#title' => t('Text processing'),
|
||||
'#default_value' => $settings['text_processing'],
|
||||
'#options' => array(
|
||||
t('Plain text'),
|
||||
t('Filtered text (user selects input format)'),
|
||||
),
|
||||
);
|
||||
if ($field['type'] == 'text_with_summary') {
|
||||
$form['display_summary'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Summary input'),
|
||||
'#default_value' => $settings['display_summary'],
|
||||
'#description' => t('This allows authors to input an explicit summary, to be displayed instead of the automatically trimmed text when using the "Summary or trimmed" display format.'),
|
||||
);
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement hook_field_validate().
|
||||
*
|
||||
|
@ -466,6 +511,35 @@ function text_field_widget_info() {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement hook_field_widget_settings_form().
|
||||
*/
|
||||
function text_field_widget_settings_form($field, $instance) {
|
||||
$widget = $instance['widget'];
|
||||
$settings = $widget['settings'];
|
||||
|
||||
if ($widget['type'] == 'text_textfield') {
|
||||
$form['size'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Size of textfield'),
|
||||
'#default_value' => $settings['size'],
|
||||
'#required' => TRUE,
|
||||
'#element_validate' => array('_element_validate_integer_positive'),
|
||||
);
|
||||
}
|
||||
else {
|
||||
$form['rows'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Rows'),
|
||||
'#default_value' => $settings['rows'],
|
||||
'#required' => TRUE,
|
||||
'#element_validate' => array('_element_validate_integer_positive'),
|
||||
);
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement FAPI hook_elements().
|
||||
*
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
// $Id$
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Default theme implementation to configure field display settings.
|
||||
*
|
||||
* Available variables:
|
||||
*
|
||||
* - $form: The complete form for the field display settings.
|
||||
* - $contexts: An associative array of the available contexts for these fields.
|
||||
* On the node field display settings this defaults to including "teaser" and
|
||||
* "full" as the available contexts.
|
||||
* - $rows: The field display settings form broken down into rendered rows for
|
||||
* printing as a table.
|
||||
* - $submit: The rendered submit button for this form.
|
||||
*
|
||||
* @see field_ui_display_overview_form()
|
||||
* @see template_preprocess_field_ui_display_overview_form()
|
||||
*/
|
||||
?>
|
||||
<?php if ($rows): ?>
|
||||
<table id="field-display-overview" class="sticky-enabled">
|
||||
<thead>
|
||||
<tr>
|
||||
<th> </th>
|
||||
<?php foreach ($contexts as $key => $value): ?>
|
||||
<th colspan="2"><?php print $value; ?>
|
||||
<?php endforeach; ?>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php print t('Field'); ?></th>
|
||||
<?php foreach ($contexts as $key => $value): ?>
|
||||
<th><?php print t('Label'); ?></th>
|
||||
<th><?php print t('Format'); ?></th>
|
||||
<?php endforeach; ?>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
$count = 0;
|
||||
foreach ($rows as $row): ?>
|
||||
<tr class="<?php print $count % 2 == 0 ? 'odd' : 'even'; ?>">
|
||||
<td><span class="<?php print $row->label_class; ?>"><?php print $row->human_name; ?></span></td>
|
||||
<?php foreach ($contexts as $context => $title): ?>
|
||||
<td><?php print $row->{$context}->label; ?></td>
|
||||
<td><?php print $row->{$context}->type; ?></td>
|
||||
<?php endforeach; ?>
|
||||
</tr>
|
||||
<?php $count++;
|
||||
endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php print $submit; ?>
|
||||
<?php endif; ?>
|
|
@ -0,0 +1,94 @@
|
|||
<?php
|
||||
// $Id$
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Default theme implementation to configure field settings.
|
||||
*
|
||||
* Available variables:
|
||||
*
|
||||
* - $form: The complete overview form for the field settings.
|
||||
* - $contexts: An associative array of the available contexts for these fields.
|
||||
* On the node field display settings this defaults to including "teaser" and
|
||||
* "full" as the available contexts.
|
||||
* - $rows: The field overview form broken down into rendered rows for printing
|
||||
* as a table.
|
||||
* - $submit: The rendered submit button for this form.
|
||||
*
|
||||
* @see field_ui_field_overview_form()
|
||||
* @see template_preprocess_field_ui_field_overview_form()
|
||||
*/
|
||||
?>
|
||||
<table id="field-overview" class="sticky-enabled">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?php print t('Label'); ?></th>
|
||||
<th><?php print t('Weight'); ?></th>
|
||||
<th><?php print t('Name'); ?></th>
|
||||
<th><?php print t('Field'); ?></th>
|
||||
<th><?php print t('Widget'); ?></th>
|
||||
<th colspan="2"><?php print t('Operations'); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
$count = 0;
|
||||
foreach ($rows as $row): ?>
|
||||
<tr class="<?php print $count % 2 == 0 ? 'odd' : 'even'; ?> <?php print $row->class ?>">
|
||||
<?php
|
||||
switch ($row->row_type):
|
||||
case 'field': ?>
|
||||
<td>
|
||||
<span class="<?php print $row->label_class; ?>"><?php print $row->label; ?></span>
|
||||
</td>
|
||||
<td><?php print $row->weight . $row->hidden_name; ?></td>
|
||||
<td><?php print $row->field_name; ?></td>
|
||||
<td><?php print $row->type; ?></td>
|
||||
<td><?php print $row->widget_type; ?></td>
|
||||
<td><?php print $row->edit; ?></td>
|
||||
<td><?php print $row->delete; ?></td>
|
||||
<?php break;
|
||||
|
||||
case 'extra': ?>
|
||||
<td>
|
||||
<span class="<?php print $row->label_class; ?>"><?php print $row->label; ?></span>
|
||||
</td>
|
||||
<td><?php print $row->weight . $row->hidden_name; ?></td>
|
||||
<td><?php print $row->name; ?></td>
|
||||
<td colspan="2"><?php print $row->description; ?></td>
|
||||
<td><?php print $row->edit; ?></td>
|
||||
<td><?php print $row->delete; ?></td>
|
||||
<?php break;
|
||||
|
||||
case 'add_new_field': ?>
|
||||
<td>
|
||||
<div class="<?php print $row->label_class; ?>">
|
||||
<div class="new"><?php print t('Add new field'); ?></div>
|
||||
<?php print $row->label; ?>
|
||||
</div>
|
||||
</td>
|
||||
<td><div class="new"> </div><?php print $row->weight . $row->hidden_name; ?></td>
|
||||
<td colspan="2"><div class="new"> </div><?php print $row->field_name; ?></td>
|
||||
<td><div class="new"> </div><?php print $row->type; ?></td>
|
||||
<td colspan="2"><div class="new"> </div><?php print $row->widget_type; ?></td>
|
||||
<?php break;
|
||||
|
||||
case 'add_existing_field': ?>
|
||||
<td>
|
||||
<div class="<?php print $row->label_class; ?>">
|
||||
<div class="new"><?php print t('Add existing field'); ?></div>
|
||||
<?php print $row->label; ?>
|
||||
</div>
|
||||
</td>
|
||||
<td><div class="new"> </div><?php print $row->weight . $row->hidden_name; ?></td>
|
||||
<td colspan="3"><div class="new"> </div><?php print $row->field_name; ?></td>
|
||||
<td colspan="2"><div class="new"> </div><?php print $row->widget_type; ?></td>
|
||||
<?php break;
|
||||
endswitch; ?>
|
||||
</tr>
|
||||
<?php $count++;
|
||||
endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<?php print $submit; ?>
|
|
@ -0,0 +1,8 @@
|
|||
/* $Id$ */
|
||||
|
||||
/* 'Manage fields' overview */
|
||||
#field-overview .label-add-new-field,
|
||||
#field-overview .label-add-existing-field {
|
||||
float: right;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,135 @@
|
|||
<?php
|
||||
// $Id$
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Hooks provided by the Field UI module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup field_ui_field_type
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Field settings form.
|
||||
*
|
||||
* @param $field
|
||||
* The field structure being configured.
|
||||
* @param $instance
|
||||
* The instance structure being configured.
|
||||
* @return
|
||||
* The form definition for the field settings.
|
||||
*/
|
||||
function hook_field_settings_form($field, $instance) {
|
||||
$settings = $field['settings'];
|
||||
$form['max_length'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Maximum length'),
|
||||
'#default_value' => $settings['max_length'],
|
||||
'#required' => FALSE,
|
||||
'#element_validate' => array('_element_validate_integer_positive'),
|
||||
'#description' => t('The maximum length of the field in characters. Leave blank for an unlimited size.'),
|
||||
);
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instance settings form.
|
||||
*
|
||||
* @param $field
|
||||
* The field structure being configured.
|
||||
* @param $instance
|
||||
* The instance structure being configured.
|
||||
* @return
|
||||
* The form definition for the field instance settings.
|
||||
*/
|
||||
function hook_field_instance_settings_form($field, $instance) {
|
||||
$settings = $instance['settings'];
|
||||
|
||||
$form['text_processing'] = array(
|
||||
'#type' => 'radios',
|
||||
'#title' => t('Text processing'),
|
||||
'#default_value' => $settings['text_processing'],
|
||||
'#options' => array(
|
||||
t('Plain text'),
|
||||
t('Filtered text (user selects input format)'),
|
||||
),
|
||||
);
|
||||
if ($field['type'] == 'text_with_summary') {
|
||||
$form['display_summary'] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('Display summary'),
|
||||
'#options' => array(
|
||||
t('No'),
|
||||
t('Yes'),
|
||||
),
|
||||
'#description' => t('Display the summary to allow the user to input a summary value. Hide the summary to automatically fill it with a trimmed portion from the main post. '),
|
||||
'#default_value' => !empty($settings['display_summary']) ? $settings['display_summary'] : 0,
|
||||
);
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Widget settings form.
|
||||
*
|
||||
* @param $field
|
||||
* The field structure being configured.
|
||||
* @param $instance
|
||||
* The instance structure being configured.
|
||||
* @return
|
||||
* The form definition for the widget settings.
|
||||
*/
|
||||
function hook_field_widget_settings_form($field, $instance) {
|
||||
$widget = $instance['widget'];
|
||||
$settings = $widget['settings'];
|
||||
$form = array();
|
||||
|
||||
if ($widget['type'] == 'text_textfield') {
|
||||
$form['size'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Size of textfield'),
|
||||
'#default_value' => $settings['size'],
|
||||
'#element_validate' => array('_element_validate_integer_positive'),
|
||||
'#required' => TRUE,
|
||||
);
|
||||
}
|
||||
else {
|
||||
$form['rows'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Rows'),
|
||||
'#default_value' => $settings['rows'],
|
||||
'#element_validate' => array('_element_validate_integer_positive'),
|
||||
'#required' => TRUE,
|
||||
);
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formatter settings form.
|
||||
*
|
||||
* @todo Not implemented yet. The signature below is only prospective, but
|
||||
* providing $instance is not enough, since one $instance holds several display
|
||||
* settings.
|
||||
*
|
||||
* @param $formatter
|
||||
* The type of the formatter being configured.
|
||||
* @param $settings
|
||||
* The current values of the formatter settings.
|
||||
* @param $field
|
||||
* The field structure being configured.
|
||||
* @param $instance
|
||||
* The instance structure being configured.
|
||||
* @return
|
||||
* The form definition for the formatter settings.
|
||||
*/
|
||||
function hook_field_formatter_settings_form($formatter, $settings, $field, $instance) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @} End of "ingroup field_ui_field_type"
|
||||
*/
|
|
@ -0,0 +1,18 @@
|
|||
/* $Id$ */
|
||||
|
||||
/* 'Manage fields' overview */
|
||||
#field-overview .label-add-new-field,
|
||||
#field-overview .label-add-existing-field {
|
||||
float: left; /* LTR */
|
||||
}
|
||||
#field-overview tr.add-new .tabledrag-changed {
|
||||
display: none;
|
||||
}
|
||||
#field-overview tr.add-new .description {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
#field-overview .new {
|
||||
font-weight: bold;
|
||||
padding-bottom: .5em;
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
; $Id$
|
||||
name = Field UI
|
||||
description = User Interface for the Field API.
|
||||
package = Core
|
||||
version = VERSION
|
||||
core = 7.x
|
||||
files[] = field_ui.module
|
||||
files[] = field_ui.admin.inc
|
|
@ -0,0 +1,84 @@
|
|||
// $Id$
|
||||
|
||||
(function($) {
|
||||
|
||||
Drupal.behaviors.fieldManageFields = {
|
||||
attach: function (context) {
|
||||
attachUpdateSelects(context);
|
||||
}
|
||||
};
|
||||
|
||||
function attachUpdateSelects(context) {
|
||||
var widgetTypes = Drupal.settings.fieldWidgetTypes;
|
||||
var fields = Drupal.settings.fields;
|
||||
|
||||
// Store the default text of widget selects.
|
||||
$('#field-overview .widget-type-select', context).each(function () {
|
||||
this.initialValue = this.options[0].text;
|
||||
});
|
||||
|
||||
// 'Field type' select updates its 'Widget' select.
|
||||
$('#field-overview .field-type-select', context).each(function () {
|
||||
this.targetSelect = $('.widget-type-select', $(this).parents('tr').eq(0));
|
||||
|
||||
$(this).bind('mouseup keyup', function () {
|
||||
var selectedFieldType = this.options[this.selectedIndex].value;
|
||||
var options = (selectedFieldType in widgetTypes ? widgetTypes[selectedFieldType] : []);
|
||||
this.targetSelect.fieldPopulateOptions(options);
|
||||
});
|
||||
|
||||
// Trigger change on initial pageload to get the right widget options
|
||||
// when field type comes pre-selected (on failed validation).
|
||||
$(this).trigger('mouseup');
|
||||
});
|
||||
|
||||
// 'Existing field' select updates its 'Widget' select and 'Label' textfield.
|
||||
$('#field-overview .field-select', context).each(function () {
|
||||
this.targetSelect = $('.widget-type-select', $(this).parents('tr').eq(0));
|
||||
this.targetTextfield = $('.label-textfield', $(this).parents('tr').eq(0));
|
||||
|
||||
$(this).change(function (e, updateText) {
|
||||
var updateText = (typeof updateText == 'undefined' ? true : updateText);
|
||||
var selectedField = this.options[this.selectedIndex].value;
|
||||
var selectedFieldType = (selectedField in fields ? fields[selectedField].type : null);
|
||||
var selectedFieldWidget = (selectedField in fields ? fields[selectedField].widget : null);
|
||||
var options = (selectedFieldType && (selectedFieldType in widgetTypes) ? widgetTypes[selectedFieldType] : []);
|
||||
this.targetSelect.fieldPopulateOptions(options, selectedFieldWidget);
|
||||
|
||||
if (updateText) {
|
||||
$(this.targetTextfield).attr('value', (selectedField in fields ? fields[selectedField].label : ''));
|
||||
}
|
||||
});
|
||||
|
||||
// Trigger change on initial pageload to get the right widget options
|
||||
// and label when field type comes pre-selected (on failed validation).
|
||||
$(this).trigger('change', false);
|
||||
});
|
||||
}
|
||||
|
||||
jQuery.fn.fieldPopulateOptions = function (options, selected) {
|
||||
return this.each(function () {
|
||||
var disabled = false;
|
||||
if (options.length == 0) {
|
||||
options = [this.initialValue];
|
||||
disabled = true;
|
||||
}
|
||||
|
||||
// If possible, keep the same widget selected when changing field type.
|
||||
// This is based on textual value, since the internal value might be
|
||||
// different (options_buttons vs. node_reference_buttons).
|
||||
var previousSelectedText = this.options[this.selectedIndex].text;
|
||||
|
||||
var html = '';
|
||||
jQuery.each(options, function (value, text) {
|
||||
// Figure out which value should be selected. The 'selected' param
|
||||
// takes precedence.
|
||||
var is_selected = ((typeof selected != 'undefined' && value == selected) || (typeof selected == 'undefined' && text == previousSelectedText));
|
||||
html += '<option value="' + value + '"' + (is_selected ? ' selected="selected"' : '') + '>' + text + '</option>';
|
||||
});
|
||||
|
||||
$(this).html(html).attr('disabled', disabled ? 'disabled' : '');
|
||||
});
|
||||
};
|
||||
|
||||
})(jQuery);
|
|
@ -0,0 +1,327 @@
|
|||
<?php
|
||||
// $Id$
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Allows administrators to associate custom fields to fieldable types.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implement hook_help().
|
||||
*/
|
||||
function field_ui_help($path, $arg) {
|
||||
switch ($path) {
|
||||
case 'admin/help#field_ui':
|
||||
$output = '';
|
||||
$output .= '<p>' . t('The Field UI module provides an administrative interface for adding custom fields to content types, users, comments, and other types of data. In the case of content types, a few fields are provided by default, such as the "Summary and Body" field. The Field UI module lets administrators edit or delete the default fields attached to content, as well as create new fields for storing any additional information. Field configuration is accessible through tabs on the <a href="@content-types">content types administration page</a>. (See the <a href="@node-help">node module help page</a> for more information about content types.)', array('@content-types' => url('admin/content/types'), '@node-help' => url('admin/help/node'))) . '</p>';
|
||||
$output .= '<p>' . t('When adding a custom field to a content type, you determine its type (whether it will contain text, numbers, lists, etc.) and how it will be displayed (either as a text field or text area, a select box, checkboxes, radio buttons, or an auto-complete text field). A field may have multiple values (i.e., a "person" may have multiple e-mail addresses) or a single value (i.e., an "employee" has a single employee identification number).') . '</p>';
|
||||
$output .= '<p>' . t('Custom field types may be provided by additional modules. Drupal core includes the following field types:') . '</p>';
|
||||
$output .= '<ul>';
|
||||
$output .= '<li>' . t('<em>Number</em>: Adds numeric field types, in integer, decimal or floating point form. You may define a set of allowed inputs, or specify an allowable range of values. A variety of common formats for displaying numeric data are available.') . '</li>';
|
||||
$output .= '<li>' . t("<em>Text</em>: Adds text field types. A text field may contain plain text only, or optionally, may use Drupal's input format filters to securely manage HTML output. Text input fields may be either a single line (text field), multiple lines (text area), or for greater input control, a select box, checkbox, or radio buttons. If desired, CCK can validate the input to a set of allowed values.") . '</li>';
|
||||
$output .= '<li>' . t('<em>List</em>: Provides storage mechanisms to store a list of items. Usually these items are input through a select list, checkboxes, or radio buttons.') . '</li>';
|
||||
$output .= '</ul>';
|
||||
return $output;
|
||||
|
||||
case 'admin/reports/fields':
|
||||
return '<p>' . t('This list shows all fields currently in use for easy reference.') . '</p>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement hook_menu().
|
||||
*/
|
||||
function field_ui_menu() {
|
||||
$items['admin/reports/fields'] = array(
|
||||
'title' => 'Field list',
|
||||
'description' => 'Overview of fields on all object types.',
|
||||
'page callback' => 'field_ui_fields_list',
|
||||
'access arguments' => array('administer content types'),
|
||||
'type' => MENU_NORMAL_ITEM,
|
||||
);
|
||||
|
||||
// Ensure the following is not executed until field_bundles is working and
|
||||
// tables are updated. Needed to avoid errors on initial installation.
|
||||
if (defined('MAINTENANCE_MODE')) {
|
||||
return $items;
|
||||
}
|
||||
// Create tabs for all possible bundles.
|
||||
foreach (field_info_fieldable_types() as $obj_type => $info) {
|
||||
foreach ($info['bundles'] as $bundle_name => $bundle_info) {
|
||||
if (isset($bundle_info['admin'])) {
|
||||
// Extract informations from the bundle description.
|
||||
$path = $bundle_info['admin']['path'];
|
||||
$bundle_arg = isset($bundle_info['admin']['bundle argument']) ? $bundle_info['admin']['bundle argument'] : $bundle_name;
|
||||
$access = array_intersect_key($bundle_info['admin'], drupal_map_assoc(array('access callback', 'access arguments')));
|
||||
|
||||
$items["$path/fields"] = array(
|
||||
'title' => 'Manage fields',
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('field_ui_field_overview_form', $obj_type, $bundle_arg),
|
||||
'type' => MENU_LOCAL_TASK,
|
||||
'weight' => 1,
|
||||
) + $access;
|
||||
// A dummy function to trigger a page refresh so that field menus get
|
||||
// rebuilt correctly when new fields are added.
|
||||
$items["$path/fields/refresh"] = array(
|
||||
'title' => 'Refresh menu',
|
||||
'page callback' => 'field_ui_field_menu_refresh',
|
||||
'page arguments' => array($obj_type, $bundle_arg),
|
||||
'type' => MENU_CALLBACK,
|
||||
'weight' => 1,
|
||||
) + $access;
|
||||
$items["$path/display"] = array(
|
||||
'title' => 'Display fields',
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('field_ui_display_overview_form', $obj_type, $bundle_arg),
|
||||
'type' => MENU_LOCAL_TASK,
|
||||
'weight' => 2,
|
||||
) + $access;
|
||||
|
||||
// 'Display fields' tab and context secondary tabs.
|
||||
$tabs = field_ui_build_modes_tabs($obj_type);
|
||||
foreach ($tabs as $key => $tab) {
|
||||
$items["$path/display/$key"] = array(
|
||||
'title' => $tab['title'],
|
||||
'page arguments' => array('field_ui_display_overview_form', $obj_type, $bundle_arg, $key),
|
||||
'type' => $key == 'basic' ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK,
|
||||
'weight' => $key == 'basic' ? 0 : 1,
|
||||
) + $access;
|
||||
}
|
||||
|
||||
$instance_position = count(explode('/', $path)) + 1;
|
||||
$items["$path/fields/%field_ui_menu"] = array(
|
||||
'title callback' => 'field_ui_menu_label',
|
||||
'title arguments' => array($instance_position),
|
||||
'load arguments' => array($bundle_name),
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('field_ui_field_edit_form', $obj_type, $bundle_arg, $instance_position),
|
||||
'type' => MENU_LOCAL_TASK,
|
||||
) + $access;
|
||||
$items["$path/fields/%field_ui_menu/edit"] = array(
|
||||
'title' => 'Edit instance settings',
|
||||
'load arguments' => array($bundle_name),
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('field_ui_field_edit_form', $obj_type, $bundle_arg, $instance_position),
|
||||
'type' => MENU_DEFAULT_LOCAL_TASK,
|
||||
) + $access;
|
||||
$items["$path/fields/%field_ui_menu/field-settings"] = array(
|
||||
'title' => 'Edit field settings',
|
||||
'load arguments' => array($bundle_name),
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('field_ui_field_settings_form', $obj_type, $bundle_arg, $instance_position),
|
||||
'type' => MENU_LOCAL_TASK,
|
||||
) + $access;
|
||||
$items["$path/fields/%field_ui_menu/widget-type"] = array(
|
||||
'title' => 'Change widget type',
|
||||
'load arguments' => array($bundle_name),
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('field_ui_widget_type_form', $obj_type, $bundle_arg, $instance_position),
|
||||
'type' => MENU_LOCAL_TASK,
|
||||
) + $access;
|
||||
$items["$path/fields/%field_ui_menu/delete"] = array(
|
||||
'title' => 'Delete instance',
|
||||
'load arguments' => array($bundle_name),
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('field_ui_field_delete_form', $obj_type, $bundle_arg, $instance_position),
|
||||
'type' => MENU_LOCAL_TASK,
|
||||
) + $access;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu loader; Load a field instance based on its name.
|
||||
*/
|
||||
function field_ui_menu_load($field_name, $bundle_name) {
|
||||
if ($instance = field_info_instance($field_name, $bundle_name)) {
|
||||
return $instance;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu title callback; Return a field label based on its instance.
|
||||
*/
|
||||
function field_ui_menu_label($instance) {
|
||||
return t($instance['label']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement hook_theme().
|
||||
*/
|
||||
function field_ui_theme() {
|
||||
return array(
|
||||
'field_ui_field_overview_form' => array(
|
||||
'arguments' => array('form' => NULL),
|
||||
'file' => 'field_ui.admin.inc',
|
||||
'template' => 'field_ui-field-overview-form',
|
||||
),
|
||||
'field_ui_display_overview_form' => array(
|
||||
'arguments' => array('form' => NULL),
|
||||
'file' => 'field_ui.admin.inc',
|
||||
'template' => 'field_ui-display-overview-form',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Group available build modes on tabs on the 'Display fields' page.
|
||||
*
|
||||
* @todo Remove this completely and use vertical tabs?
|
||||
*/
|
||||
function field_ui_build_modes_tabs($obj_type, $tab_selector = NULL) {
|
||||
$info = &drupal_static(__FUNCTION__);
|
||||
|
||||
if (!isset($info[$obj_type])) {
|
||||
$info[$obj_type] = module_invoke_all('field_ui_build_modes_tabs');
|
||||
// Collect titles, and filter out non active modes.
|
||||
$active_modes = field_build_modes($obj_type);
|
||||
foreach ($info[$obj_type] as $tab => $values) {
|
||||
$modes = array();
|
||||
foreach ($info[$obj_type][$tab]['build modes'] as $mode) {
|
||||
if (isset($active_modes[$mode])) {
|
||||
$modes[$mode] = $active_modes[$mode];
|
||||
}
|
||||
}
|
||||
if ($modes) {
|
||||
$info[$obj_type][$tab]['build modes'] = $modes;
|
||||
}
|
||||
else {
|
||||
unset($info[$obj_type][$tab]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($tab_selector) {
|
||||
return isset($info[$obj_type][$tab_selector]) ? $info[$obj_type][$tab_selector]['build modes'] : array();
|
||||
}
|
||||
return $info[$obj_type];
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement hook_field_ui_build_modes_tabs() on behalf of other core modules.
|
||||
*
|
||||
* @return
|
||||
* An array describing the build modes defined by the module, grouped by tabs.
|
||||
*
|
||||
* A module can add its render modes to a tab defined by another module.
|
||||
* Expected format:
|
||||
* @code
|
||||
* array(
|
||||
* 'tab1' => array(
|
||||
* 'title' => t('The human-readable title of the tab'),
|
||||
* 'build modes' => array('mymodule_mode1', 'mymodule_mode2'),
|
||||
* ),
|
||||
* 'tab2' => array(
|
||||
* // ...
|
||||
* ),
|
||||
* );
|
||||
* @endcode
|
||||
*/
|
||||
function field_ui_field_ui_build_modes_tabs() {
|
||||
$modes = array(
|
||||
'basic' => array(
|
||||
'title' => t('Basic'),
|
||||
'build modes' => array('teaser', 'full'),
|
||||
),
|
||||
'rss' => array(
|
||||
'title' => t('RSS'),
|
||||
'build modes' => array('rss'),
|
||||
),
|
||||
'print' => array(
|
||||
'title' => t('Print'),
|
||||
'build modes' => array('print'),
|
||||
),
|
||||
'search' => array(
|
||||
'title' => t('Search'),
|
||||
'build modes' => array('search_index', 'search_result'),
|
||||
),
|
||||
);
|
||||
return $modes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a field.
|
||||
*
|
||||
* Field API does not allow field updates, so we create a method here to
|
||||
* update a field if no data is created yet.
|
||||
*
|
||||
* @see field_create_field()
|
||||
*/
|
||||
function field_ui_update_field($field) {
|
||||
$field_types = field_info_field_types();
|
||||
$module = $field_types[$field['type']]['module'];
|
||||
|
||||
$defaults = field_info_field_settings($field['type']);
|
||||
$field['settings'] = array_merge($defaults, (array) $field['settings']);
|
||||
$data = $field;
|
||||
unset($data['id'], $data['columns'], $data['field_name'], $data['type'], $data['locked'], $data['module'], $data['cardinality'], $data['active'], $data['deleted']);
|
||||
$field['data'] = $data;
|
||||
|
||||
drupal_write_record('field_config', $field, array('field_name'));
|
||||
|
||||
// Clear caches.
|
||||
field_cache_clear(TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement hook_field_attach_create_bundle().
|
||||
*/
|
||||
function field_ui_field_attach_create_bundle($bundle) {
|
||||
// When a new bundle is created, the menu needs to be rebuilt to add our
|
||||
// menu item tabs.
|
||||
menu_rebuild();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement hook_field_attach_rename_bundle().
|
||||
*/
|
||||
function field_ui_field_attach_rename_bundle($bundle_old, $bundle_new) {
|
||||
if ($bundle_old !== $bundle_new && $extra = variable_get("field_extra_weights_$bundle_old", array())) {
|
||||
variable_set("field_extra_weights_$bundle_new", $extra);
|
||||
variable_del("field_extra_weights_$bundle_old");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement hook_field_attach_delete_bundle().
|
||||
*/
|
||||
function field_ui_field_attach_delete_bundle($bundle) {
|
||||
variable_del('field_extra_weights_' . $bundle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to create the right administration path for a bundle.
|
||||
*/
|
||||
function _field_ui_bundle_admin_path($bundle_name) {
|
||||
$bundles = field_info_bundles();
|
||||
$bundle_info = $bundles[$bundle_name];
|
||||
return isset($bundle_info['admin']['real path']) ? $bundle_info['admin']['real path'] : $bundle_info['admin']['path'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to identify inactive fields within a bundle.
|
||||
*/
|
||||
function field_ui_inactive_instances($bundle_name = NULL) {
|
||||
if (!empty($bundle_name)) {
|
||||
$inactive = array($bundle_name => array());
|
||||
$params = array('bundle' => $bundle_name);
|
||||
}
|
||||
else {
|
||||
$inactive = array();
|
||||
$params = array();
|
||||
}
|
||||
$active_instances = field_info_instances();
|
||||
$all_instances = field_read_instances($params, array('include_inactive' => TRUE));
|
||||
foreach ($all_instances as $instance) {
|
||||
if (!isset($active_instances[$instance['bundle']][$instance['field_name']])) {
|
||||
$inactive[$instance['bundle']][$instance['field_name']] = $instance;
|
||||
}
|
||||
}
|
||||
if (!empty($bundle_name)) {
|
||||
return $inactive[$bundle_name];
|
||||
}
|
||||
return $inactive;
|
||||
}
|
|
@ -40,12 +40,25 @@ function node_help($path, $arg) {
|
|||
$output .= '<p>' . t('The administrative <a href="@content">content page</a> allows you to review and manage your site content. The node module makes a number of permissions available for each content type, which may be set by role on the <a href="@permissions">permissions page</a>.', array('@content' => url('admin/content'), '@permissions' => url('admin/settings/permissions'))) . '</p>';
|
||||
$output .= '<p>' . t('For more information, see the online handbook entry for <a href="@node">Node module</a>.', array('@node' => 'http://drupal.org/handbook/modules/node/')) . '</p>';
|
||||
return $output;
|
||||
|
||||
case 'admin/content':
|
||||
return ' '; // Return a non-null value so that the 'more help' link is shown.
|
||||
|
||||
case 'admin/structure/types/add':
|
||||
return '<p>' . t('Each piece of content is of a specific content type. Each <em>content type</em> can have different fields, behaviors, and permissions assigned to it.') . '</p>';
|
||||
|
||||
case 'admin/structure/node-type/' . $arg[3] . '/fields':
|
||||
return '<p>' . t('This form lets you add, edit, and arrange fields within the %type content type.', array('%type' => node_type_get_name($arg[3]))) . '</p>';
|
||||
|
||||
case 'admin/structure/node-type/' . $arg[3] . '/display':
|
||||
return '<p>' . t('This form lets you configure how fields and labels are displayed when %type content is viewed in teaser and full-page mode.', array('%type' => node_type_get_name($arg[3]))) . '</p>';
|
||||
|
||||
case 'admin/structure/node-type/' . $arg[3] . '/display/' . $arg[5]:
|
||||
return '<p>' . t('This form lets you configure how fields should be displayed when rendered %type content in the following contexts.', array('%type' => node_type_get_name($arg[3]))) . '</p>';
|
||||
|
||||
case 'node/%/revisions':
|
||||
return '<p>' . t('The revisions let you track differences between multiple versions of a post.') . '</p>';
|
||||
|
||||
case 'node/%/edit':
|
||||
$node = node_load($arg[1]);
|
||||
$type = node_type_get_type($node);
|
||||
|
@ -173,6 +186,25 @@ function node_field_build_modes($obj_type) {
|
|||
return $modes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement hook_field_extra_fields().
|
||||
*/
|
||||
function node_field_extra_fields($bundle) {
|
||||
$extra = array();
|
||||
|
||||
if ($type = node_type_get_type($bundle)) {
|
||||
if ($type->has_title) {
|
||||
$extra['title'] = array(
|
||||
'label' => $type->title_label,
|
||||
'description' => t('Node module element.'),
|
||||
'weight' => -5,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $extra;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gather a listing of links to nodes.
|
||||
*
|
||||
|
|
|
@ -159,6 +159,7 @@ function node_form(&$form_state, $node) {
|
|||
|
||||
$form['additional_settings'] = array(
|
||||
'#type' => 'vertical_tabs',
|
||||
'#weight' => 99,
|
||||
);
|
||||
|
||||
// Add a log field if the "Create new revision" option is checked, or if the
|
||||
|
|
|
@ -198,6 +198,28 @@ function poll_node_info() {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement hook_field_extra_fields().
|
||||
*/
|
||||
function poll_field_extra_fields($bundle) {
|
||||
$extra = array();
|
||||
|
||||
if ($bundle == 'poll') {
|
||||
$extra['choice_wrapper'] = array(
|
||||
'label' => t('Poll choices'),
|
||||
'description' => t('Poll module choices.'),
|
||||
'weight' => -4,
|
||||
);
|
||||
$extra['settings'] = array(
|
||||
'label' => t('Poll settings'),
|
||||
'description' => t('Poll module settings.'),
|
||||
'weight' => -3,
|
||||
);
|
||||
}
|
||||
|
||||
return $extra;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement hook_form().
|
||||
*/
|
||||
|
|
|
@ -64,6 +64,25 @@ function taxonomy_field_build_modes($obj_type) {
|
|||
return $modes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement hook_field_extra_fields().
|
||||
*/
|
||||
function taxonomy_field_extra_fields($bundle) {
|
||||
$extra = array();
|
||||
|
||||
if ($type = node_type_get_type($bundle)) {
|
||||
if (taxonomy_get_vocabularies($bundle)) {
|
||||
$extra['taxonomy'] = array(
|
||||
'label' => t('Taxonomy'),
|
||||
'description' => t('Taxonomy module element.'),
|
||||
'weight' => -3,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $extra;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement hook_theme().
|
||||
*/
|
||||
|
@ -2247,3 +2266,35 @@ function taxonomy_elements() {
|
|||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement hook_field_settings_form().
|
||||
*/
|
||||
function taxonomy_field_settings_form($field, $instance) {
|
||||
// Get proper values for 'allowed_values_function', which is a core setting.
|
||||
$vocabularies = taxonomy_get_vocabularies();
|
||||
$options = array();
|
||||
foreach ($vocabularies as $vocabulary) {
|
||||
$options[$vocabulary->vid] = $vocabulary->name;
|
||||
}
|
||||
$form['allowed_values'] = array(
|
||||
'#tree' => TRUE,
|
||||
);
|
||||
|
||||
foreach ($field['settings']['allowed_values'] as $delta => $tree) {
|
||||
$form['allowed_values'][$delta]['vid'] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('Vocabulary'),
|
||||
'#default_value' => $tree['vid'],
|
||||
'#options' => $options,
|
||||
'#required' => TRUE,
|
||||
'#description' => t('The vocabulary which supplies the options for this field.'),
|
||||
);
|
||||
$form['allowed_values'][$delta]['parent'] = array(
|
||||
'#type' => 'value',
|
||||
'#value' => $tree['parent'],
|
||||
);
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
|
|
@ -120,6 +120,33 @@ function user_field_build_modes($obj_type) {
|
|||
return $modes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement hook_field_extra_fields().
|
||||
*/
|
||||
function user_field_extra_fields($bundle) {
|
||||
$extra = array();
|
||||
|
||||
if ($bundle == 'user') {
|
||||
$extra['account'] = array(
|
||||
'label' => 'User name and password',
|
||||
'description' => t('User module account form elements'),
|
||||
'weight' => -10,
|
||||
);
|
||||
$extra['timezone'] = array(
|
||||
'label' => 'Timezone',
|
||||
'description' => t('User module timezone form element.'),
|
||||
'weight' => 6,
|
||||
);
|
||||
$extra['summary'] = array(
|
||||
'label' => 'History',
|
||||
'description' => t('User module history view element.'),
|
||||
'weight' => 5,
|
||||
);
|
||||
}
|
||||
|
||||
return $extra;
|
||||
}
|
||||
|
||||
function user_external_load($authname) {
|
||||
$uid = db_query("SELECT uid FROM {authmap} WHERE authname = :authname", array(':authname' => $authname))->fetchField();
|
||||
|
||||
|
@ -1344,6 +1371,11 @@ function user_menu() {
|
|||
'page arguments' => array('user_admin_settings'),
|
||||
'access arguments' => array('administer users'),
|
||||
);
|
||||
$items['admin/settings/user/settings'] = array(
|
||||
'title' => 'Settings',
|
||||
'type' => MENU_DEFAULT_LOCAL_TASK,
|
||||
'weight' => -10,
|
||||
);
|
||||
|
||||
// Permission administration pages.
|
||||
$items['admin/settings/permissions'] = array(
|
||||
|
@ -2430,6 +2462,10 @@ function user_help($path, $arg) {
|
|||
<li>Anonymous user: this role is used for users that don\'t have a user account or that are not authenticated.</li>
|
||||
<li>Authenticated user: this role is automatically granted to all logged in users.</li>
|
||||
</ul>', array('@permissions' => url('admin/settings/permissions')));
|
||||
case 'admin/settings/user/fields':
|
||||
return '<p>' . t('This form lets administrators add, edit, and arrange fields for storing user data.') . '</p>';
|
||||
case 'admin/settings/user/display':
|
||||
return '<p>' . t('This form lets administrators configure how fields should be displayed when rendering a user profile page.') . '</p>';
|
||||
case 'admin/people/search':
|
||||
return '<p>' . t('Enter a simple pattern ("*" may be used as a wildcard match) to search for a username or e-mail address. For example, one may search for "br" and Drupal might return "brian", "brad", and "brenda@example.com".') . '</p>';
|
||||
}
|
||||
|
|
|
@ -14,3 +14,4 @@ dependencies[] = taxonomy
|
|||
dependencies[] = dblog
|
||||
dependencies[] = search
|
||||
dependencies[] = toolbar
|
||||
dependencies[] = field_ui
|
||||
|
|
Loading…
Reference in New Issue