diff options
-rw-r--r-- | modules/field/field.api.php | 96 | ||||
-rw-r--r-- | modules/field/field.attach.inc | 58 | ||||
-rw-r--r-- | modules/field/field.info.inc | 12 | ||||
-rw-r--r-- | modules/field/modules/field_sql_storage/field_sql_storage.module | 8 | ||||
-rw-r--r-- | modules/node/node.module | 25 | ||||
-rw-r--r-- | modules/simpletest/tests/field_test.module | 48 | ||||
-rw-r--r-- | modules/taxonomy/taxonomy.module | 24 | ||||
-rw-r--r-- | modules/user/user.module | 15 |
8 files changed, 193 insertions, 93 deletions
diff --git a/modules/field/field.api.php b/modules/field/field.api.php index 48eb5005e..76268b908 100644 --- a/modules/field/field.api.php +++ b/modules/field/field.api.php @@ -9,47 +9,81 @@ /** * Inform the Field API about one or more fieldable types. * - * Inform the Field API about one or more fieldable types, (object - * types to which fields can be attached). + * Inform the Field API about one or more fieldable types (object types to + * which fields can be attached). * * @return * An array whose keys are fieldable object type names and - * whose values identify properties of those types that the Field - * system needs to know about: - * - * name: The human-readable name of the type. - * id key: The object property that contains the primary id for the - * object. Every object passed to the Field API must - * have this property and its value must be numeric. - * revision key: The object property that contains the revision id - * for the object, or NULL if the object type is not - * versioned. The Field API assumes that all revision ids are - * unique across all instances of a type; this means, for example, - * that every object's revision ids cannot be 0, 1, 2, ... - * bundle key: The object property that contains the bundle name for - * the object (bundle name is what nodes call "content type"). - * The bundle name defines which fields are connected to the object. - * cacheable: A boolean indicating whether Field API should cache + * whose values are arrays with the following key/value pairs: + * - label: The human-readable name of the type. + * - object keys: An array describing how the Field API can extract the + * informations it needs from the objects of the type. + * - id: The name of the property that contains the primary id of the + * object. Every object passed to the Field API must have this property + * and its value must be numeric. + * - revision: The name of the property that contains the revision id of + * the object. The Field API assumes that all revision ids are unique + * across all objects of a type. + * This element can be omitted if the objects of this type are not + * versionable. + * - bundle: The name of the property that contains the bundle name for the + * object. The bundle name defines which set of fields are attached to + * the object (e.g. what nodes call "content type"). + * This element can be omitted if this type has no bundles (all objects + * have the same fields). + * - bundle keys: An array describing how the Field API can extract the + * informations it needs from the bundle objects for this type (e.g + * $vocabulary objects for terms; not applicable for nodes). + * This element can be omitted if this type's bundles do not exist as + * standalone objects. + * - bundle: The name of the property that contains the name of the bundle + * object. + * - cacheable: A boolean indicating whether Field API should cache * loaded fields for each object, reducing the cost of * field_attach_load(). - * bundles: An array of all existing bundle names for this object - * type. TODO: Define format. TODO: I'm unclear why we need - * this. + * - bundles: An array describing all bundles for this object type. + * Keys are bundles machine names, as found in the objects' 'bundle' + * property (defined in the 'object keys' entry above). + * - label: The human-readable name of the bundle. + * - admin: An array of informations that allow Field UI pages (currently + * implemented in a contributed module) to attach themselves to the + * existing administration pages for the bundle. + * - path: the path of the bundle's main administration page, as defined + * in hook_menu(). If the path includes a placeholder for the bundle, + * the 'bundle argument', 'bundle helper' and 'real path' keys below + * are required. + * - bundle argument: The position of the placeholder in 'path', if any. + * - real path: The actual path (no placeholder) of the bundle's main + * administration page. This will be used to generate links. + * - access callback: As in hook_menu(). 'user_access' will be assumed if + * no value is provided. + * - access arguments: As in hook_menu(). */ function hook_fieldable_info() { $return = array( - 'node' => array( - 'name' => t('Node'), - 'id key' => 'nid', - 'revision key' => 'vid', - 'bundle key' => 'type', - // Node.module handles its own caching. - 'cacheable' => FALSE, - // Bundles must provide human readable name so - // we can create help and error messages about them. - 'bundles' => node_type_get_names(), + 'taxonomy_term' => array( + 'label' => t('Taxonomy term'), + 'object keys' => array( + 'id' => 'tid', + 'bundle' => 'vocabulary_machine_name', + ), + 'bundle keys' => array( + 'bundle' => 'machine_name', + ), + 'bundles' => array(), ), ); + foreach (taxonomy_get_vocabularies() as $vocabulary) { + $return['taxonomy_term']['bundles'][$vocabulary->machine_name] = array( + 'label' => $vocabulary->name, + 'admin' => array( + 'path' => 'admin/content/taxonomy/%taxonomy_vocabulary', + 'real path' => 'admin/content/taxonomy/' . $vocabulary->vid, + 'bundle argument' => 3, + 'access arguments' => array('administer taxonomy'), + ), + ); + } return $return; } diff --git a/modules/field/field.attach.inc b/modules/field/field.attach.inc index 66574157a..08ef44173 100644 --- a/modules/field/field.attach.inc +++ b/modules/field/field.attach.inc @@ -382,8 +382,8 @@ function field_attach_form($obj_type, $object, &$form, &$form_state) { * The type of $object; e.g. 'node' or 'user'. * @param $objects * An array of objects for which to load fields, keyed by object id. - * Each object needs to have its 'bundle key', 'id key' and (if applicable) - * 'revision key' filled. + * Each object needs to have its 'bundle', 'id' and (if applicable) + * 'revision' keys filled. * @param $age * FIELD_LOAD_CURRENT to load the most recent revision for all * fields, or FIELD_LOAD_REVISION to load the version indicated by @@ -485,8 +485,8 @@ function field_attach_load($obj_type, $objects, $age = FIELD_LOAD_CURRENT) { * The type of $object; e.g. 'node' or 'user'. * @param $objects * An array of objects for which to load fields, keyed by object id. - * Each object needs to have its 'bundle key', 'id key' and 'revision key' - * filled. + * Each object needs to have its 'bundle', 'id' and (if applicable) + * 'revision' keys filled. * @returns * On return, the objects in $objects are modified by having the * appropriate set of fields added. @@ -546,8 +546,8 @@ function field_attach_validate($obj_type, $object) { * @param $obj_type * The type of $object; e.g. 'node' or 'user'. * @param $object - * The object being submitted. The 'bundle key', 'id key' and (if applicable) - * 'revision key' should be present. The actual field values will be read + * The object being submitted. The 'bundle', 'id' and (if applicable) + * 'revision' keys should be present. The actual field values will be read * from $form_state['values']. * @param $form * The form structure. @@ -578,8 +578,8 @@ function field_attach_form_validate($obj_type, $object, $form, &$form_state) { * @param $obj_type * The type of $object; e.g. 'node' or 'user'. * @param $object - * The object being submitted. The 'bundle key', 'id key' and (if applicable) - * 'revision key' should be present. The actual field values will be read + * The object being submitted. The 'bundle', 'id' and (if applicable) + * 'revision' keys should be present. The actual field values will be read * from $form_state['values']. * @param $form * The form structure to fill in. @@ -993,20 +993,42 @@ function field_attach_delete_bundle($bundle) { * 2: bundle name of the object * 3: whether $obj_type's fields should be cached (TRUE/FALSE) */ -function field_attach_extract_ids($object_type, $object) { +function field_attach_extract_ids($obj_type, $object) { // TODO D7 : prevent against broken 3rd party $node without 'type'. - $info = field_info_fieldable_types($object_type); + $info = field_info_fieldable_types($obj_type); // Objects being created might not have id/vid yet. - $id = isset($object->{$info['id key']}) ? $object->{$info['id key']} : NULL; - $vid = ($info['revision key'] && isset($object->{$info['revision key']})) ? $object->{$info['revision key']} : NULL; + $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['bundle key'] ? $object->{$info['bundle key']} : $object_type; + $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. + * + * @param $obj_type + * The type of $object; e.g. 'node' or 'user'. + * @param $bundle + * The bundle object (or string if bundles for this object type do not exist + * as standalone objects). + * @return + * The bundle name. + */ +function field_attach_extract_bundle($obj_type, $bundle) { + if (is_string($bundle)) { + return $bundle; + } + + $info = field_info_fieldable_types($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_attach_extract_ids(). @@ -1025,12 +1047,12 @@ function field_attach_extract_ids($object_type, $object) { function field_attach_create_stub_object($obj_type, $ids) { $object = new stdClass(); $info = field_info_fieldable_types($obj_type); - $object->{$info['id key']} = $ids[0]; - if (isset($info['revision key']) && !is_null($ids[1])) { - $object->{$info['revision key']} = $ids[1]; + $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['bundle key']) { - $object->{$info['bundle key']} = $ids[2]; + if ($info['object keys']['bundle']) { + $object->{$info['object keys']['bundle']} = $ids[2]; } return $object; } diff --git a/modules/field/field.info.inc b/modules/field/field.info.inc index 3eb1d2e33..e9ac66c23 100644 --- a/modules/field/field.info.inc +++ b/modules/field/field.info.inc @@ -126,16 +126,18 @@ function _field_info_collate_types($reset = FALSE) { foreach ($fieldable_types as $name => $fieldable_info) { // Provide defaults. $fieldable_info += array( - 'revision key' => '', - 'bundle key' => '', 'cacheable' => TRUE, 'bundles' => array(), ); + $fieldable_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($fieldable_info['bundle key'])) { - $fieldable_info['bundles'] = array($name => $fieldable_info['name']); + if (empty($fieldable_info['object keys']['bundle']) && empty($fieldable_info['bundles'])) { + $fieldable_info['bundles'] = array($name => array('label' => $fieldable_info['label'])); } $info['fieldable types'][$name] = $fieldable_info; $info['fieldable types'][$name]['module'] = $module; @@ -367,7 +369,7 @@ function field_info_bundles($obj_type = NULL) { } /** - * Identity the type of entity that created a bundle. + * Identify the type of entity that created a bundle. * // TODO : might not be needed depending on how we solve * // the 'namespace bundle names' issue */ diff --git a/modules/field/modules/field_sql_storage/field_sql_storage.module b/modules/field/modules/field_sql_storage/field_sql_storage.module index b74bad0da..3ce99136a 100644 --- a/modules/field/modules/field_sql_storage/field_sql_storage.module +++ b/modules/field/modules/field_sql_storage/field_sql_storage.module @@ -412,23 +412,23 @@ function field_sql_storage_field_storage_query($field_name, $conditions, $count, $query->range($cursor, $limit); } $results = $query->execute(); - + $found = FALSE; foreach ($results as $row) { $found = TRUE; ++$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); - $id = ($load_current || empty($entity_type['revision key'])) ? $row->entity_id : $row->revision_id; + $id = ($load_current || empty($entity_type['object keys']['revision'])) ? $row->entity_id : $row->revision_id; // We get multiple rows if the field has multiple deltas. Only // count the first one. if (isset($return[$row->type][$id])) { continue; } - + $return[$row->type][$id] = field_attach_create_stub_object($row->type, array($row->entity_id, $row->revision_id, $row->bundle)); --$count; } diff --git a/modules/node/node.module b/modules/node/node.module index 4c3141b25..639d6f98c 100644 --- a/modules/node/node.module +++ b/modules/node/node.module @@ -124,17 +124,28 @@ function node_cron() { function node_fieldable_info() { $return = array( 'node' => array( - 'name' => t('Node'), - 'id key' => 'nid', - 'revision key' => 'vid', - 'bundle key' => 'type', + 'label' => t('Node'), + 'object keys' => array( + 'id' => 'nid', + 'revision' => 'vid', + 'bundle' => 'type', + ), // Node.module handles its own caching. // 'cacheable' => FALSE, - // Bundles must provide human readable name so - // we can create help and error messages about them. - 'bundles' => node_type_get_names(), + 'bundles' => array(), ), ); + // Bundles must provide a human readable name so we can create help and error + // messages, and the path to attach Field admin pages to. + foreach (node_type_get_names() as $type => $name) { + $return['node']['bundles'][$type] = array( + 'label' => $name, + 'admin' => array( + 'path' => 'admin/build/node-type/' . str_replace('_', '-', $type), + 'access arguments' => array('administer content types'), + ), + ); + } return $return; } diff --git a/modules/simpletest/tests/field_test.module b/modules/simpletest/tests/field_test.module index 6073faefe..94efd014c 100644 --- a/modules/simpletest/tests/field_test.module +++ b/modules/simpletest/tests/field_test.module @@ -26,12 +26,12 @@ function field_test_permission() { */ function field_test_menu() { $items = array(); - $info = field_test_fieldable_info(); + $bundles = field_info_bundles('test_entity'); - foreach (array_keys($info['test_entity']['bundles']) as $bundle) { - $bundle_url_str = str_replace('_', '-', $bundle); + foreach ($bundles as $bundle_name => $bundle_info) { + $bundle_url_str = str_replace('_', '-', $bundle_name); $items['test-entity/add/' . $bundle_url_str] = array( - 'title' => "Add $bundle test_entity", + 'title' => t('Add %bundle test_entity', array('%bundle' => $bundle_info['label'])), 'page callback' => 'field_test_entity_add', 'page arguments' => array(2), 'access arguments' => array('administer field_test content'), @@ -61,23 +61,27 @@ function field_test_menu() { * Define a test fieldable entity. */ function field_test_fieldable_info() { - $bundles = variable_get('field_test_bundles', array('test_bundle' => 'Test Bundle')); + $bundles = variable_get('field_test_bundles', array('test_bundle' => array('label' => 'Test Bundle'))); return array( 'test_entity' => array( 'name' => t('Test Entity'), - 'id key' => 'ftid', - 'revision key' => 'ftvid', + 'object keys' => array( + 'id' => 'ftid', + 'revision' => 'ftvid', + 'bundle' => 'fttype', + ), 'cacheable' => FALSE, - 'bundle key' => 'fttype', 'bundles' => $bundles, ), // This entity type doesn't get form handling for now... 'test_cacheable_entity' => array( 'name' => t('Test Entity, cacheable'), - 'id key' => 'ftid', - 'revision key' => 'ftvid', + 'object keys' => array( + 'id' => 'ftid', + 'revision' => 'ftvid', + 'bundle' => 'fttype', + ), 'cacheable' => TRUE, - 'bundle key' => 'fttype', 'bundles' => $bundles, ), ); @@ -86,18 +90,18 @@ function field_test_fieldable_info() { /** * Create a new bundle for test_entity objects. * - * @param $bundle + * @param $bundle_name * The machine-readable name of the bundle. * @param $text * The human-readable name of the bundle. If none is provided, the machine * name will be used. */ -function field_test_create_bundle($bundle, $text = NULL) { - $bundles = variable_get('field_test_bundles', array('test_bundle' => 'Test Bundle')); - $bundles += array($bundle => $text ? $text : $bundle); +function field_test_create_bundle($bundle_name, $text = NULL) { + $bundles = variable_get('field_test_bundles', array('test_bundle' => array('label' => 'Test Bundle'))); + $bundles += array($bundle_name => array('label' => $text ? $text : $bundle_name)); variable_set('field_test_bundles', $bundles); - field_attach_create_bundle($bundle); + field_attach_create_bundle($bundle_name); } /** @@ -109,7 +113,7 @@ function field_test_create_bundle($bundle, $text = NULL) { * The new machine-readable name of the bundle. */ function field_test_rename_bundle($bundle_old, $bundle_new) { - $bundles = variable_get('field_test_bundles', array('test_bundle' => 'Test Bundle')); + $bundles = variable_get('field_test_bundles', array('test_bundle' => array('label' => 'Test Bundle'))); $bundles[$bundle_new] = $bundles[$bundle_old]; unset($bundles[$bundle_old]); variable_set('field_test_bundles', $bundles); @@ -120,15 +124,15 @@ function field_test_rename_bundle($bundle_old, $bundle_new) { /** * Delete a bundle for test_entity objects. * - * @param $bundle + * @param $bundle_name * The machine-readable name of the bundle to delete. */ -function field_test_delete_bundle($bundle) { - $bundles = variable_get('field_test_bundles', array('test_bundle' => 'Test Bundle')); - unset($bundles[$bundle]); +function field_test_delete_bundle($bundle_name) { + $bundles = variable_get('field_test_bundles', array('test_bundle' => array('label' => 'Test Bundle'))); + unset($bundles[$bundle_name]); variable_set('field_test_bundles', $bundles); - field_attach_delete_bundle($bundle); + field_attach_delete_bundle($bundle_name); } /** diff --git a/modules/taxonomy/taxonomy.module b/modules/taxonomy/taxonomy.module index a8996514d..4c9b0988f 100644 --- a/modules/taxonomy/taxonomy.module +++ b/modules/taxonomy/taxonomy.module @@ -24,12 +24,28 @@ function taxonomy_permission() { function taxonomy_fieldable_info() { $return = array( 'taxonomy_term' => array( - 'name' => t('Taxonomy term'), - 'id key' => 'tid', - 'bundle key' => 'vocabulary_machine_name', - 'bundles' => taxonomy_vocabulary_get_names(), + 'label' => t('Taxonomy term'), + 'object keys' => array( + 'id' => 'tid', + 'bundle' => 'vocabulary_machine_name', + ), + 'bundle keys' => array( + 'bundle' => 'machine_name', + ), + 'bundles' => array(), ), ); + foreach (taxonomy_get_vocabularies() as $vocabulary) { + $return['taxonomy_term']['bundles'][$vocabulary->machine_name] = array( + 'label' => $vocabulary->name, + 'admin' => array( + 'path' => 'admin/content/taxonomy/%taxonomy_vocabulary', + 'real path' => 'admin/content/taxonomy/' . $vocabulary->vid, + 'bundle argument' => 3, + 'access arguments' => array('administer taxonomy'), + ), + ); + } return $return; } diff --git a/modules/user/user.module b/modules/user/user.module index 277555038..3072ae2ef 100644 --- a/modules/user/user.module +++ b/modules/user/user.module @@ -89,8 +89,19 @@ function user_theme() { function user_fieldable_info() { $return = array( 'user' => array( - 'name' => t('User'), - 'id key' => 'uid', + 'label' => t('User'), + 'object keys' => array( + 'id' => 'uid', + ), + 'bundles' => array( + 'user' => array( + 'label' => t('User'), + 'admin' => array( + 'path' => 'admin/settings/user', + 'access arguments' => array('administer users'), + ), + ), + ), ), ); return $return; |