Commit 607e9626 authored by Dries's avatar Dries

- Patch #361683by Barry, Yves, Karen, Moshe Weitzman, David Strauss, floriant, chx, David Rothstein: initial field API patch. More work to be done, but ... oh my!
parent d4867346
......@@ -490,8 +490,10 @@ function drupal_verify_profile($profile, $locale) {
*
* @param $module_list
* The modules to install.
* @param $disable_modules_installed_hook
* Normally just testing wants to set this to TRUE.
*/
function drupal_install_modules($module_list = array()) {
function drupal_install_modules($module_list = array(), $disable_modules_installed_hook = FALSE) {
$files = module_rebuild_cache();
$module_list = array_flip(array_values($module_list));
do {
......@@ -511,7 +513,7 @@ function drupal_install_modules($module_list = array()) {
asort($module_list);
$module_list = array_keys($module_list);
$modules_installed = array_filter($module_list, '_drupal_install_module');
if (!empty($modules_installed)) {
if (!$disable_modules_installed_hook && !empty($modules_installed)) {
module_invoke_all('modules_installed', $modules_installed);
}
module_enable($module_list);
......
......@@ -624,8 +624,10 @@ function theme() {
}
if (isset($info['function'])) {
// The theme call is a function.
if (drupal_function_exists($info['function'])) {
$output = call_user_func_array($info['function'], $args);
}
}
else {
// The theme call is a template.
$variables = array(
......@@ -2005,6 +2007,10 @@ function template_preprocess_node(&$variables) {
// Clean up name so there are no underscores.
$variables['template_files'][] = 'node-' . str_replace('_', '-', $node->type);
$variables['template_files'][] = 'node-' . $node->nid;
// Add $FIELD_NAME_rendered variables for fields.
drupal_function_exists('field_attach_preprocess');
$variables += field_attach_preprocess('node', $node);
}
/**
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
<?php
/**
* @file
*
* Default 'implementations' of hook_field_*().
*
* Handles common field housekeeping.
* Those implementations are special, as field.module does not define any field
* types. Those functions take care of default stuff common to all field types.
*
* Storage ops ('load', 'insert', 'update', 'delete', 'delete revisions')
* are not executed field by field, and are thus handled separately.
*/
function field_default_validate($obj_type, $object, $field, $instance, $items, $form) {
// TODO: here we could validate that required fields are filled in (for programmatic save)
}
function field_default_submit($obj_type, &$object, $field, $instance, &$items, $form, &$form_state) {
// Get field values from the submitted form values. Assigning them to $items
// populates $object->field_name when we return from _field_invoke_default().
// TODO D7: Allow the values to be form_altered to another location, like we
// do for the form definition ($form['#fields'][$field_name]['form_path']) ?
if (isset($form_state['values'][$field['field_name']])) {
$items = $form_state['values'][$field['field_name']];
// Remove the 'value' of the 'add more' button.
unset($items[$field['field_name'] . '_add_more']);
// TODO: the above should be moved to validate time (and values saved back
// using form_set_value() ), so that hook_field_validate() works on clean data.
// Not sure we'll want what's below in validate too.
// Reorder items to account for drag-n-drop reordering.
if (field_behaviors_widget('multiple values', $instance) == FIELD_BEHAVIOR_DEFAULT) {
$items = _field_sort_items($field, $items);
}
// Filter out empty values.
$items = field_set_empty($field, $items);
// _field_invoke() does not add back items for fields not present in the
// original $object, so add them manually.
$object->{$field['field_name']} = $items;
}
else {
// The form did not include this field, for instance because of access
// rules: make sure any existing value for the field stays unchanged.
unset($object->{$field['field_name']});
}
}
/**
* The 'view' operation constructs the $object in a way that you can use
* drupal_render() to display the formatted output for an individual field.
* i.e. print drupal_render($object->content['field_foo']);
*
* The code supports both single value formatters, which theme an individual
* item value, and multiple value formatters, which theme all values for the
* field in a single theme. The multiple value formatters could be used, for
* instance, to plot field values on a single map or display them in a graph.
* Single value formatters are the default, multiple value formatters can be
* designated as such in formatter_info().
*
* The $object array will look like:
* $object->content['field_foo']['wrapper'] = array(
* '#type' => 'field',
* '#title' => 'label'
* '#field_name' => 'field_name',
* '#object' => $object,
* '#object_type' => $obj_type,
* // Value of the $teaser param of hook_nodeapi('view').
* '#teaser' => $teaser,
* 'items' =>
* 0 => array(
* '#item' => $items[0],
* // Only for 'single-value' formatters
* '#theme' => $theme,
* '#field_name' => 'field_name',
* '#bundle' => $bundle,
* '#formatter' => $formatter_name,
* '#settings' => $formatter_settings,
* '#object' => $object,
* '#object_type' => $obj_type,
* '#delta' => 0,
* ),
* 1 => array(
* '#item' => $items[1],
* // Only for 'single-value' formatters
* '#theme' => $theme,
* '#field_name' => 'field_name',
* '#bundle' => $bundle_name,
* '#formatter' => $formatter_name,
* '#settings' => $formatter_settings,
* '#object' => $object,
* '#object_type' => $obj_type,
* '#delta' => 1,
* ),
* // Only for 'multiple-value' formatters
* '#theme' => $theme,
* '#field_name' => 'field_name',
* '#bundle' => $bundle_name,
* '#formatter' => $formatter_name,
* '#settings' => $formatter_settings,
* ),
* );
*/
function field_default_view($obj_type, $object, $field, $instance, $items, $teaser) {
list($id, $vid, $bundle) = field_attach_extract_ids($obj_type, $object);
$addition = array();
// Entities without build modes should provide a 'full' context.
// NODE_BUILD_NORMAL is 0, and ('whatever' == 0) is TRUE, so we need a ===.
if (!isset($object->build_mode)) {
$context = 'full';
}
elseif ($object->build_mode === NODE_BUILD_NORMAL
|| $object->build_mode == NODE_BUILD_PREVIEW) {
$context = $teaser ? 'teaser' : 'full';
}
else {
$context = $object->build_mode;
}
// If we don't have specific settings for the current build_mode, we use the
// (required) 'full' build_mode.
$display = isset($instance['display'][$context]) ? $instance['display'][$context] : $instance['display']['full'];
// Ensure we have a valid formatter and formatter settings.
$display = _field_get_formatter($display, $field);
if ($display['type'] && $display['type'] !== 'hidden') {
$theme = 'field_formatter_' . $display['type'];
$single = (field_behaviors_formatter('multiple values', $display) == FIELD_BEHAVIOR_DEFAULT);
$label_display = $display['label'];
if (isset($object->build_mode) && $object->build_mode == NODE_BUILD_SEARCH_INDEX) {
$label_display = 'hidden';
}
$info = array(
'#field_name' => $field['field_name'],
'#bundle' => $bundle,
'#object' => $object,
'#object_type' => $obj_type,
);
$element = $info + array(
'#type' => 'field',
'#title' => check_plain(t($instance['label'])),
'#access' => field_access('view', $field),
'#label_display' => $label_display,
'#teaser' => $teaser,
'#single' => $single,
'items' => array(),
);
// Fill-in items.
foreach ($items as $delta => $item) {
$element['items'][$delta] = array(
'#item' => $item,
'#weight' => $delta,
);
}
// Append formatter information either on each item ('single-value' formatter)
// or at the upper 'items' level ('multiple-value' formatter)
$format_info = $info + array(
'#formatter' => $display['type'],
'#settings' => $display['settings'],
'#theme' => $theme,
);
if ($single) {
foreach ($items as $delta => $item) {
$element['items'][$delta] += $format_info;
$element['items'][$delta]['#item']['#delta'] = $delta;
}
}
else {
$element['items'] += $format_info;
}
// The wrapper lets us get the themed output for the whole field
// to populate the $FIELD_NAME_rendered variable for templates,
// and hide it from the $content variable if needed.
// See 'preprocess' op and theme_content_field_wrapper()?
$wrapper = $info + array(
'field' => $element,
'#weight' => $instance['weight'],
'#post_render' => array('field_wrapper_post_render'),
'#context' => $context,
);
$addition = array($field['field_name'] => $wrapper);
}
return $addition;
}
/**
* Hide excluded fields from the $content variable in templates.
*/
function field_wrapper_post_render($content, $element) {
$instance = field_info_instance($element['#field_name'], $element['#bundle']);
if (theme('field_exclude', $content, $instance, $element['#context'])) {
return '';
}
return $content;
}
/**
* 'Theme' function for a field's addition to the combined template output,
* i.e. the node's $content or the user's $user_profile value.
* This allows more flexibility in templates : you can use custom markup
* around a few specific fields, and print the rest normally.
*
* This is a theme function, so it can be overridden in different
* themes to produce different results.
*
* The html for individual fields and groups are available in the
* $FIELD_NAME_rendered and $GROUP_NAME_rendered variables.
*
* @return
* Whether or not the field's content is to be added in this context.
* Uses the 'exclude' value from the field's display settings.
*/
function theme_field_exclude($content, $object, $context) {
if (empty($object['display'])
|| empty($object['display'][$context])
|| empty($object['display'][$context]['exclude'])) {
return FALSE;
}
else {
return TRUE;
}
}
function field_default_preprocess($obj_type, $object, $field, $instance, &$items) {
return array(
$field['field_name'] . '_rendered' => isset($object->content[$field['field_name']]['#children']) ? $object->content[$field['field_name']]['#children'] : '',
);
}
function field_default_prepare_translation($obj_type, $object, $field, $instance, &$items) {
$addition = array();
if (isset($object->translation_source->$field['field_name'])) {
$addition[$field['field_name']] = $object->translation_source->$field['field_name'];
}
return $addition;
}
\ No newline at end of file
This diff is collapsed.
; $Id$
name = Field
description = Field API to add fields to objects like nodes and users.
package = Core - fields
core = 7.x
files[] = field.module
files[] = field.install
files[] = field.crud.inc
files[] = field.info.inc
files[] = field.default.inc
files[] = field.attach.inc
files[] = field.form.inc
files[] = field.autoload.inc
dependencies[] = field_sql_storage
required = TRUE
This diff is collapsed.
<?php
// $Id$
/**
* Implementation of hook_install().
*/
function field_install() {
drupal_install_schema('field');
}
/**
* Implementation of hook_uninstall().
*/
function field_uninstall() {
drupal_uninstall_schema('field');
}
/**
* Implementation of hook_enable().
*/
function field_enable() {
// Make sure old data is emptied out of the caches, since it
// may no longer be valid since the module was last enabled,
// especially if not all the same field modules are enabled
// as before. Especially needed during updates.
module_load_include('inc', 'field', 'field.crud');
module_load_include('inc', 'field', 'field.info');
cache_clear_all('*', 'cache_field', TRUE);
field_cache_clear(TRUE);
}
/**
* Implementation of hook_disable().
*/
function field_disable() {
// Make sure old data is emptied out of the caches, since it
// may no longer be valid when the module is re-enabled.
module_load_include('inc', 'field', 'field.crud');
cache_clear_all('*', 'cache_field', TRUE);
field_cache_clear(TRUE);
}
/**
* Implementation of hook_schema.
*/
function field_schema() {
// Static (meta) tables.
$schema['field_config'] = array(
'fields' => array(
'field_name' => array(
'type' => 'varchar',
'length' => 32,
'not null' => TRUE,
'description' => 'The name of this field',
),
'type' => array(
'type' => 'varchar',
'length' => 128,
'not null' => TRUE,
'description' => 'The type of this field, coming from a field module',
),
'locked' => array(
'type' => 'int',
'size' => 'tiny',
'not null' => TRUE,
'default' => 0,
'description' => '@TODO',
),
'settings' => array(
'type' => 'text',
'size' => 'medium',
'not null' => TRUE,
'serialize' => TRUE,
'description' => 'Field specific settings, for example maximum length',
),
'module' => array(
'type' => 'varchar',
'length' => 128,
'not null' => TRUE,
'default' => '',
),
'cardinality' => array(
'type' => 'int',
'size' => 'tiny',
'not null' => TRUE,
'default' => 0,
),
'active' => array(
'type' => 'int',
'size' => 'tiny',
'not null' => TRUE,
'default' => 0,
),
'deleted' => array(
'type' => 'int',
'size' => 'tiny',
'not null' => TRUE,
'default' => 0,
),
),
'primary key' => array('field_name'),
'indexes' => array(
// used by field_read_fields
'active_deleted' => array('active', 'deleted'),
// used by field_modules_disabled
'module' => array('module'),
// used by field_associate_fields
'type' => array('type'),
),
);
$schema['field_config_instance'] = array(
'fields' => array(
'field_name' => array('type' => 'varchar', 'length' => 32, 'not null' => TRUE, 'default' => ''),
'bundle' => array('type' => 'varchar', 'length' => 128, 'not null' => TRUE, 'default' => ''),
'widget_type' => array('type' => 'varchar', 'length' => 128, 'not null' => TRUE, 'default' => ''),
'widget_module' => array('type' => 'varchar', 'length' => 128, 'not null' => TRUE, 'default' => ''),
'widget_active' => array(
'type' => 'int',
'size' => 'tiny',
'not null' => TRUE,
'default' => 0,
),
'data' => array(
'type' => 'text',
'size' => 'medium',
'not null' => TRUE,
'serialize' => TRUE,
),
'weight' => array(
'type' => 'int',
'not null' => TRUE,
'default' => 0,
),
'deleted' => array(
'type' => 'int',
'size' => 'tiny',
'not null' => TRUE,
'default' => 0,
),
),
'primary key' => array('field_name', 'bundle'),
'indexes' => array(
// used by field_read_instances
'widget_active_deleted' => array('widget_active', 'deleted'),
// used by field_modules_disabled
'widget_module' => array('widget_module'),
// used by field_associate_fields
'widget_type' => array('widget_type'),
),
);
$schema['cache_field'] = drupal_get_schema_unprocessed('system', 'cache');
return $schema;
}
This diff is collapsed.
This diff is collapsed.
; $Id$
name = Field SQL storage
description = Stores field data in an SQL database.
package = Core - fields
core = 7.x
files[] = field_sql_storage.module
files[] = field_sql_storage.install
required = TRUE
\ No newline at end of file
<?php
// $Id$
/**
* Implementation of hook_install().
*/
function field_sql_storage_install() {
drupal_install_schema('field_sql_storage');
}
/**
* Implementation of hook_uninstall().
*/
function field_sql_storage_uninstall() {
drupal_uninstall_schema('field_sql_storage');
}
function field_sql_storage_schema() {
$schema = array();
// Static (meta-data) tables.
$schema['field_config_entity_type'] = array(
'fields' => array(
'etid' => array(
'type' => 'serial',
'unsigned' => TRUE,
'not null' => TRUE,
'description' => 'The unique id for this entity type',
),
'type' => array(
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'description' => 'An entity type',
),
),
'primary key' => array('etid'),
'unique keys' => array('type' => array('type')),
);
// Dynamic (data) tables.
if (db_table_exists('field_config')) {
$fields = field_read_fields();
drupal_load('module', 'field_sql_storage');
$schema = array();
foreach ($fields as $field) {
$schema += _field_sql_storage_schema($field);
}
}
return $schema;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment