summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAngie Byron <webchick@24967.no-reply.drupal.org>2009-07-10 05:58:13 +0000
committerAngie Byron <webchick@24967.no-reply.drupal.org>2009-07-10 05:58:13 +0000
commitf6ccf978f6fc256ca1f17bd8e6b1ae5be4fe8df2 (patch)
treeff1b9dcdb4d8c64fea7470194b5c36d0253f4260
parente916edc798f891fdb08e2fae9684afc02e3de9d3 (diff)
downloadbrdo-f6ccf978f6fc256ca1f17bd8e6b1ae5be4fe8df2.tar.gz
brdo-f6ccf978f6fc256ca1f17bd8e6b1ae5be4fe8df2.tar.bz2
#488542 by yched: Allow field UI to be attached to any fieldable entity.
-rw-r--r--modules/field/field.api.php96
-rw-r--r--modules/field/field.attach.inc58
-rw-r--r--modules/field/field.info.inc12
-rw-r--r--modules/field/modules/field_sql_storage/field_sql_storage.module8
-rw-r--r--modules/node/node.module25
-rw-r--r--modules/simpletest/tests/field_test.module48
-rw-r--r--modules/taxonomy/taxonomy.module24
-rw-r--r--modules/user/user.module15
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;