Commit 03e2ec64 authored by Dries's avatar Dries

- Patch #606994 by yched: move entity handling out of Field API.

parent 150f6a68
......@@ -5964,7 +5964,20 @@ function entity_get_info($entity_type = NULL) {
'controller class' => 'DrupalDefaultEntityController',
'static cache' => TRUE,
'load hook' => $name . '_load',
'bundles' => array(),
'object keys' => array(),
'cacheable' => TRUE,
'translation' => array(),
);
$entity_info[$name]['object keys'] += array(
'revision' => '',
'bundle' => '',
);
// If no bundle key is provided, assume a single bundle, named after
// the entity type.
if (empty($entity_info[$name]['object keys']['bundle']) && empty($entity_info[$name]['bundles'])) {
$entity_info[$name]['bundles'] = array($name => array('label' => $entity_info[$name]['label']));
}
}
// Let other modules alter the entity info.
drupal_alter('entity_info', $entity_info);
......@@ -5975,6 +5988,63 @@ function entity_get_info($entity_type = NULL) {
return empty($entity_type) ? $entity_info : $entity_info[$entity_type];
}
/**
* Helper function to extract id, vid, and bundle name from an entity.
*
* @param $entity_type
* The entity type; e.g. 'node' or 'user'.
* @param $entity
* The entity from which to extract values.
* @return
* A numerically indexed array (not a hash table) containing these
* elements:
*
* 0: primary id of the entity
* 1: revision id of the entity, or NULL if $entity_type is not versioned
* 2: bundle name of the entity
* 3: whether $entity_type's fields should be cached (TRUE/FALSE)
*/
function entity_extract_ids($entity_type, $entity) {
$info = entity_get_info($entity_type);
// Objects being created might not have id/vid yet.
$id = isset($entity->{$info['object keys']['id']}) ? $entity->{$info['object keys']['id']} : NULL;
$vid = ($info['object keys']['revision'] && isset($entity->{$info['object keys']['revision']})) ? $entity->{$info['object keys']['revision']} : NULL;
// If no bundle key provided, then we assume a single bundle, named after the
// entity type.
$bundle = $info['object keys']['bundle'] ? $entity->{$info['object keys']['bundle']} : $entity_type;
$cacheable = $info['cacheable'];
return array($id, $vid, $bundle, $cacheable);
}
/**
* Helper function to assemble an object structure with initial ids.
*
* This function can be seen as reciprocal to entity_extract_ids().
*
* @param $entity_type
* The entity type; e.g. 'node' or 'user'.
* @param $ids
* A numerically indexed array, as returned by entity_extract_ids(),
* containing these elements:
* 0: primary id of the entity
* 1: revision id of the entity, or NULL if $entity_type is not versioned
* 2: bundle name of the entity
* @return
* An entity structure, initialized with the ids provided.
*/
function entity_create_stub_entity($entity_type, $ids) {
$entity = new stdClass();
$info = entity_get_info($entity_type);
$entity->{$info['object keys']['id']} = $ids[0];
if (isset($info['object keys']['revision']) && !is_null($ids[1])) {
$entity->{$info['object keys']['revision']} = $ids[1];
}
if ($info['object keys']['bundle']) {
$entity->{$info['object keys']['bundle']} = $ids[2];
}
return $entity;
}
/**
* Load entities from the database.
*
......
......@@ -68,7 +68,7 @@ public function __construct($entityType) {
$this->idKey = $this->entityInfo['object keys']['id'];
// Check if the entity type supports revisions.
if (isset($this->entityInfo['object keys']['revision'])) {
if (!empty($this->entityInfo['object keys']['revision'])) {
$this->revisionKey = $this->entityInfo['object keys']['revision'];
$this->revisionTable = $this->entityInfo['revision table'];
}
......
......@@ -181,7 +181,7 @@ function _field_invoke($op, $obj_type, $object, &$a = NULL, &$b = NULL, $options
// Iterate through the object's field instances.
$return = array();
list(, , $bundle) = field_extract_ids($obj_type, $object);
list(, , $bundle) = entity_extract_ids($obj_type, $object);
if ($options['deleted']) {
$instances = field_read_instances(array('object_type' => $obj_type, 'bundle' => $bundle), array('include_deleted' => $options['deleted']));
......@@ -298,7 +298,7 @@ function _field_invoke_multiple($op, $obj_type, $objects, &$a = NULL, &$b = NULL
// is deleted, so we reference field data via the
// $object->$field_name property.
foreach ($objects as $object) {
list($id, $vid, $bundle) = field_extract_ids($obj_type, $object);
list($id, $vid, $bundle) = entity_extract_ids($obj_type, $object);
if ($options['deleted']) {
$instances = field_read_field(array('bundle' => $bundle, array('include_deleted' => $options['deleted'])));
......@@ -488,7 +488,7 @@ function field_attach_form($obj_type, $object, &$form, &$form_state, $langcode =
$form += (array) _field_invoke_default('form', $obj_type, $object, $form, $form_state, $options);
// Add custom weight handling.
list($id, $vid, $bundle) = field_extract_ids($obj_type, $object);
list($id, $vid, $bundle) = entity_extract_ids($obj_type, $object);
$form['#attached']['css'][] = drupal_get_path('module', 'field') . '/theme/field.css';
$form['#pre_render'][] = '_field_extra_weights_pre_render';
$form['#extra_fields'] = field_extra_fields($bundle);
......@@ -536,7 +536,7 @@ function field_attach_load($obj_type, $objects, $age = FIELD_LOAD_CURRENT, $opti
);
$options += $default_options;
$info = field_info_fieldable_types($obj_type);
$info = entity_get_info($obj_type);
// Only the most current revision of non-deleted fields for
// cacheable fieldable types can be cached.
$cache_read = $load_current && $info['cacheable'] && empty($options['deleted']);
......@@ -591,7 +591,7 @@ function field_attach_load($obj_type, $objects, $age = FIELD_LOAD_CURRENT, $opti
// Collect the storage backends used by the remaining fields in the objects.
$storages = array();
foreach ($queried_objects as $obj) {
list($id, $vid, $bundle) = field_extract_ids($obj_type, $obj);
list($id, $vid, $bundle) = entity_extract_ids($obj_type, $obj);
if ($options['deleted']) {
$instances = field_read_instances(array('object_type' => $obj_type, 'bundle' => $bundle), array('include_deleted' => $options['deleted']));
}
......@@ -636,7 +636,7 @@ function field_attach_load($obj_type, $objects, $age = FIELD_LOAD_CURRENT, $opti
if ($cache_write) {
foreach ($queried_objects as $id => $object) {
$data = array();
list($id, $vid, $bundle) = field_extract_ids($obj_type, $object);
list($id, $vid, $bundle) = entity_extract_ids($obj_type, $object);
$instances = field_info_instances($obj_type, $bundle);
foreach ($instances as $instance) {
$data[$instance['field_name']] = $queried_objects[$id]->{$instance['field_name']};
......@@ -819,7 +819,7 @@ function field_attach_insert($obj_type, $object) {
_field_invoke_default('insert', $obj_type, $object);
_field_invoke('insert', $obj_type, $object);
list($id, $vid, $bundle, $cacheable) = field_extract_ids($obj_type, $object);
list($id, $vid, $bundle, $cacheable) = entity_extract_ids($obj_type, $object);
// Let other modules act on inserting the object, accumulating saved
// fields along the way.
......@@ -865,7 +865,7 @@ function field_attach_insert($obj_type, $object) {
function field_attach_update($obj_type, $object) {
_field_invoke('update', $obj_type, $object);
list($id, $vid, $bundle, $cacheable) = field_extract_ids($obj_type, $object);
list($id, $vid, $bundle, $cacheable) = entity_extract_ids($obj_type, $object);
// Let other modules act on updating the object, accumulating saved
// fields along the way.
......@@ -916,7 +916,7 @@ function field_attach_update($obj_type, $object) {
function field_attach_delete($obj_type, $object) {
_field_invoke('delete', $obj_type, $object);
list($id, $vid, $bundle, $cacheable) = field_extract_ids($obj_type, $object);
list($id, $vid, $bundle, $cacheable) = entity_extract_ids($obj_type, $object);
// Collect the storage backends used by the fields in the objects.
$storages = array();
......@@ -955,7 +955,7 @@ function field_attach_delete($obj_type, $object) {
function field_attach_delete_revision($obj_type, $object) {
_field_invoke('delete_revision', $obj_type, $object);
list($id, $vid, $bundle, $cacheable) = field_extract_ids($obj_type, $object);
list($id, $vid, $bundle, $cacheable) = entity_extract_ids($obj_type, $object);
// Collect the storage backends used by the fields in the objects.
$storages = array();
......@@ -1193,7 +1193,7 @@ function field_attach_view($obj_type, $object, $build_mode = 'full', $langcode =
$output = _field_invoke_default('view', $obj_type, $object, $build_mode, $null, $options);
// Add custom weight handling.
list($id, $vid, $bundle) = field_extract_ids($obj_type, $object);
list($id, $vid, $bundle) = entity_extract_ids($obj_type, $object);
$output['#attached']['css'][] = drupal_get_path('module', 'field') . '/theme/field.css';
$output['#pre_render'][] = '_field_extra_weights_pre_render';
$output['#extra_fields'] = field_extra_fields($bundle);
......@@ -1229,7 +1229,7 @@ function field_attach_view($obj_type, $object, $build_mode = 'full', $langcode =
* values.
*/
function field_attach_preprocess($obj_type, $object, $element, &$variables) {
list(, , $bundle) = field_extract_ids($obj_type, $object);
list(, , $bundle) = entity_extract_ids($obj_type, $object);
foreach (field_info_instances($obj_type, $bundle) as $instance) {
$field_name = $instance['field_name'];
......
......@@ -258,7 +258,7 @@ function field_create_field($field) {
// Disallow reserved field names. This can't prevent all field name
// collisions with existing object properties, but some is better
// than none.
foreach (field_info_fieldable_types() as $type => $info) {
foreach (entity_get_info() as $type => $info) {
if (in_array($field['field_name'], $info['object keys'])) {
throw new FieldException(t('Attempt to create field name %name which is reserved by entity type %type.', array('%name' => $field['field_name'], '%type' => $type)));
}
......@@ -387,7 +387,7 @@ function field_update_field($field) {
throw new FieldException('Attempt to update a non-existent field.');
}
// Use the prior field values for anything not specifically set by the new
// Use the prior field values for anything not specifically set by the new
// field to be sure that all values are set.
$field += $prior_field;
$field['settings'] += $prior_field['settings'];
......@@ -441,9 +441,9 @@ function field_update_field($field) {
// Clear caches
field_cache_clear(TRUE);
// Invoke external hooks after the cache is cleared for API consistency.
module_invoke_all('field_update_field', $field, $prior_field, $has_data);
module_invoke_all('field_update_field', $field, $prior_field, $has_data);
}
/**
......
......@@ -83,7 +83,7 @@ function field_default_prepare_view($obj_type, $objects, $field, $instances, $la
* @see field_attach_view()
*/
function field_default_view($obj_type, $object, $field, $instance, $langcode, $items, $build_mode) {
list($id, $vid, $bundle) = field_extract_ids($obj_type, $object);
list($id, $vid, $bundle) = entity_extract_ids($obj_type, $object);
$addition = array();
$display = $instance['display'][$build_mode];
......
......@@ -13,7 +13,7 @@ function field_default_form($obj_type, $object, $field, $instance, $langcode, $i
// This could be called with no object, as when a UI module creates a
// dummy form to set default values.
if ($object) {
list($id, , ) = field_extract_ids($obj_type, $object);
list($id, , ) = entity_extract_ids($obj_type, $object);
}
$addition = array();
......
......@@ -24,6 +24,11 @@
* are affected.
*/
function field_info_cache_clear() {
// @todo: Remove this when field_attach_*_bundle() bundle management
// functions are moved to the entity API.
drupal_static_reset('entity_get_info');
cache_clear_all('entity_info', 'cache');
_field_info_collate_types(TRUE);
drupal_static_reset('field_build_modes');
_field_info_collate_fields(TRUE);
......@@ -53,12 +58,6 @@ function field_info_cache_clear() {
* formatter_type.
* * label, field types, behaviors: from hook_field_formatter_info()
* * module: module that exposes the formatter type
* fieldable types: array of hook_entity_info() results, keyed by entity_type.
* * name, id key, revision key, bundle key, cacheable, bundles: from
* hook_entity_info()
* * module: module that exposes the entity type
* @TODO use entity_get_info().
*/
function _field_info_collate_types($reset = FALSE) {
static $info;
......@@ -79,7 +78,6 @@ function _field_info_collate_types($reset = FALSE) {
'widget types' => array(),
'formatter types' => array(),
'storage types' => array(),
'fieldable types' => array(),
);
// Populate field types.
......@@ -139,34 +137,6 @@ function _field_info_collate_types($reset = FALSE) {
}
drupal_alter('field_storage_info', $info['storage types']);
// Populate information about 'fieldable' entities.
foreach (module_implements('entity_info') as $module) {
$entities = (array) module_invoke($module, 'entity_info');
foreach ($entities as $name => $entity_info) {
if (!empty($entity_info['fieldable'])) {
// Provide defaults.
$entity_info += array(
'cacheable' => TRUE,
'translation' => array(),
'bundles' => array(),
);
$entity_info['object keys'] += array(
'revision' => '',
'bundle' => '',
);
// If no bundle key provided, then we assume a single bundle, named
// after the type of the object. Make sure the bundle created
// has the human-readable name we need for bundle messages.
if (empty($entity_info['object keys']['bundle']) && empty($entity_info['bundles'])) {
$entity_info['bundles'] = array($name => array('label' => $entity_info['label']));
}
$info['fieldable types'][$name] = $entity_info;
$info['fieldable types'][$name]['module'] = $module;
}
}
}
drupal_alter('entity_info', $info['fieldable types']);
cache_set('field_info_types', $info, 'cache_field');
}
}
......@@ -457,29 +427,6 @@ function field_info_storage_types($storage_type = NULL) {
}
}
/**
* Return hook_fieldable_info() data.
*
* @param $obj_type
* (optional) A fieldable type name. If ommitted, all fieldable types will be
* returned.
* @return
* Either a fieldable type description, as provided by hook_fieldable_info(),
* or an array of all existing fieldable types, keyed by fieldable type name.
*/
function field_info_fieldable_types($obj_type = NULL) {
$info = _field_info_collate_types();
$fieldable_types = $info['fieldable types'];
if ($obj_type) {
if (isset($fieldable_types[$obj_type])) {
return $fieldable_types[$obj_type];
}
}
else {
return $fieldable_types;
}
}
/**
* Return information about existing bundles.
*
......@@ -491,15 +438,15 @@ function field_info_fieldable_types($obj_type = NULL) {
* keyed by object type.
*/
function field_info_bundles($obj_type = NULL) {
$info = _field_info_collate_types();
$info = entity_get_info();
if ($obj_type) {
return isset($info['fieldable types'][$obj_type]['bundles']) ? $info['fieldable types'][$obj_type]['bundles'] : array();
return isset($info[$obj_type]['bundles']) ? $info[$obj_type]['bundles'] : array();
}
$bundles = array();
foreach ($info['fieldable types'] as $type => $fieldable_info) {
$bundles[$type] = $fieldable_info['bundles'];
foreach ($info as $type => $entity_info) {
$bundles[$type] = $entity_info['bundles'];
}
return $bundles;
}
......
......@@ -506,7 +506,7 @@ function field_format($obj_type, $object, $field, $item, $formatter_type = NULL,
$field_type = field_info_field_types($field['type']);
// We need $field, $instance, $obj_type, $object to be able to display a value...
list(, , $bundle) = field_extract_ids($obj_type, $object);
list(, , $bundle) = entity_extract_ids($obj_type, $object);
$instance = field_info_instance($obj_type, $field['field_name'], $bundle);
$display = array(
......@@ -655,36 +655,7 @@ function field_access($op, $field, $obj_type, $object = NULL, $account = NULL) {
}
/**
* Helper function to extract id, vid, and bundle name from an object.
*
* @param $obj_type
* The type of $object; e.g. 'node' or 'user'.
* @param $object
* The object from which to extract values.
* @return
* A numerically indexed array (not a hash table) containing these
* elements:
*
* 0: primary id of the object
* 1: revision id of the object, or NULL if $obj_type is not versioned
* 2: bundle name of the object
* 3: whether $obj_type's fields should be cached (TRUE/FALSE)
*/
function field_extract_ids($obj_type, $object) {
// TODO D7 : prevent against broken 3rd party $node without 'type'.
$info = field_info_fieldable_types($obj_type);
// Objects being created might not have id/vid yet.
$id = isset($object->{$info['object keys']['id']}) ? $object->{$info['object keys']['id']} : NULL;
$vid = ($info['object keys']['revision'] && isset($object->{$info['object keys']['revision']})) ? $object->{$info['object keys']['revision']} : NULL;
// If no bundle key provided, then we assume a single bundle, named after the
// type of the object.
$bundle = $info['object keys']['bundle'] ? $object->{$info['object keys']['bundle']} : $obj_type;
$cacheable = $info['cacheable'];
return array($id, $vid, $bundle, $cacheable);
}
/**
* Helper function to extract id, vid, and bundle name from an object.
* Helper function to extract the bundle name of from a bundle object.
*
* @param $obj_type
* The type of $object; e.g. 'node' or 'user'.
......@@ -699,41 +670,12 @@ function field_extract_bundle($obj_type, $bundle) {
return $bundle;
}
$info = field_info_fieldable_types($obj_type);
$info = entity_get_info($obj_type);
if (is_object($bundle) && isset($info['bundle keys']['bundle']) && isset($bundle->{$info['bundle keys']['bundle']})) {
return $bundle->{$info['bundle keys']['bundle']};
}
}
/**
* Helper function to assemble an object structure with initial ids.
*
* This function can be seen as reciprocal to field_extract_ids().
*
* @param $obj_type
* The type of $object; e.g. 'node' or 'user'.
* @param $ids
* A numerically indexed array, as returned by field_extract_ids(),
* containing these elements:
* 0: primary id of the object
* 1: revision id of the object, or NULL if $obj_type is not versioned
* 2: bundle name of the object
* @return
* An $object structure, initialized with the ids provided.
*/
function field_create_stub_entity($obj_type, $ids) {
$object = new stdClass();
$info = field_info_fieldable_types($obj_type);
$object->{$info['object keys']['id']} = $ids[0];
if (isset($info['object keys']['revision']) && !is_null($ids[1])) {
$object->{$info['object keys']['revision']} = $ids[1];
}
if ($info['object keys']['bundle']) {
$object->{$info['object keys']['bundle']} = $ids[2];
}
return $object;
}
/**
* Theme preprocess function for field.tpl.php.
*
......@@ -741,7 +683,7 @@ function field_create_stub_entity($obj_type, $ids) {
*/
function template_preprocess_field(&$variables) {
$element = $variables['element'];
list(, , $bundle) = field_extract_ids($element['#object_type'], $element['#object']);
list(, , $bundle) = entity_extract_ids($element['#object_type'], $element['#object']);
$instance = field_info_instance($element['#object_type'], $element['#field_name'], $bundle);
$field = field_info_field($element['#field_name']);
......
......@@ -95,7 +95,7 @@ function field_multilingual_content_languages() {
* TRUE, if the handler is allowed to manage field translations.
*/
function field_multilingual_check_translation_handlers($obj_type, $handler = NULL) {
$obj_info = field_info_fieldable_types($obj_type);
$obj_info = entity_get_info($obj_type);
if (isset($handler)) {
return isset($obj_info['translation'][$handler]) && !empty($obj_info['translation'][$handler]);
......
......@@ -1789,7 +1789,7 @@ class FieldCrudTestCase extends FieldTestCase {
$count = $query->execute()->fetchField();
$this->assertEqual($count, 0, 'A field_config row for the field does not exist.');
}
/**
* Test reading back a field definition.
*/
......@@ -1943,7 +1943,7 @@ class FieldCrudTestCase extends FieldTestCase {
function testUpdateFieldType() {
$field = array('field_name' => 'field_type', 'type' => 'number_decimal');
$field = field_create_field($field);
$test_field = array('field_name' => 'field_type', 'type' => 'number_integer');
try {
field_update_field($test_field);
......@@ -2463,7 +2463,7 @@ class FieldTranslationsTestCase extends FieldTestCase {
function testTranslatableFieldSaveLoad() {
// Enable field translations for nodes.
field_test_entity_info_translatable('node', TRUE);
$obj_info = field_info_fieldable_types('node');
$obj_info = entity_get_info('node');
$this->assertTrue(count($obj_info['translation']), t('Nodes are translatable.'));
// Prepare the field translations.
......@@ -2472,7 +2472,7 @@ class FieldTranslationsTestCase extends FieldTestCase {
$object = field_test_create_stub_entity($eid, $evid, $this->instance['bundle']);
$field_translations = array();
$available_languages = field_multilingual_available_languages($obj_type, $this->field);
$this->assertTrue(count($available_languages) > 1, t('Field is translatable.'));
$this->assertTrue(count($available_languages) > 1, t('Field is translatable.'));
foreach ($available_languages as $langcode) {
$field_translations[$langcode] = $this->_generateTestFieldValues($this->field['cardinality']);
}
......@@ -2529,7 +2529,7 @@ class FieldBulkDeleteTestCase extends FieldTestCase {
function _generateStubObjects($obj_type, $objects, $field_name = NULL) {
$stubs = array();
foreach ($objects as $obj) {
$stub = field_create_stub_entity($obj_type, field_extract_ids($obj_type, $obj));
$stub = entity_create_stub_entity($obj_type, entity_extract_ids($obj_type, $obj));
if (isset($field_name)) {
$stub->{$field_name} = $obj->{$field_name};
}
......
......@@ -344,7 +344,7 @@ function field_sql_storage_field_storage_load($obj_type, $objects, $age, $fields
* Implement hook_field_storage_write().
*/
function field_sql_storage_field_storage_write($obj_type, $object, $op, $fields) {
list($id, $vid, $bundle) = field_extract_ids($obj_type, $object);
list($id, $vid, $bundle) = entity_extract_ids($obj_type, $object);
$etid = _field_sql_storage_etid($obj_type);
foreach ($fields as $field_id) {
......@@ -433,7 +433,7 @@ function field_sql_storage_field_storage_write($obj_type, $object, $op, $fields)
* This function deletes data for all fields for an object from the database.
*/
function field_sql_storage_field_storage_delete($obj_type, $object, $fields) {
list($id, $vid, $bundle) = field_extract_ids($obj_type, $object);
list($id, $vid, $bundle) = entity_extract_ids($obj_type, $object);
$etid = _field_sql_storage_etid($obj_type);
foreach (field_info_instances($obj_type, $bundle) as $instance) {
......@@ -451,7 +451,7 @@ function field_sql_storage_field_storage_delete($obj_type, $object, $fields) {
* an object.
*/
function field_sql_storage_field_storage_purge($obj_type, $object, $field, $instance) {
list($id, $vid, $bundle) = field_extract_ids($obj_type, $object);
list($id, $vid, $bundle) = entity_extract_ids($obj_type, $object);
$etid = _field_sql_storage_etid($obj_type);
$table_name = _field_sql_storage_tablename($field);
......@@ -569,11 +569,11 @@ function field_sql_storage_field_storage_query($field_id, $conditions, $options)
$options['cursor']++;
// If querying all revisions and the entity type has revisions, we need
// to key the results by revision_ids.
$entity_type = field_info_fieldable_types($row->type);
$entity_type = entity_get_info($row->type);
$id = ($load_current || empty($entity_type['object keys']['revision'])) ? $row->entity_id : $row->revision_id;
if (!isset($return[$row->type][$id])) {
$return[$row->type][$id] = field_create_stub_entity($row->type, array($row->entity_id, $row->revision_id, $row->bundle));
$return[$row->type][$id] = entity_create_stub_entity($row->type, array($row->entity_id, $row->revision_id, $row->bundle));
$obj_count++;
}
}
......@@ -594,7 +594,7 @@ function field_sql_storage_field_storage_query($field_id, $conditions, $options)
* This function actually deletes the data from the database.
*/
function field_sql_storage_field_storage_delete_revision($obj_type, $object, $fields) {
list($id, $vid, $bundle) = field_extract_ids($obj_type, $object);
list($id, $vid, $bundle) = entity_extract_ids($obj_type, $object);
$etid = _field_sql_storage_etid($obj_type);
if (isset($vid)) {
......
......@@ -47,83 +47,85 @@ function field_ui_menu() {
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')));
$instance_position = count(explode('/', $path)) + 1;
foreach (entity_get_info() as $obj_type => $info) {
if ($info['fieldable']) {
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')));
$instance_position = count(explode('/', $path)) + 1;
$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,
'file' => 'field_ui.admin.inc',
) + $access;
$items["$path/fields/%field_ui_menu"] = array(
'title callback' => 'field_ui_menu_label',
'title arguments' => array($instance_position),
'load arguments' => array($obj_type, $bundle_arg),
'page callback' => 'drupal_get_form',
'page arguments' => array('field_ui_field_edit_form', $obj_type, $bundle_arg, $instance_position),
'type' => MENU_LOCAL_TASK,
'file' => 'field_ui.admin.inc',
) + $access;
$items["$path/fields/%field_ui_menu/edit"] = array(
'title' => 'Edit instance settings',
'load arguments' => array($obj_type, $bundle_arg),
'page callback' => 'drupal_get_form',
'page arguments' => array('field_ui_field_edit_form', $obj_type, $bundle_arg, $instance_position),
'type' => MENU_DEFAULT_LOCAL_TASK,
'file' => 'field_ui.admin.inc',
) + $access;
$items["$path/fields/%field_ui_menu/field-settings"] = array(
'title' => 'Edit field settings',
'load arguments' => array($obj_type, $bundle_arg),
'page callback' => 'drupal_get_form',
'page arguments' => array('field_ui_field_settings_form', $obj_type, $bundle_arg, $instance_position),
'type' => MENU_LOCAL_TASK,
'file' => 'field_ui.admin.inc',
) + $access;
$items["$path/fields/%field_ui_menu/widget-type"] = array(
'title' => 'Change widget type',
'load arguments' => array($obj_type, $bundle_arg),
'page callback' => 'drupal_get_form',
'page arguments' => array('field_ui_widget_type_form', $obj_type, $bundle_arg, $instance_position),
'type' => MENU_LOCAL_TASK,
'file' => 'field_ui.admin.inc',
) + $access;