updated core to 7.73

This commit is contained in:
2020-09-24 17:04:08 +02:00
parent 084d28842a
commit 7d87153100
524 changed files with 25194 additions and 7745 deletions
+90 -16
View File
@@ -1,4 +1,8 @@
<?php
/**
* @file
* Hooks provided by the Field module.
*/
/**
* @addtogroup hooks
@@ -23,14 +27,22 @@
* @see hook_field_extra_fields_alter()
*
* @return
* A nested array of 'pseudo-field' components. Each list is nested within
* the following keys: entity type, bundle name, context (either 'form' or
* A nested array of 'pseudo-field' elements. Each list is nested within the
* following keys: entity type, bundle name, context (either 'form' or
* 'display'). The keys are the name of the elements as appearing in the
* renderable array (either the entity form or the displayed entity). The
* value is an associative array:
* - label: The human readable name of the component.
* - description: A short description of the component contents.
* - label: The human readable name of the element.
* - description: A short description of the element contents.
* - weight: The default weight of the element.
* - edit: (optional) String containing markup (normally a link) used as the
* element's 'edit' operation in the administration interface. Only for
* 'form' context.
* - delete: (optional) String containing markup (normally a link) used as the
* element's 'delete' operation in the administration interface. Only for
* 'form' context.
*
* @ingroup field_types
*/
function hook_field_extra_fields() {
$extra['node']['poll'] = array(
@@ -70,6 +82,8 @@ function hook_field_extra_fields() {
* The associative array of 'pseudo-field' components.
*
* @see hook_field_extra_fields()
*
* @ingroup field_types
*/
function hook_field_extra_fields_alter(&$info) {
// Force node title to always be at the top of the list by default.
@@ -107,6 +121,9 @@ function hook_field_extra_fields_alter(&$info) {
/**
* Define Field API field types.
*
* Along with this hook, you also need to implement other hooks. See
* @link field_types Field Types API @endlink for more information.
*
* @return
* An array whose keys are field type names and whose values are arrays
* describing the field type, with the following key/value pairs:
@@ -193,8 +210,11 @@ function hook_field_info_alter(&$info) {
/**
* Define the Field API schema for a field structure.
*
* This hook MUST be defined in .install for it to be detected during
* installation and upgrade.
* This is invoked when a field is created, in order to obtain the database
* schema from the module that defines the field's type.
*
* This hook must be defined in the module's .install file for it to be detected
* during installation and upgrade.
*
* @param $field
* A field structure.
@@ -644,6 +664,8 @@ function hook_field_delete_revision($entity_type, $entity, $field, $instance, $l
* The source entity from which field values are being copied.
* @param $source_langcode
* The source language from which field values are being copied.
*
* @ingroup field_language
*/
function hook_field_prepare_translation($entity_type, $entity, $field, $instance, $langcode, &$items, $source_entity, $source_langcode) {
// If the translating user is not permitted to use the assigned text format,
@@ -1238,7 +1260,7 @@ function hook_field_formatter_view($entity_type, $entity, $field, $instance, $la
*/
/**
* @ingroup field_attach
* @addtogroup field_attach
* @{
*/
@@ -1300,9 +1322,33 @@ function hook_field_attach_load($entity_type, $entities, $age, $options) {
* This hook is invoked after the field module has performed the operation.
*
* See field_attach_validate() for details and arguments.
*
* @param $entity_type
* The type of $entity; e.g., 'node' or 'user'.
* @param $entity
* The entity with fields to validate.
* @param array $errors
* The array of errors (keyed by field name, language code, and delta) that
* have already been reported for the entity. The function should add its
* errors to this array. Each error is an associative array with the following
* keys and values:
* - error: An error code (should be a string prefixed with the module name).
* - message: The human readable message to be displayed.
*/
function hook_field_attach_validate($entity_type, $entity, &$errors) {
// @todo Needs function body.
// Make sure any images in article nodes have an alt text.
if ($entity_type == 'node' && $entity->type == 'article' && !empty($entity->field_image)) {
foreach ($entity->field_image as $langcode => $items) {
foreach ($items as $delta => $item) {
if (!empty($item['fid']) && empty($item['alt'])) {
$errors['field_image'][$langcode][$delta][] = array(
'error' => 'field_example_invalid',
'message' => t('All images in articles need to have an alternative text set.'),
);
}
}
}
}
}
/**
@@ -1504,6 +1550,8 @@ function hook_field_attach_prepare_translation_alter(&$entity, $context) {
* - entity_type: The type of the entity to be displayed.
* - entity: The entity with fields to render.
* - langcode: The language code $entity has to be displayed in.
*
* @ingroup field_language
*/
function hook_field_language_alter(&$display_language, $context) {
// Do not apply core language fallback rules if they are disabled or if Locale
@@ -1525,6 +1573,8 @@ function hook_field_language_alter(&$display_language, $context) {
* An associative array containing:
* - entity_type: The type of the entity the field is attached to.
* - field: A field data structure.
*
* @ingroup field_language
*/
function hook_field_available_languages_alter(&$languages, $context) {
// Add an unavailable language.
@@ -1575,7 +1625,7 @@ function hook_field_attach_rename_bundle($entity_type, $bundle_old, $bundle_new)
* @param $entity_type
* The type of entity; for example, 'node' or 'user'.
* @param $bundle
* The bundle that was just deleted.
* The name of the bundle that was just deleted.
* @param $instances
* An array of all instances that existed for the bundle before it was
* deleted.
@@ -1590,7 +1640,7 @@ function hook_field_attach_delete_bundle($entity_type, $bundle, $instances) {
}
/**
* @} End of "defgroup field_attach".
* @} End of "addtogroup field_attach".
*/
/**
@@ -1847,7 +1897,7 @@ function hook_field_storage_write($entity_type, $entity, $op, $fields) {
$items = (array) $entity->{$field_name}[$langcode];
$delta_count = 0;
foreach ($items as $delta => $item) {
// We now know we have someting to insert.
// We now know we have something to insert.
$do_insert = TRUE;
$record = array(
'entity_type' => $entity_type,
@@ -2250,6 +2300,10 @@ function hook_field_storage_pre_update($entity_type, $entity, &$skip_fields) {
}
}
/**
* @} End of "addtogroup field_storage
*/
/**
* Returns the maximum weight for the entity components handled by the module.
*
@@ -2263,9 +2317,12 @@ function hook_field_storage_pre_update($entity_type, $entity, &$skip_fields) {
* @param $context
* The context for which the maximum weight is requested. Either 'form', or
* the name of a view mode.
*
* @return
* The maximum weight of the entity's components, or NULL if no components
* were found.
*
* @ingroup field_info
*/
function hook_field_info_max_weight($entity_type, $bundle, $context) {
$weights = array();
@@ -2277,6 +2334,11 @@ function hook_field_info_max_weight($entity_type, $bundle, $context) {
return $weights ? max($weights) : NULL;
}
/**
* @addtogroup field_types
* @{
*/
/**
* Alters the display settings of a field before it gets displayed.
*
@@ -2343,6 +2405,10 @@ function hook_field_display_ENTITY_TYPE_alter(&$display, $context) {
}
}
/**
* @} End of "addtogroup field_types
*/
/**
* Alters the display settings of pseudo-fields before an entity is displayed.
*
@@ -2358,6 +2424,8 @@ function hook_field_display_ENTITY_TYPE_alter(&$display, $context) {
* - entity_type: The entity type; e.g., 'node' or 'user'.
* - bundle: The bundle name.
* - view_mode: The view mode, e.g. 'full', 'teaser'...
*
* @ingroup field_types
*/
function hook_field_extra_fields_display_alter(&$displays, $context) {
if ($context['entity_type'] == 'taxonomy_term' && $context['view_mode'] == 'full') {
@@ -2387,6 +2455,8 @@ function hook_field_extra_fields_display_alter(&$displays, $context) {
* - instance: The instance of the field.
*
* @see hook_field_widget_properties_alter()
*
* @ingroup field_widget
*/
function hook_field_widget_properties_ENTITY_TYPE_alter(&$widget, $context) {
// Change a widget's type according to the time of day.
@@ -2397,10 +2467,6 @@ function hook_field_widget_properties_ENTITY_TYPE_alter(&$widget, $context) {
}
}
/**
* @} End of "addtogroup field_storage".
*/
/**
* @addtogroup field_crud
* @{
@@ -2508,7 +2574,7 @@ function hook_field_delete_field($field) {
*
* @param $instance
* The instance as it is post-update.
* @param $prior_$instance
* @param $prior_instance
* The instance as it was pre-update.
*/
function hook_field_update_instance($instance, $prior_instance) {
@@ -2596,6 +2662,8 @@ function hook_field_purge_instance($instance) {
*
* @param $field
* The field being purged.
*
* @ingroup field_storage
*/
function hook_field_storage_purge_field($field) {
$table_name = _field_sql_storage_tablename($field);
@@ -2613,6 +2681,8 @@ function hook_field_storage_purge_field($field) {
*
* @param $instance
* The instance being purged.
*
* @ingroup field_storage
*/
function hook_field_storage_purge_field_instance($instance) {
db_delete('my_module_field_instance_info')
@@ -2634,6 +2704,8 @@ function hook_field_storage_purge_field_instance($instance) {
* The (possibly deleted) field whose data is being purged.
* @param $instance
* The deleted field instance whose data is being purged.
*
* @ingroup field_storage
*/
function hook_field_storage_purge($entity_type, $entity, $field, $instance) {
list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
@@ -2673,6 +2745,8 @@ function hook_field_storage_purge($entity_type, $entity, $field, $instance) {
*
* @return
* TRUE if the operation is allowed, and FALSE if the operation is denied.
*
* @ingroup field_types
*/
function hook_field_access($op, $field, $entity_type, $entity, $account) {
if ($field['field_name'] == 'field_of_interest' && $op == 'edit') {
+7 -1
View File
@@ -318,7 +318,7 @@ function _field_invoke_multiple($op, $entity_type, $entities, &$a = NULL, &$b =
// Unless a language suggestion is provided we iterate on all the
// available languages.
$available_languages = field_available_languages($entity_type, $field);
$language = !empty($options['language'][$id]) ? $options['language'][$id] : $options['language'];
$language = is_array($options['language']) && !empty($options['language'][$id]) ? $options['language'][$id] : $options['language'];
$languages = _field_language_suggestion($available_languages, $language, $field_name);
foreach ($languages as $langcode) {
$grouped_items[$field_id][$langcode][$id] = isset($entity->{$field_name}[$langcode]) ? $entity->{$field_name}[$langcode] : array();
@@ -976,6 +976,12 @@ function field_attach_insert($entity_type, $entity) {
/**
* Save field data for an existing entity.
*
* When calling this function outside an entity save operation be sure to
* clear caches for the entity:
* @code
* entity_get_controller($entity_type)->resetCache(array($entity_id))
* @endcode
*
* @param $entity_type
* The type of $entity; e.g. 'node' or 'user'.
* @param $entity
+26 -11
View File
@@ -60,11 +60,11 @@ function field_create_field($field) {
}
// Field type is required.
if (empty($field['type'])) {
throw new FieldException('Attempt to create a field with no type.');
throw new FieldException(format_string('Attempt to create field @field_name with no type.', array('@field_name' => $field['field_name'])));
}
// Field name cannot contain invalid characters.
if (!preg_match('/^[_a-z]+[_a-z0-9]*$/', $field['field_name'])) {
throw new FieldException('Attempt to create a field with invalid characters. Only lowercase alphanumeric characters and underscores are allowed, and only lowercase letters and underscore are allowed as the first character');
throw new FieldException(format_string('Attempt to create a field @field_name with invalid characters. Only lowercase alphanumeric characters and underscores are allowed, and only lowercase letters and underscore are allowed as the first character', array('@field_name' => $field['field_name'])));
}
// Field name cannot be longer than 32 characters. We use drupal_strlen()
@@ -189,7 +189,7 @@ function field_create_field($field) {
}
// Clear caches
field_cache_clear(TRUE);
field_cache_clear();
// Invoke external hooks after the cache is cleared for API consistency.
module_invoke_all('field_create_field', $field);
@@ -244,9 +244,11 @@ function field_update_field($field) {
// $prior_field may no longer be right.
module_load_install($field['module']);
$schema = (array) module_invoke($field['module'], 'field_schema', $field);
$schema += array('columns' => array(), 'indexes' => array());
$schema += array('columns' => array(), 'indexes' => array(), 'foreign keys' => array());
// 'columns' are hardcoded in the field type.
$field['columns'] = $schema['columns'];
// 'foreign keys' are hardcoded in the field type.
$field['foreign keys'] = $schema['foreign keys'];
// 'indexes' can be both hardcoded in the field type, and specified in the
// incoming $field definition.
$field += array(
@@ -286,7 +288,7 @@ function field_update_field($field) {
drupal_write_record('field_config', $field, $primary_key);
// Clear caches
field_cache_clear(TRUE);
field_cache_clear();
// Invoke external hooks after the cache is cleared for API consistency.
module_invoke_all('field_update_field', $field, $prior_field, $has_data);
@@ -428,7 +430,7 @@ function field_delete_field($field_name) {
->execute();
// Clear the cache.
field_cache_clear(TRUE);
field_cache_clear();
module_invoke_all('field_delete_field', $field);
}
@@ -522,17 +524,30 @@ function field_create_instance($instance) {
* Updates an instance of a field.
*
* @param $instance
* An associative array representing an instance structure. The required
* keys and values are:
* An associative array representing an instance structure. The following
* required array elements specify which field instance is being updated:
* - entity_type: The type of the entity the field is attached to.
* - bundle: The bundle this field belongs to.
* - field_name: The name of an existing field.
* Read-only_id properties are assigned automatically. Any other
* properties specified in $instance overwrite the existing values for
* the instance.
* The other array elements represent properties of the instance, and all
* properties must be specified or their default values will be used (except
* internal-use properties, which are assigned automatically). To avoid
* losing the previously stored properties of the instance when making a
* change, first load the instance with field_info_instance(), then override
* the values you want to override, and finally save using this function.
* Example:
* @code
* // Fetch an instance info array.
* $instance_info = field_info_instance($entity_type, $field_name, $bundle_name);
* // Change a single property in the instance definition.
* $instance_info['required'] = TRUE;
* // Write the changed definition back.
* field_update_instance($instance_info);
* @endcode
*
* @throws FieldException
*
* @see field_info_instance()
* @see field_create_instance()
*/
function field_update_instance($instance) {
+3 -4
View File
@@ -11,8 +11,7 @@ dependencies[] = field_sql_storage
required = TRUE
stylesheets[all][] = theme/field.css
; Information added by drupal.org packaging script on 2013-04-03
version = "7.22"
; Information added by Drupal.org packaging script on 2020-09-16
version = "7.73"
project = "drupal"
datestamp = "1365027012"
datestamp = "1600272641"
+24 -6
View File
@@ -146,7 +146,10 @@ class FieldInfo {
// Save in "static" and persistent caches.
$this->fieldMap = $map;
cache_set('field_info:field_map', $map, 'cache_field');
if (lock_acquire('field_info:field_map')) {
cache_set('field_info:field_map', $map, 'cache_field');
lock_release('field_info:field_map');
}
return $map;
}
@@ -174,7 +177,10 @@ class FieldInfo {
}
// Store in persistent cache.
cache_set('field_info:fields', $this->fieldsById, 'cache_field');
if (lock_acquire('field_info:fields')) {
cache_set('field_info:fields', $this->fieldsById, 'cache_field');
lock_release('field_info:fields');
}
}
// Fill the name/ID map.
@@ -231,7 +237,10 @@ class FieldInfo {
}
// Store in persistent cache.
cache_set('field_info:instances', $this->bundleInstances, 'cache_field');
if (lock_acquire('field_info:instances')) {
cache_set('field_info:instances', $this->bundleInstances, 'cache_field');
lock_release('field_info:instances');
}
}
$this->loadedAllInstances = TRUE;
@@ -419,7 +428,11 @@ class FieldInfo {
foreach ($instances as $instance) {
$cache['fields'][] = $this->fieldsById[$instance['field_id']];
}
cache_set("field_info:bundle:$entity_type:$bundle", $cache, 'cache_field');
if (lock_acquire("field_info:bundle:$entity_type:$bundle")) {
cache_set("field_info:bundle:$entity_type:$bundle", $cache, 'cache_field');
lock_release("field_info:bundle:$entity_type:$bundle");
}
return $instances;
}
@@ -460,7 +473,10 @@ class FieldInfo {
// Store in the 'static' and persistent caches.
$this->bundleExtraFields[$entity_type][$bundle] = $info;
cache_set("field_info:bundle_extra:$entity_type:$bundle", $info, 'cache_field');
if (lock_acquire("field_info:bundle_extra:$entity_type:$bundle")) {
cache_set("field_info:bundle_extra:$entity_type:$bundle", $info, 'cache_field');
lock_release("field_info:bundle_extra:$entity_type:$bundle");
}
return $this->bundleExtraFields[$entity_type][$bundle];
}
@@ -596,10 +612,12 @@ class FieldInfo {
// Fill in default values.
$display += array(
'label' => 'above',
'type' => $field_type_info['default_formatter'],
'settings' => array(),
'weight' => 0,
);
if (empty($display['type'])) {
$display['type'] = $field_type_info['default_formatter'];
}
if ($display['type'] != 'hidden') {
$formatter_type_info = field_info_formatter_types($display['type']);
// Fall back to default formatter if formatter type is not available.
+16 -1
View File
@@ -223,7 +223,11 @@ function _field_info_collate_types($reset = FALSE) {
}
drupal_alter('field_storage_info', $info['storage types']);
cache_set("field_info_types:$langcode", $info, 'cache_field');
// Set the cache if we can acquire a lock.
if (lock_acquire("field_info_types:$langcode")) {
cache_set("field_info_types:$langcode", $info, 'cache_field');
lock_release("field_info_types:$langcode");
}
}
}
@@ -449,6 +453,17 @@ function field_info_bundles($entity_type = NULL) {
* - type: The field type.
* - bundles: The bundles in which the field appears, as an array with entity
* types as keys and the array of bundle names as values.
* Example:
* @code
* array(
* 'body' => array(
* 'bundles' => array(
* 'node' => array('page', 'article'),
* ),
* 'type' => 'text_with_summary',
* ),
* );
* @endcode
*/
function field_info_field_map() {
$cache = _field_info_field_cache();
+23 -1
View File
@@ -128,7 +128,7 @@ function field_schema() {
'not null' => TRUE,
'default' => ''
),
'entity_type' => array(
'entity_type' => array(
'type' => 'varchar',
'length' => 32,
'not null' => TRUE,
@@ -162,6 +162,7 @@ function field_schema() {
),
);
$schema['cache_field'] = drupal_get_schema_unprocessed('system', 'cache');
$schema['cache_field']['description'] = 'Cache table for the Field module to store already built field information.';
return $schema;
}
@@ -466,6 +467,27 @@ function field_update_7003() {
// Empty update to force a rebuild of the registry.
}
/**
* Grant the new "administer fields" permission to trusted users.
*/
function field_update_7004() {
// Assign the permission to anyone that already has a trusted core permission
// that would have previously let them administer fields on an entity type.
$rids = array();
$permissions = array(
'administer site configuration',
'administer content types',
'administer users',
);
foreach ($permissions as $permission) {
$rids = array_merge($rids, array_keys(user_roles(FALSE, $permission)));
}
$rids = array_unique($rids);
foreach ($rids as $rid) {
_update_7000_user_role_grant_permissions($rid, array('administer fields'), 'field');
}
}
/**
* @} End of "addtogroup updates-7.x-extra".
*/
+31 -16
View File
@@ -316,6 +316,21 @@ function field_help($path, $arg) {
}
}
/**
* Implements hook_permission().
*/
function field_permission() {
return array(
'administer fields' => array(
'title' => t('Administer fields'),
'description' => t('Additional permissions are required based on what the fields are attached to (for example, <a href="@url">administer content types</a> to manage fields attached to content).', array(
'@url' => '#module-node',
)),
'restrict access' => TRUE,
),
);
}
/**
* Implements hook_theme().
*/
@@ -342,17 +357,6 @@ function field_cron() {
field_purge_batch($limit);
}
/**
* Implements hook_modules_uninstalled().
*/
function field_modules_uninstalled($modules) {
module_load_include('inc', 'field', 'field.crud');
foreach ($modules as $module) {
// TODO D7: field_module_delete is not yet implemented
// field_module_delete($module);
}
}
/**
* Implements hook_system_info_alter().
*
@@ -819,9 +823,9 @@ function field_view_value($entity_type, $entity, $field_name, $item, $display =
*
* This function can be used by third-party modules that need to output an
* isolated field.
* - Do not use inside node (or other entities) templates, use
* - Do not use inside node (or any other entity) templates; use
* render($content[FIELD_NAME]) instead.
* - Do not use to display all fields in an entity, use
* - Do not use to display all fields in an entity; use
* field_attach_prepare_view() and field_attach_view() instead.
* - The field_view_value() function can be used to output a single formatted
* field value, without label or wrapping field markup.
@@ -905,6 +909,7 @@ function field_view_field($entity_type, $entity, $field_name, $display = array()
'entity' => $entity,
'view_mode' => '_custom',
'display' => $display,
'language' => $langcode,
);
drupal_alter('field_attach_view', $result, $context);
@@ -947,20 +952,30 @@ function field_get_items($entity_type, $entity, $field_name, $langcode = NULL) {
*/
function field_has_data($field) {
$query = new EntityFieldQuery();
return (bool) $query
->fieldCondition($field)
$query = $query->fieldCondition($field)
->range(0, 1)
->count()
// Neutralize the 'entity_field_access' query tag added by
// field_sql_storage_field_storage_query(). The result cannot depend on the
// access grants of the current user.
->addTag('DANGEROUS_ACCESS_CHECK_OPT_OUT')
->addTag('DANGEROUS_ACCESS_CHECK_OPT_OUT');
return (bool) $query
->execute() || (bool) $query
->age(FIELD_LOAD_REVISION)
->execute();
}
/**
* Determine whether the user has access to a given field.
*
* This function does not determine whether access is granted to the entity
* itself, only the specific field. Callers are responsible for ensuring that
* entity access is also respected. For example, when checking field access for
* nodes, check node_access() before checking field_access(), and when checking
* field access for entities using the Entity API contributed module,
* check entity_access() before checking field_access().
*
* @param $op
* The operation to be performed. Possible values:
* - 'edit'
@@ -7,8 +7,7 @@ dependencies[] = field
files[] = field_sql_storage.test
required = TRUE
; Information added by drupal.org packaging script on 2013-04-03
version = "7.22"
; Information added by Drupal.org packaging script on 2020-09-16
version = "7.73"
project = "drupal"
datestamp = "1365027012"
datestamp = "1600272641"
@@ -64,6 +64,49 @@ function _field_sql_storage_revision_tablename($field) {
}
}
/**
* Generates a table alias for a field data table.
*
* The table alias is unique for each unique combination of field name
* (represented by $tablename), delta_group and language_group.
*
* @param $tablename
* The name of the data table for this field.
* @param $field_key
* The numeric key of this field in this query.
* @param $query
* The EntityFieldQuery that is executed.
*
* @return
* A string containing the generated table alias.
*/
function _field_sql_storage_tablealias($tablename, $field_key, EntityFieldQuery $query) {
// No conditions present: use a unique alias.
if (empty($query->fieldConditions[$field_key])) {
return $tablename . $field_key;
}
// Find the delta and language condition values and append them to the alias.
$condition = $query->fieldConditions[$field_key];
$alias = $tablename;
$has_group_conditions = FALSE;
foreach (array('delta', 'language') as $column) {
if (isset($condition[$column . '_group'])) {
$alias .= '_' . $column . '_' . $condition[$column . '_group'];
$has_group_conditions = TRUE;
}
}
// Return the alias when it has delta/language group conditions.
if ($has_group_conditions) {
return $alias;
}
// Return a unique alias in other cases.
return $tablename . $field_key;
}
/**
* Generate a column name for a field data table.
*
@@ -180,7 +223,17 @@ function _field_sql_storage_schema($field) {
foreach ($field['indexes'] as $index_name => $columns) {
$real_name = _field_sql_storage_indexname($field['field_name'], $index_name);
foreach ($columns as $column_name) {
$current['indexes'][$real_name][] = _field_sql_storage_columnname($field['field_name'], $column_name);
// Indexes can be specified as either a column name or an array with
// column name and length. Allow for either case.
if (is_array($column_name)) {
$current['indexes'][$real_name][] = array(
_field_sql_storage_columnname($field['field_name'], $column_name[0]),
$column_name[1],
);
}
else {
$current['indexes'][$real_name][] = _field_sql_storage_columnname($field['field_name'], $column_name);
}
}
}
@@ -188,7 +241,7 @@ function _field_sql_storage_schema($field) {
foreach ($field['foreign keys'] as $specifier => $specification) {
$real_name = _field_sql_storage_indexname($field['field_name'], $specifier);
$current['foreign keys'][$real_name]['table'] = $specification['table'];
foreach ($specification['columns'] as $column => $referenced) {
foreach ($specification['columns'] as $column_name => $referenced) {
$sql_storage_column = _field_sql_storage_columnname($field['field_name'], $column_name);
$current['foreign keys'][$real_name]['columns'][$sql_storage_column] = $referenced;
}
@@ -289,7 +342,17 @@ function field_sql_storage_field_storage_update_field($field, $prior_field, $has
$real_name = _field_sql_storage_indexname($field['field_name'], $name);
$real_columns = array();
foreach ($columns as $column_name) {
$real_columns[] = _field_sql_storage_columnname($field['field_name'], $column_name);
// Indexes can be specified as either a column name or an array with
// column name and length. Allow for either case.
if (is_array($column_name)) {
$real_columns[] = array(
_field_sql_storage_columnname($field['field_name'], $column_name[0]),
$column_name[1],
);
}
else {
$real_columns[] = _field_sql_storage_columnname($field['field_name'], $column_name);
}
}
db_add_index($table, $real_name, $real_columns);
db_add_index($revision_table, $real_name, $real_columns);
@@ -422,7 +485,7 @@ function field_sql_storage_field_storage_write($entity_type, $entity, $op, $fiel
$items = (array) $entity->{$field_name}[$langcode];
$delta_count = 0;
foreach ($items as $delta => $item) {
// We now know we have someting to insert.
// We now know we have something to insert.
$do_insert = TRUE;
$record = array(
'entity_type' => $entity_type,
@@ -504,17 +567,21 @@ function field_sql_storage_field_storage_query(EntityFieldQuery $query) {
$id_key = 'revision_id';
}
$table_aliases = array();
$query_tables = NULL;
// Add tables for the fields used.
foreach ($query->fields as $key => $field) {
$tablename = $tablename_function($field);
// Every field needs a new table.
$table_alias = $tablename . $key;
$table_alias = _field_sql_storage_tablealias($tablename, $key, $query);
$table_aliases[$key] = $table_alias;
if ($key) {
$select_query->join($tablename, $table_alias, "$table_alias.entity_type = $field_base_table.entity_type AND $table_alias.$id_key = $field_base_table.$id_key");
if (!isset($query_tables[$table_alias])) {
$select_query->join($tablename, $table_alias, "$table_alias.entity_type = $field_base_table.entity_type AND $table_alias.$id_key = $field_base_table.$id_key");
}
}
else {
$select_query = db_select($tablename, $table_alias);
// Store a reference to the list of joined tables.
$query_tables =& $select_query->getTables();
// Allow queries internal to the Field API to opt out of the access
// check, for situations where the query's results should not depend on
// the access grants for the current user.
@@ -126,7 +126,7 @@ class FieldSqlStorageTestCase extends DrupalWebTestCase {
$rows = db_select($this->table, 't')->fields('t')->execute()->fetchAllAssoc('delta', PDO::FETCH_ASSOC);
foreach ($values as $delta => $value) {
if ($delta < $this->field['cardinality']) {
$this->assertEqual($rows[$delta][$this->field_name . '_value'], $value['value'], t("Value $delta is inserted correctly"));
$this->assertEqual($rows[$delta][$this->field_name . '_value'], $value['value'], format_string("Value %delta is inserted correctly", array('%delta' => $delta)));
}
else {
$this->assertFalse(array_key_exists($delta, $rows), "No extraneous value gets inserted.");
@@ -145,7 +145,7 @@ class FieldSqlStorageTestCase extends DrupalWebTestCase {
$rows = db_select($this->table, 't')->fields('t')->execute()->fetchAllAssoc('delta', PDO::FETCH_ASSOC);
foreach ($values as $delta => $value) {
if ($delta < $this->field['cardinality']) {
$this->assertEqual($rows[$delta][$this->field_name . '_value'], $value['value'], t("Value $delta is updated correctly"));
$this->assertEqual($rows[$delta][$this->field_name . '_value'], $value['value'], format_string("Value %delta is updated correctly", array('%delta' => $delta)));
}
else {
$this->assertFalse(array_key_exists($delta, $rows), "No extraneous value gets updated.");
@@ -175,7 +175,7 @@ class FieldSqlStorageTestCase extends DrupalWebTestCase {
$rows = db_select($this->table, 't')->fields('t')->execute()->fetchAllAssoc('delta', PDO::FETCH_ASSOC);
foreach ($values as $delta => $value) {
if ($delta < $this->field['cardinality']) {
$this->assertEqual($rows[$delta][$this->field_name . '_value'], $value['value'], t("Update with no field_name entry leaves value $delta untouched"));
$this->assertEqual($rows[$delta][$this->field_name . '_value'], $value['value'], format_string("Update with no field_name entry leaves value %delta untouched", array('%delta' => $delta)));
}
}
@@ -183,7 +183,7 @@ class FieldSqlStorageTestCase extends DrupalWebTestCase {
$entity->{$this->field_name} = NULL;
field_attach_update($entity_type, $entity);
$rows = db_select($this->table, 't')->fields('t')->execute()->fetchAllAssoc('delta', PDO::FETCH_ASSOC);
$this->assertEqual(count($rows), 0, t("Update with an empty field_name entry empties the field."));
$this->assertEqual(count($rows), 0, "Update with an empty field_name entry empties the field.");
}
/**
@@ -326,7 +326,7 @@ class FieldSqlStorageTestCase extends DrupalWebTestCase {
// Ensure that the field tables are still there.
foreach (_field_sql_storage_schema($prior_field) as $table_name => $table_info) {
$this->assertTrue(db_table_exists($table_name), t('Table %table exists.', array('%table' => $table_name)));
$this->assertTrue(db_table_exists($table_name), format_string('Table %table exists.', array('%table' => $table_name)));
}
}
@@ -345,8 +345,8 @@ class FieldSqlStorageTestCase extends DrupalWebTestCase {
// Verify the indexes we will create do not exist yet.
foreach ($tables as $table) {
$this->assertFalse(Database::getConnection()->schema()->indexExists($table, 'value'), t("No index named value exists in $table"));
$this->assertFalse(Database::getConnection()->schema()->indexExists($table, 'value_format'), t("No index named value_format exists in $table"));
$this->assertFalse(Database::getConnection()->schema()->indexExists($table, 'value'), format_string("No index named value exists in %table", array('%table' => $table)));
$this->assertFalse(Database::getConnection()->schema()->indexExists($table, 'value_format'), format_string("No index named value_format exists in %table", array('%table' => $table)));
}
// Add data so the table cannot be dropped.
@@ -355,24 +355,24 @@ class FieldSqlStorageTestCase extends DrupalWebTestCase {
field_attach_insert('test_entity', $entity);
// Add an index
$field = array('field_name' => $field_name, 'indexes' => array('value' => array('value')));
$field = array('field_name' => $field_name, 'indexes' => array('value' => array(array('value', 255))));
field_update_field($field);
foreach ($tables as $table) {
$this->assertTrue(Database::getConnection()->schema()->indexExists($table, "{$field_name}_value"), t("Index on value created in $table"));
$this->assertTrue(Database::getConnection()->schema()->indexExists($table, "{$field_name}_value"), format_string("Index on value created in %table", array('%table' => $table)));
}
// Add a different index, removing the existing custom one.
$field = array('field_name' => $field_name, 'indexes' => array('value_format' => array('value', 'format')));
$field = array('field_name' => $field_name, 'indexes' => array('value_format' => array(array('value', 127), array('format', 127))));
field_update_field($field);
foreach ($tables as $table) {
$this->assertTrue(Database::getConnection()->schema()->indexExists($table, "{$field_name}_value_format"), t("Index on value_format created in $table"));
$this->assertFalse(Database::getConnection()->schema()->indexExists($table, "{$field_name}_value"), t("Index on value removed in $table"));
$this->assertTrue(Database::getConnection()->schema()->indexExists($table, "{$field_name}_value_format"), format_string("Index on value_format created in %table", array('%table' => $table)));
$this->assertFalse(Database::getConnection()->schema()->indexExists($table, "{$field_name}_value"), format_string("Index on value removed in %table", array('%table' => $table)));
}
// Verify that the tables were not dropped.
$entity = field_test_create_stub_entity(0, 0, $instance['bundle']);
field_attach_load('test_entity', array(0 => $entity));
$this->assertEqual($entity->{$field_name}[LANGUAGE_NONE][0]['value'], 'field data', t("Index changes performed without dropping the tables"));
$this->assertEqual($entity->{$field_name}[LANGUAGE_NONE][0]['value'], 'field data', "Index changes performed without dropping the tables");
}
/**
@@ -387,19 +387,19 @@ class FieldSqlStorageTestCase extends DrupalWebTestCase {
$instance = field_info_instance($this->instance['entity_type'], $this->instance['field_name'], $this->instance['bundle']);
// The storage details are indexed by a storage engine type.
$this->assertTrue(array_key_exists('sql', $field['storage']['details']), t('The storage type is SQL.'));
$this->assertTrue(array_key_exists('sql', $field['storage']['details']), 'The storage type is SQL.');
// The SQL details are indexed by table name.
$details = $field['storage']['details']['sql'];
$this->assertTrue(array_key_exists($current, $details[FIELD_LOAD_CURRENT]), t('Table name is available in the instance array.'));
$this->assertTrue(array_key_exists($revision, $details[FIELD_LOAD_REVISION]), t('Revision table name is available in the instance array.'));
$this->assertTrue(array_key_exists($current, $details[FIELD_LOAD_CURRENT]), 'Table name is available in the instance array.');
$this->assertTrue(array_key_exists($revision, $details[FIELD_LOAD_REVISION]), 'Revision table name is available in the instance array.');
// Test current and revision storage details together because the columns
// are the same.
foreach ((array) $this->field['columns'] as $column_name => $attributes) {
$storage_column_name = _field_sql_storage_columnname($this->field['field_name'], $column_name);
$this->assertEqual($details[FIELD_LOAD_CURRENT][$current][$column_name], $storage_column_name, t('Column name %value matches the definition in %bin.', array('%value' => $column_name, '%bin' => $current)));
$this->assertEqual($details[FIELD_LOAD_REVISION][$revision][$column_name], $storage_column_name, t('Column name %value matches the definition in %bin.', array('%value' => $column_name, '%bin' => $revision)));
$this->assertEqual($details[FIELD_LOAD_CURRENT][$current][$column_name], $storage_column_name, format_string('Column name %value matches the definition in %bin.', array('%value' => $column_name, '%bin' => $current)));
$this->assertEqual($details[FIELD_LOAD_REVISION][$revision][$column_name], $storage_column_name, format_string('Column name %value matches the definition in %bin.', array('%value' => $column_name, '%bin' => $revision)));
}
}
@@ -407,21 +407,180 @@ class FieldSqlStorageTestCase extends DrupalWebTestCase {
* Test foreign key support.
*/
function testFieldSqlStorageForeignKeys() {
// Create a decimal field.
// Create a 'shape' field, with a configurable foreign key (see
// field_test_field_schema()).
$field_name = 'testfield';
$field = array('field_name' => $field_name, 'type' => 'text');
$field = field_create_field($field);
// Retrieve the field and instance with field_info and verify the foreign
// keys are in place.
$foreign_key_name = 'shape';
$field = array('field_name' => $field_name, 'type' => 'shape', 'settings' => array('foreign_key_name' => $foreign_key_name));
field_create_field($field);
// Retrieve the field definition and check that the foreign key is in place.
$field = field_info_field($field_name);
$this->assertEqual($field['foreign keys']['format']['table'], 'filter_format', t('Foreign key table name preserved through CRUD'));
$this->assertEqual($field['foreign keys']['format']['columns']['format'], 'format', t('Foreign key column name preserved through CRUD'));
$this->assertEqual($field['foreign keys'][$foreign_key_name]['table'], $foreign_key_name, 'Foreign key table name preserved through CRUD');
$this->assertEqual($field['foreign keys'][$foreign_key_name]['columns'][$foreign_key_name], 'id', 'Foreign key column name preserved through CRUD');
// Update the field settings, it should update the foreign key definition
// too.
$foreign_key_name = 'color';
$field['settings']['foreign_key_name'] = $foreign_key_name;
field_update_field($field);
// Retrieve the field definition and check that the foreign key is in place.
$field = field_info_field($field_name);
$this->assertEqual($field['foreign keys'][$foreign_key_name]['table'], $foreign_key_name, 'Foreign key table name modified after update');
$this->assertEqual($field['foreign keys'][$foreign_key_name]['columns'][$foreign_key_name], 'id', 'Foreign key column name modified after update');
// Now grab the SQL schema and verify that too.
$schema = drupal_get_schema(_field_sql_storage_tablename($field));
$this->assertEqual(count($schema['foreign keys']), 1, t("There is 1 foreign key in the schema"));
$schema = drupal_get_schema(_field_sql_storage_tablename($field), TRUE);
$this->assertEqual(count($schema['foreign keys']), 1, 'There is 1 foreign key in the schema');
$foreign_key = reset($schema['foreign keys']);
$filter_column = _field_sql_storage_columnname($field['field_name'], 'format');
$this->assertEqual($foreign_key['table'], 'filter_format', t('Foreign key table name preserved in the schema'));
$this->assertEqual($foreign_key['columns'][$filter_column], 'format', t('Foreign key column name preserved in the schema'));
$foreign_key_column = _field_sql_storage_columnname($field['field_name'], $foreign_key_name);
$this->assertEqual($foreign_key['table'], $foreign_key_name, 'Foreign key table name preserved in the schema');
$this->assertEqual($foreign_key['columns'][$foreign_key_column], 'id', 'Foreign key column name preserved in the schema');
}
/**
* Test handling multiple conditions on one column of a field.
*
* Tests both the result and the complexity of the query.
*/
function testFieldSqlStorageMultipleConditionsSameColumn() {
$entity = field_test_create_stub_entity(NULL, NULL);
$entity->{$this->field_name}[LANGUAGE_NONE][0] = array('value' => 1);
field_test_entity_save($entity);
$entity = field_test_create_stub_entity(NULL, NULL);
$entity->{$this->field_name}[LANGUAGE_NONE][0] = array('value' => 2);
field_test_entity_save($entity);
$entity = field_test_create_stub_entity(NULL, NULL);
$entity->{$this->field_name}[LANGUAGE_NONE][0] = array('value' => 3);
field_test_entity_save($entity);
$query = new EntityFieldQuery();
// This tag causes field_test_query_store_global_test_query_alter() to be
// invoked so that the query can be tested.
$query->addTag('store_global_test_query');
$query->entityCondition('entity_type', 'test_entity');
$query->entityCondition('bundle', 'test_bundle');
$query->fieldCondition($this->field_name, 'value', 1, '<>', 0, LANGUAGE_NONE);
$query->fieldCondition($this->field_name, 'value', 2, '<>', 0, LANGUAGE_NONE);
$result = field_sql_storage_field_storage_query($query);
// Test the results.
$this->assertEqual(1, count($result), format_string('One result should be returned, got @count', array('@count' => count($result))));
// Test the complexity of the query.
$query = $GLOBALS['test_query'];
$this->assertNotNull($query, 'Precondition: the query should be available');
$tables = $query->getTables();
$this->assertEqual(1, count($tables), 'The query contains just one table.');
// Clean up.
unset($GLOBALS['test_query']);
}
/**
* Test handling multiple conditions on multiple columns of one field.
*
* Tests both the result and the complexity of the query.
*/
function testFieldSqlStorageMultipleConditionsDifferentColumns() {
// Create the multi-column shape field
$field_name = strtolower($this->randomName());
$field = array('field_name' => $field_name, 'type' => 'shape', 'cardinality' => 4);
$field = field_create_field($field);
$instance = array(
'field_name' => $field_name,
'entity_type' => 'test_entity',
'bundle' => 'test_bundle'
);
$instance = field_create_instance($instance);
$entity = field_test_create_stub_entity(NULL, NULL);
$entity->{$field_name}[LANGUAGE_NONE][0] = array('shape' => 'A', 'color' => 'X');
field_test_entity_save($entity);
$entity = field_test_create_stub_entity(NULL, NULL);
$entity->{$field_name}[LANGUAGE_NONE][0] = array('shape' => 'B', 'color' => 'X');
field_test_entity_save($entity);
$entity = field_test_create_stub_entity(NULL, NULL);
$entity->{$field_name}[LANGUAGE_NONE][0] = array('shape' => 'A', 'color' => 'Y');
field_test_entity_save($entity);
$query = new EntityFieldQuery();
// This tag causes field_test_query_store_global_test_query_alter() to be
// invoked so that the query can be tested.
$query->addTag('store_global_test_query');
$query->entityCondition('entity_type', 'test_entity');
$query->entityCondition('bundle', 'test_bundle');
$query->fieldCondition($field_name, 'shape', 'B', '=', 'something', LANGUAGE_NONE);
$query->fieldCondition($field_name, 'color', 'X', '=', 'something', LANGUAGE_NONE);
$result = field_sql_storage_field_storage_query($query);
// Test the results.
$this->assertEqual(1, count($result), format_string('One result should be returned, got @count', array('@count' => count($result))));
// Test the complexity of the query.
$query = $GLOBALS['test_query'];
$this->assertNotNull($query, 'Precondition: the query should be available');
$tables = $query->getTables();
$this->assertEqual(1, count($tables), 'The query contains just one table.');
// Clean up.
unset($GLOBALS['test_query']);
}
/**
* Test handling multiple conditions on multiple columns of one field for multiple languages.
*
* Tests both the result and the complexity of the query.
*/
function testFieldSqlStorageMultipleConditionsDifferentColumnsMultipleLanguages() {
field_test_entity_info_translatable('test_entity', TRUE);
// Create the multi-column shape field
$field_name = strtolower($this->randomName());
$field = array('field_name' => $field_name, 'type' => 'shape', 'cardinality' => 4, 'translatable' => TRUE);
$field = field_create_field($field);
$instance = array(
'field_name' => $field_name,
'entity_type' => 'test_entity',
'bundle' => 'test_bundle',
'settings' => array(
// Prevent warning from field_test_field_load().
'test_hook_field_load' => FALSE,
),
);
$instance = field_create_instance($instance);
$entity = field_test_create_stub_entity(NULL, NULL);
$entity->{$field_name}[LANGUAGE_NONE][0] = array('shape' => 'A', 'color' => 'X');
$entity->{$field_name}['en'][0] = array('shape' => 'B', 'color' => 'Y');
field_test_entity_save($entity);
$entity = field_test_entity_test_load($entity->ftid);
$query = new EntityFieldQuery();
// This tag causes field_test_query_store_global_test_query_alter() to be
// invoked so that the query can be tested.
$query->addTag('store_global_test_query');
$query->entityCondition('entity_type', 'test_entity');
$query->entityCondition('bundle', 'test_bundle');
$query->fieldCondition($field_name, 'color', 'X', '=', NULL, LANGUAGE_NONE);
$query->fieldCondition($field_name, 'shape', 'B', '=', NULL, 'en');
$result = field_sql_storage_field_storage_query($query);
// Test the results.
$this->assertEqual(1, count($result), format_string('One result should be returned, got @count', array('@count' => count($result))));
// Test the complexity of the query.
$query = $GLOBALS['test_query'];
$this->assertNotNull($query, 'Precondition: the query should be available');
$tables = $query->getTables();
$this->assertEqual(2, count($tables), 'The query contains two tables.');
// Clean up.
unset($GLOBALS['test_query']);
}
}
+3 -4
View File
@@ -7,8 +7,7 @@ dependencies[] = field
dependencies[] = options
files[] = tests/list.test
; Information added by drupal.org packaging script on 2013-04-03
version = "7.22"
; Information added by Drupal.org packaging script on 2020-09-16
version = "7.73"
project = "drupal"
datestamp = "1365027012"
datestamp = "1600272641"
+8 -1
View File
@@ -61,7 +61,7 @@ function list_update_7001() {
// Additionally, float keys need to be disambiguated ('.5' is '0.5').
if ($field['type'] == 'list_number' && !empty($allowed_values)) {
$keys = array_map(create_function('$a', 'return (string) (float) $a;'), array_keys($allowed_values));
$keys = array_map('_list_update_7001_float_string_cast', array_keys($allowed_values));
$allowed_values = array_combine($keys, array_values($allowed_values));
}
@@ -88,6 +88,13 @@ function list_update_7001() {
}
}
/**
* Helper callback function to cast the array element.
*/
function _list_update_7001_float_string_cast($element) {
return (string) (float) $element;
}
/**
* Helper function for list_update_7001: extract allowed values from a string.
*
+52 -52
View File
@@ -51,9 +51,9 @@ class ListFieldTestCase extends FieldTestCase {
// All three options appear.
$entity = field_test_create_stub_entity();
$form = drupal_get_form('field_test_entity_form', $entity);
$this->assertTrue(!empty($form[$this->field_name][$langcode][1]), t('Option 1 exists'));
$this->assertTrue(!empty($form[$this->field_name][$langcode][2]), t('Option 2 exists'));
$this->assertTrue(!empty($form[$this->field_name][$langcode][3]), t('Option 3 exists'));
$this->assertTrue(!empty($form[$this->field_name][$langcode][1]), 'Option 1 exists');
$this->assertTrue(!empty($form[$this->field_name][$langcode][2]), 'Option 2 exists');
$this->assertTrue(!empty($form[$this->field_name][$langcode][3]), 'Option 3 exists');
// Use one of the values in an actual entity, and check that this value
// cannot be removed from the list.
@@ -77,19 +77,19 @@ class ListFieldTestCase extends FieldTestCase {
field_update_field($this->field);
$entity = field_test_create_stub_entity();
$form = drupal_get_form('field_test_entity_form', $entity);
$this->assertTrue(empty($form[$this->field_name][$langcode][1]), t('Option 1 does not exist'));
$this->assertTrue(!empty($form[$this->field_name][$langcode][2]), t('Option 2 exists'));
$this->assertTrue(empty($form[$this->field_name][$langcode][3]), t('Option 3 does not exist'));
$this->assertTrue(empty($form[$this->field_name][$langcode][1]), 'Option 1 does not exist');
$this->assertTrue(!empty($form[$this->field_name][$langcode][2]), 'Option 2 exists');
$this->assertTrue(empty($form[$this->field_name][$langcode][3]), 'Option 3 does not exist');
// Completely new options appear.
$this->field['settings']['allowed_values'] = array(10 => 'Update', 20 => 'Twenty');
field_update_field($this->field);
$form = drupal_get_form('field_test_entity_form', $entity);
$this->assertTrue(empty($form[$this->field_name][$langcode][1]), t('Option 1 does not exist'));
$this->assertTrue(empty($form[$this->field_name][$langcode][2]), t('Option 2 does not exist'));
$this->assertTrue(empty($form[$this->field_name][$langcode][3]), t('Option 3 does not exist'));
$this->assertTrue(!empty($form[$this->field_name][$langcode][10]), t('Option 10 exists'));
$this->assertTrue(!empty($form[$this->field_name][$langcode][20]), t('Option 20 exists'));
$this->assertTrue(empty($form[$this->field_name][$langcode][1]), 'Option 1 does not exist');
$this->assertTrue(empty($form[$this->field_name][$langcode][2]), 'Option 2 does not exist');
$this->assertTrue(empty($form[$this->field_name][$langcode][3]), 'Option 3 does not exist');
$this->assertTrue(!empty($form[$this->field_name][$langcode][10]), 'Option 10 exists');
$this->assertTrue(!empty($form[$this->field_name][$langcode][20]), 'Option 20 exists');
// Options are reset when a new field with the same name is created.
field_delete_field($this->field_name);
@@ -107,9 +107,9 @@ class ListFieldTestCase extends FieldTestCase {
$this->instance = field_create_instance($this->instance);
$entity = field_test_create_stub_entity();
$form = drupal_get_form('field_test_entity_form', $entity);
$this->assertTrue(!empty($form[$this->field_name][$langcode][1]), t('Option 1 exists'));
$this->assertTrue(!empty($form[$this->field_name][$langcode][2]), t('Option 2 exists'));
$this->assertTrue(!empty($form[$this->field_name][$langcode][3]), t('Option 3 exists'));
$this->assertTrue(!empty($form[$this->field_name][$langcode][1]), 'Option 1 exists');
$this->assertTrue(!empty($form[$this->field_name][$langcode][2]), 'Option 2 exists');
$this->assertTrue(!empty($form[$this->field_name][$langcode][3]), 'Option 3 exists');
}
}
@@ -212,7 +212,7 @@ class ListFieldUITestCase extends FieldTestCase {
parent::setUp('field_test', 'field_ui');
// Create test user.
$admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer taxonomy'));
$admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer taxonomy', 'administer fields'));
$this->drupalLogin($admin_user);
// Create content type, with underscores.
@@ -233,20 +233,20 @@ class ListFieldUITestCase extends FieldTestCase {
// Flat list of textual values.
$string = "Zero\nOne";
$array = array('0' => 'Zero', '1' => 'One');
$this->assertAllowedValuesInput($string, $array, t('Unkeyed lists are accepted.'));
$this->assertAllowedValuesInput($string, $array, 'Unkeyed lists are accepted.');
// Explicit integer keys.
$string = "0|Zero\n2|Two";
$array = array('0' => 'Zero', '2' => 'Two');
$this->assertAllowedValuesInput($string, $array, t('Integer keys are accepted.'));
$this->assertAllowedValuesInput($string, $array, 'Integer keys are accepted.');
// Check that values can be added and removed.
$string = "0|Zero\n1|One";
$array = array('0' => 'Zero', '1' => 'One');
$this->assertAllowedValuesInput($string, $array, t('Values can be added and removed.'));
$this->assertAllowedValuesInput($string, $array, 'Values can be added and removed.');
// Non-integer keys.
$this->assertAllowedValuesInput("1.1|One", 'keys must be integers', t('Non integer keys are rejected.'));
$this->assertAllowedValuesInput("abc|abc", 'keys must be integers', t('Non integer keys are rejected.'));
$this->assertAllowedValuesInput("1.1|One", 'keys must be integers', 'Non integer keys are rejected.');
$this->assertAllowedValuesInput("abc|abc", 'keys must be integers', 'Non integer keys are rejected.');
// Mixed list of keyed and unkeyed values.
$this->assertAllowedValuesInput("Zero\n1|One", 'invalid input', t('Mixed lists are rejected.'));
$this->assertAllowedValuesInput("Zero\n1|One", 'invalid input', 'Mixed lists are rejected.');
// Create a node with actual data for the field.
$settings = array(
@@ -256,22 +256,22 @@ class ListFieldUITestCase extends FieldTestCase {
$node = $this->drupalCreateNode($settings);
// Check that a flat list of values is rejected once the field has data.
$this->assertAllowedValuesInput( "Zero\nOne", 'invalid input', t('Unkeyed lists are rejected once the field has data.'));
$this->assertAllowedValuesInput( "Zero\nOne", 'invalid input', 'Unkeyed lists are rejected once the field has data.');
// Check that values can be added but values in use cannot be removed.
$string = "0|Zero\n1|One\n2|Two";
$array = array('0' => 'Zero', '1' => 'One', '2' => 'Two');
$this->assertAllowedValuesInput($string, $array, t('Values can be added.'));
$this->assertAllowedValuesInput($string, $array, 'Values can be added.');
$string = "0|Zero\n1|One";
$array = array('0' => 'Zero', '1' => 'One');
$this->assertAllowedValuesInput($string, $array, t('Values not in use can be removed.'));
$this->assertAllowedValuesInput("0|Zero", 'some values are being removed while currently in use', t('Values in use cannot be removed.'));
$this->assertAllowedValuesInput($string, $array, 'Values not in use can be removed.');
$this->assertAllowedValuesInput("0|Zero", 'some values are being removed while currently in use', 'Values in use cannot be removed.');
// Delete the node, remove the value.
node_delete($node->nid);
$string = "0|Zero";
$array = array('0' => 'Zero');
$this->assertAllowedValuesInput($string, $array, t('Values not in use can be removed.'));
$this->assertAllowedValuesInput($string, $array, 'Values not in use can be removed.');
}
/**
@@ -284,19 +284,19 @@ class ListFieldUITestCase extends FieldTestCase {
// Flat list of textual values.
$string = "Zero\nOne";
$array = array('0' => 'Zero', '1' => 'One');
$this->assertAllowedValuesInput($string, $array, t('Unkeyed lists are accepted.'));
$this->assertAllowedValuesInput($string, $array, 'Unkeyed lists are accepted.');
// Explicit numeric keys.
$string = "0|Zero\n.5|Point five";
$array = array('0' => 'Zero', '0.5' => 'Point five');
$this->assertAllowedValuesInput($string, $array, t('Integer keys are accepted.'));
$this->assertAllowedValuesInput($string, $array, 'Integer keys are accepted.');
// Check that values can be added and removed.
$string = "0|Zero\n.5|Point five\n1.0|One";
$array = array('0' => 'Zero', '0.5' => 'Point five', '1' => 'One');
$this->assertAllowedValuesInput($string, $array, t('Values can be added and removed.'));
$this->assertAllowedValuesInput($string, $array, 'Values can be added and removed.');
// Non-numeric keys.
$this->assertAllowedValuesInput("abc|abc\n", 'each key must be a valid integer or decimal', t('Non numeric keys are rejected.'));
$this->assertAllowedValuesInput("abc|abc\n", 'each key must be a valid integer or decimal', 'Non numeric keys are rejected.');
// Mixed list of keyed and unkeyed values.
$this->assertAllowedValuesInput("Zero\n1|One\n", 'invalid input', t('Mixed lists are rejected.'));
$this->assertAllowedValuesInput("Zero\n1|One\n", 'invalid input', 'Mixed lists are rejected.');
// Create a node with actual data for the field.
$settings = array(
@@ -306,22 +306,22 @@ class ListFieldUITestCase extends FieldTestCase {
$node = $this->drupalCreateNode($settings);
// Check that a flat list of values is rejected once the field has data.
$this->assertAllowedValuesInput("Zero\nOne", 'invalid input', t('Unkeyed lists are rejected once the field has data.'));
$this->assertAllowedValuesInput("Zero\nOne", 'invalid input', 'Unkeyed lists are rejected once the field has data.');
// Check that values can be added but values in use cannot be removed.
$string = "0|Zero\n.5|Point five\n2|Two";
$array = array('0' => 'Zero', '0.5' => 'Point five', '2' => 'Two');
$this->assertAllowedValuesInput($string, $array, t('Values can be added.'));
$this->assertAllowedValuesInput($string, $array, 'Values can be added.');
$string = "0|Zero\n.5|Point five";
$array = array('0' => 'Zero', '0.5' => 'Point five');
$this->assertAllowedValuesInput($string, $array, t('Values not in use can be removed.'));
$this->assertAllowedValuesInput("0|Zero", 'some values are being removed while currently in use', t('Values in use cannot be removed.'));
$this->assertAllowedValuesInput($string, $array, 'Values not in use can be removed.');
$this->assertAllowedValuesInput("0|Zero", 'some values are being removed while currently in use', 'Values in use cannot be removed.');
// Delete the node, remove the value.
node_delete($node->nid);
$string = "0|Zero";
$array = array('0' => 'Zero');
$this->assertAllowedValuesInput($string, $array, t('Values not in use can be removed.'));
$this->assertAllowedValuesInput($string, $array, 'Values not in use can be removed.');
}
/**
@@ -334,21 +334,21 @@ class ListFieldUITestCase extends FieldTestCase {
// Flat list of textual values.
$string = "Zero\nOne";
$array = array('Zero' => 'Zero', 'One' => 'One');
$this->assertAllowedValuesInput($string, $array, t('Unkeyed lists are accepted.'));
$this->assertAllowedValuesInput($string, $array, 'Unkeyed lists are accepted.');
// Explicit keys.
$string = "zero|Zero\none|One";
$array = array('zero' => 'Zero', 'one' => 'One');
$this->assertAllowedValuesInput($string, $array, t('Explicit keys are accepted.'));
$this->assertAllowedValuesInput($string, $array, 'Explicit keys are accepted.');
// Check that values can be added and removed.
$string = "zero|Zero\ntwo|Two";
$array = array('zero' => 'Zero', 'two' => 'Two');
$this->assertAllowedValuesInput($string, $array, t('Values can be added and removed.'));
$this->assertAllowedValuesInput($string, $array, 'Values can be added and removed.');
// Mixed list of keyed and unkeyed values.
$string = "zero|Zero\nOne\n";
$array = array('zero' => 'Zero', 'One' => 'One');
$this->assertAllowedValuesInput($string, $array, t('Mixed lists are accepted.'));
$this->assertAllowedValuesInput($string, $array, 'Mixed lists are accepted.');
// Overly long keys.
$this->assertAllowedValuesInput("zero|Zero\n" . $this->randomName(256) . "|One", 'each key must be a string at most 255 characters long', t('Overly long keys are rejected.'));
$this->assertAllowedValuesInput("zero|Zero\n" . $this->randomName(256) . "|One", 'each key must be a string at most 255 characters long', 'Overly long keys are rejected.');
// Create a node with actual data for the field.
$settings = array(
@@ -361,22 +361,22 @@ class ListFieldUITestCase extends FieldTestCase {
// data.
$string = "Zero\nOne";
$array = array('Zero' => 'Zero', 'One' => 'One');
$this->assertAllowedValuesInput($string, $array, t('Unkeyed lists are still accepted once the field has data.'));
$this->assertAllowedValuesInput($string, $array, 'Unkeyed lists are still accepted once the field has data.');
// Check that values can be added but values in use cannot be removed.
$string = "Zero\nOne\nTwo";
$array = array('Zero' => 'Zero', 'One' => 'One', 'Two' => 'Two');
$this->assertAllowedValuesInput($string, $array, t('Values can be added.'));
$this->assertAllowedValuesInput($string, $array, 'Values can be added.');
$string = "Zero\nOne";
$array = array('Zero' => 'Zero', 'One' => 'One');
$this->assertAllowedValuesInput($string, $array, t('Values not in use can be removed.'));
$this->assertAllowedValuesInput("Zero", 'some values are being removed while currently in use', t('Values in use cannot be removed.'));
$this->assertAllowedValuesInput($string, $array, 'Values not in use can be removed.');
$this->assertAllowedValuesInput("Zero", 'some values are being removed while currently in use', 'Values in use cannot be removed.');
// Delete the node, remove the value.
node_delete($node->nid);
$string = "Zero";
$array = array('Zero' => 'Zero');
$this->assertAllowedValuesInput($string, $array, t('Values not in use can be removed.'));
$this->assertAllowedValuesInput($string, $array, 'Values not in use can be removed.');
}
/**
@@ -395,15 +395,15 @@ class ListFieldUITestCase extends FieldTestCase {
'off' => $off,
);
$this->drupalPost($this->admin_path, $edit, t('Save settings'));
$this->assertText("Saved field_list_boolean configuration.", t("The 'On' and 'Off' form fields work for boolean fields."));
$this->assertText("Saved field_list_boolean configuration.", "The 'On' and 'Off' form fields work for boolean fields.");
// Test the allowed_values on the field settings form.
$this->drupalGet($this->admin_path);
$this->assertFieldByName('on', $on, t("The 'On' value is stored correctly."));
$this->assertFieldByName('off', $off, t("The 'Off' value is stored correctly."));
$this->assertFieldByName('on', $on, "The 'On' value is stored correctly.");
$this->assertFieldByName('off', $off, "The 'Off' value is stored correctly.");
$field = field_info_field($this->field_name);
$this->assertEqual($field['settings']['allowed_values'], $allowed_values, t('The allowed value is correct'));
$this->assertFalse(isset($field['settings']['on']), t('The on value is not saved into settings'));
$this->assertFalse(isset($field['settings']['off']), t('The off value is not saved into settings'));
$this->assertEqual($field['settings']['allowed_values'], $allowed_values, 'The allowed value is correct');
$this->assertFalse(isset($field['settings']['on']), 'The on value is not saved into settings');
$this->assertFalse(isset($field['settings']['off']), 'The off value is not saved into settings');
}
/**
@@ -5,8 +5,7 @@ package = Testing
version = VERSION
hidden = TRUE
; Information added by drupal.org packaging script on 2013-04-03
version = "7.22"
; Information added by Drupal.org packaging script on 2020-09-16
version = "7.73"
project = "drupal"
datestamp = "1365027012"
datestamp = "1600272641"
+3 -4
View File
@@ -6,8 +6,7 @@ core = 7.x
dependencies[] = field
files[] = number.test
; Information added by drupal.org packaging script on 2013-04-03
version = "7.22"
; Information added by Drupal.org packaging script on 2020-09-16
version = "7.73"
project = "drupal"
datestamp = "1365027012"
datestamp = "1600272641"
+13 -2
View File
@@ -164,6 +164,15 @@ function number_field_presave($entity_type, $entity, $field, $instance, $langcod
}
}
}
if ($field['type'] == 'number_float') {
// Remove the decimal point from float values with decimal
// point but no decimal numbers.
foreach ($items as $delta => $item) {
if (isset($item['value'])) {
$items[$delta]['value'] = floatval($item['value']);
}
}
}
}
/**
@@ -188,7 +197,7 @@ function number_field_formatter_info() {
'label' => t('Default'),
'field types' => array('number_integer'),
'settings' => array(
'thousand_separator' => ' ',
'thousand_separator' => '',
// The 'decimal_separator' and 'scale' settings are not configurable
// through the UI, and will therefore keep their default values. They
// are only present so that the 'number_integer' and 'number_decimal'
@@ -202,7 +211,7 @@ function number_field_formatter_info() {
'label' => t('Default'),
'field types' => array('number_decimal', 'number_float'),
'settings' => array(
'thousand_separator' => ' ',
'thousand_separator' => '',
'decimal_separator' => '.',
'scale' => 2,
'prefix_suffix' => TRUE,
@@ -222,6 +231,8 @@ function number_field_formatter_settings_form($field, $instance, $view_mode, $fo
$display = $instance['display'][$view_mode];
$settings = $display['settings'];
$element = array();
if ($display['type'] == 'number_decimal' || $display['type'] == 'number_integer') {
$options = array(
'' => t('<none>'),
+51 -5
View File
@@ -23,7 +23,7 @@ class NumberFieldTestCase extends DrupalWebTestCase {
function setUp() {
parent::setUp('field_test');
$this->web_user = $this->drupalCreateUser(array('access field_test content', 'administer field_test content', 'administer content types'));
$this->web_user = $this->drupalCreateUser(array('access field_test content', 'administer field_test content', 'administer content types', 'administer fields'));
$this->drupalLogin($this->web_user);
}
@@ -58,7 +58,7 @@ class NumberFieldTestCase extends DrupalWebTestCase {
// Display creation form.
$this->drupalGet('test-entity/add/test-bundle');
$langcode = LANGUAGE_NONE;
$this->assertFieldByName("{$this->field['field_name']}[$langcode][0][value]", '', t('Widget is displayed'));
$this->assertFieldByName("{$this->field['field_name']}[$langcode][0][value]", '', 'Widget is displayed');
// Submit a signed decimal value within the allowed precision and scale.
$value = '-1234.5678';
@@ -68,8 +68,8 @@ class NumberFieldTestCase extends DrupalWebTestCase {
$this->drupalPost(NULL, $edit, t('Save'));
preg_match('|test-entity/manage/(\d+)/edit|', $this->url, $match);
$id = $match[1];
$this->assertRaw(t('test_entity @id has been created.', array('@id' => $id)), t('Entity was created'));
$this->assertRaw(round($value, 2), t('Value is displayed.'));
$this->assertRaw(t('test_entity @id has been created.', array('@id' => $id)), 'Entity was created');
$this->assertRaw($value, 'Value is displayed.');
// Try to create entries with more than one decimal separator; assert fail.
$wrong_entries = array(
@@ -89,7 +89,7 @@ class NumberFieldTestCase extends DrupalWebTestCase {
$this->assertText(
t('There should only be one decimal separator (@separator)',
array('@separator' => $this->field['settings']['decimal_separator'])),
t('Correctly failed to save decimal value with more than one decimal point.')
'Correctly failed to save decimal value with more than one decimal point.'
);
}
@@ -152,4 +152,50 @@ class NumberFieldTestCase extends DrupalWebTestCase {
);
$this->drupalPost(NULL, $edit, t('Save'));
}
/**
* Test number_float field.
*/
function testNumberFloatField() {
$this->field = array(
'field_name' => drupal_strtolower($this->randomName()),
'type' => 'number_float',
'settings' => array(
'precision' => 8, 'scale' => 4, 'decimal_separator' => '.',
)
);
field_create_field($this->field);
$this->instance = array(
'field_name' => $this->field['field_name'],
'entity_type' => 'test_entity',
'bundle' => 'test_bundle',
'widget' => array(
'type' => 'number',
),
'display' => array(
'default' => array(
'type' => 'number_decimal',
),
),
);
field_create_instance($this->instance);
$langcode = LANGUAGE_NONE;
$value = array(
'9.' => '9',
'.' => '0',
'123.55' => '123.55',
'.55' => '0.55',
'-0.55' => '-0.55',
);
foreach($value as $key => $value) {
$edit = array(
"{$this->field['field_name']}[$langcode][0][value]" => $key,
);
$this->drupalPost('test-entity/add/test-bundle', $edit, t('Save'));
$this->assertNoText("PDOException");
$this->assertRaw($value, 'Correct value is displayed.');
}
}
}
+3 -4
View File
@@ -6,8 +6,7 @@ core = 7.x
dependencies[] = field
files[] = options.test
; Information added by drupal.org packaging script on 2013-04-03
version = "7.22"
; Information added by Drupal.org packaging script on 2020-09-16
version = "7.73"
project = "drupal"
datestamp = "1365027012"
datestamp = "1600272641"
+9 -1
View File
@@ -185,6 +185,7 @@ function _options_properties($type, $multiple, $required, $has_value) {
$base = array(
'filter_xss' => FALSE,
'strip_tags' => FALSE,
'strip_tags_and_unescape' => FALSE,
'empty_option' => FALSE,
'optgroups' => FALSE,
);
@@ -195,7 +196,7 @@ function _options_properties($type, $multiple, $required, $has_value) {
case 'select':
$properties = array(
// Select boxes do not support any HTML tag.
'strip_tags' => TRUE,
'strip_tags_and_unescape' => TRUE,
'optgroups' => TRUE,
);
if ($multiple) {
@@ -271,9 +272,16 @@ function _options_prepare_options(&$options, $properties) {
_options_prepare_options($options[$value], $properties);
}
else {
// The 'strip_tags' option is deprecated. Use 'strip_tags_and_unescape'
// when plain text is required (and where the output will be run through
// check_plain() before being inserted back into HTML) or 'filter_xss'
// when HTML is required.
if ($properties['strip_tags']) {
$options[$value] = strip_tags($label);
}
if ($properties['strip_tags_and_unescape']) {
$options[$value] = decode_entities(strip_tags($label));
}
if ($properties['filter_xss']) {
$options[$value] = field_filter_xss($label);
}
+48 -31
View File
@@ -1,7 +1,7 @@
<?php
/**
* @file
* @file
* Tests for options.module.
*/
@@ -23,8 +23,15 @@ class OptionsWidgetsTestCase extends FieldTestCase {
'type' => 'list_integer',
'cardinality' => 1,
'settings' => array(
// Make sure that 0 works as an option.
'allowed_values' => array(0 => 'Zero', 1 => 'One', 2 => 'Some <script>dangerous</script> & unescaped <strong>markup</strong>'),
'allowed_values' => array(
// Make sure that 0 works as an option.
0 => 'Zero',
1 => 'One',
// Make sure that option text is properly sanitized.
2 => 'Some <script>dangerous</script> & unescaped <strong>markup</strong>',
// Make sure that HTML entities in option text are not double-encoded.
3 => 'Some HTML encoded markup with &lt; &amp; &gt;',
),
),
);
$this->card_1 = field_create_field($this->card_1);
@@ -35,8 +42,13 @@ class OptionsWidgetsTestCase extends FieldTestCase {
'type' => 'list_integer',
'cardinality' => 2,
'settings' => array(
// Make sure that 0 works as an option.
'allowed_values' => array(0 => 'Zero', 1 => 'One', 2 => 'Some <script>dangerous</script> & unescaped <strong>markup</strong>'),
'allowed_values' => array(
// Make sure that 0 works as an option.
0 => 'Zero',
1 => 'One',
// Make sure that option text is properly sanitized.
2 => 'Some <script>dangerous</script> & unescaped <strong>markup</strong>',
),
),
);
$this->card_2 = field_create_field($this->card_2);
@@ -47,14 +59,18 @@ class OptionsWidgetsTestCase extends FieldTestCase {
'type' => 'list_boolean',
'cardinality' => 1,
'settings' => array(
// Make sure that 0 works as a 'on' value'.
'allowed_values' => array(1 => 'Zero', 0 => 'Some <script>dangerous</script> & unescaped <strong>markup</strong>'),
'allowed_values' => array(
// Make sure that 1 works as a 'on' value'.
1 => 'Zero',
// Make sure that option text is properly sanitized.
0 => 'Some <script>dangerous</script> & unescaped <strong>markup</strong>',
),
),
);
$this->bool = field_create_field($this->bool);
// Create a web user.
$this->web_user = $this->drupalCreateUser(array('access field_test content', 'administer field_test content'));
$this->web_user = $this->drupalCreateUser(array('access field_test content', 'administer field_test content', 'administer fields'));
$this->drupalLogin($this->web_user);
}
@@ -85,7 +101,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
$this->assertNoFieldChecked("edit-card-1-$langcode-0");
$this->assertNoFieldChecked("edit-card-1-$langcode-1");
$this->assertNoFieldChecked("edit-card-1-$langcode-2");
$this->assertRaw('Some dangerous &amp; unescaped <strong>markup</strong>', t('Option text was properly filtered.'));
$this->assertRaw('Some dangerous &amp; unescaped <strong>markup</strong>', 'Option text was properly filtered.');
// Select first option.
$edit = array("card_1[$langcode]" => 0);
@@ -139,7 +155,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
$this->assertNoFieldChecked("edit-card-2-$langcode-0");
$this->assertNoFieldChecked("edit-card-2-$langcode-1");
$this->assertNoFieldChecked("edit-card-2-$langcode-2");
$this->assertRaw('Some dangerous &amp; unescaped <strong>markup</strong>', t('Option text was properly filtered.'));
$this->assertRaw('Some dangerous &amp; unescaped <strong>markup</strong>', 'Option text was properly filtered.');
// Submit form: select first and third options.
$edit = array(
@@ -178,7 +194,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
"card_2[$langcode][2]" => TRUE,
);
$this->drupalPost(NULL, $edit, t('Save'));
$this->assertText('this field cannot hold more than 2 values', t('Validation error was displayed.'));
$this->assertText('this field cannot hold more than 2 values', 'Validation error was displayed.');
// Submit form: uncheck all options.
$edit = array(
@@ -225,19 +241,20 @@ class OptionsWidgetsTestCase extends FieldTestCase {
// Display form.
$this->drupalGet('test-entity/manage/' . $entity->ftid . '/edit');
// A required field without any value has a "none" option.
$this->assertTrue($this->xpath('//select[@id=:id]//option[@value="_none" and text()=:label]', array(':id' => 'edit-card-1-' . $langcode, ':label' => t('- Select a value -'))), t('A required select list has a "Select a value" choice.'));
$this->assertTrue($this->xpath('//select[@id=:id]//option[@value="_none" and text()=:label]', array(':id' => 'edit-card-1-' . $langcode, ':label' => t('- Select a value -'))), 'A required select list has a "Select a value" choice.');
// With no field data, nothing is selected.
$this->assertNoOptionSelected("edit-card-1-$langcode", '_none');
$this->assertNoOptionSelected("edit-card-1-$langcode", 0);
$this->assertNoOptionSelected("edit-card-1-$langcode", 1);
$this->assertNoOptionSelected("edit-card-1-$langcode", 2);
$this->assertRaw('Some dangerous &amp; unescaped markup', t('Option text was properly filtered.'));
$this->assertRaw('Some dangerous &amp; unescaped markup', 'Option text was properly filtered.');
$this->assertRaw('Some HTML encoded markup with &lt; &amp; &gt;', 'HTML entities in option text were properly handled and not double-encoded');
// Submit form: select invalid 'none' option.
$edit = array("card_1[$langcode]" => '_none');
$this->drupalPost(NULL, $edit, t('Save'));
$this->assertRaw(t('!title field is required.', array('!title' => $instance['field_name'])), t('Cannot save a required field when selecting "none" from the select list.'));
$this->assertRaw(t('!title field is required.', array('!title' => $instance['field_name'])), 'Cannot save a required field when selecting "none" from the select list.');
// Submit form: select first option.
$edit = array("card_1[$langcode]" => 0);
@@ -247,7 +264,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
// Display form: check that the right options are selected.
$this->drupalGet('test-entity/manage/' . $entity->ftid . '/edit');
// A required field with a value has no 'none' option.
$this->assertFalse($this->xpath('//select[@id=:id]//option[@value="_none"]', array(':id' => 'edit-card-1-' . $langcode)), t('A required select list with an actual value has no "none" choice.'));
$this->assertFalse($this->xpath('//select[@id=:id]//option[@value="_none"]', array(':id' => 'edit-card-1-' . $langcode)), 'A required select list with an actual value has no "none" choice.');
$this->assertOptionSelected("edit-card-1-$langcode", 0);
$this->assertNoOptionSelected("edit-card-1-$langcode", 1);
$this->assertNoOptionSelected("edit-card-1-$langcode", 2);
@@ -259,7 +276,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
// Display form.
$this->drupalGet('test-entity/manage/' . $entity->ftid . '/edit');
// A non-required field has a 'none' option.
$this->assertTrue($this->xpath('//select[@id=:id]//option[@value="_none" and text()=:label]', array(':id' => 'edit-card-1-' . $langcode, ':label' => t('- None -'))), t('A non-required select list has a "None" choice.'));
$this->assertTrue($this->xpath('//select[@id=:id]//option[@value="_none" and text()=:label]', array(':id' => 'edit-card-1-' . $langcode, ':label' => t('- None -'))), 'A non-required select list has a "None" choice.');
// Submit form: Unselect the option.
$edit = array("card_1[$langcode]" => '_none');
$this->drupalPost('test-entity/manage/' . $entity->ftid . '/edit', $edit, t('Save'));
@@ -276,8 +293,8 @@ class OptionsWidgetsTestCase extends FieldTestCase {
$this->assertNoOptionSelected("edit-card-1-$langcode", 0);
$this->assertNoOptionSelected("edit-card-1-$langcode", 1);
$this->assertNoOptionSelected("edit-card-1-$langcode", 2);
$this->assertRaw('Some dangerous &amp; unescaped markup', t('Option text was properly filtered.'));
$this->assertRaw('Group 1', t('Option groups are displayed.'));
$this->assertRaw('Some dangerous &amp; unescaped markup', 'Option text was properly filtered.');
$this->assertRaw('Group 1', 'Option groups are displayed.');
// Submit form: select first option.
$edit = array("card_1[$langcode]" => 0);
@@ -323,7 +340,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
$this->assertNoOptionSelected("edit-card-2-$langcode", 0);
$this->assertNoOptionSelected("edit-card-2-$langcode", 1);
$this->assertNoOptionSelected("edit-card-2-$langcode", 2);
$this->assertRaw('Some dangerous &amp; unescaped markup', t('Option text was properly filtered.'));
$this->assertRaw('Some dangerous &amp; unescaped markup', 'Option text was properly filtered.');
// Submit form: select first and third options.
$edit = array("card_2[$langcode][]" => array(0 => 0, 2 => 2));
@@ -350,7 +367,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
// Submit form: select the three options while the field accepts only 2.
$edit = array("card_2[$langcode][]" => array(0 => 0, 1 => 1, 2 => 2));
$this->drupalPost(NULL, $edit, t('Save'));
$this->assertText('this field cannot hold more than 2 values', t('Validation error was displayed.'));
$this->assertText('this field cannot hold more than 2 values', 'Validation error was displayed.');
// Submit form: uncheck all options.
$edit = array("card_2[$langcode][]" => array());
@@ -359,7 +376,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
// Test the 'None' option.
// Check that the 'none' option has no efect if actual options are selected
// Check that the 'none' option has no effect if actual options are selected
// as well.
$edit = array("card_2[$langcode][]" => array('_none' => '_none', 0 => 0));
$this->drupalPost('test-entity/manage/' . $entity->ftid . '/edit', $edit, t('Save'));
@@ -374,7 +391,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
$instance['required'] = TRUE;
field_update_instance($instance);
$this->drupalGet('test-entity/manage/' . $entity->ftid . '/edit');
$this->assertFalse($this->xpath('//select[@id=:id]//option[@value=""]', array(':id' => 'edit-card-2-' . $langcode)), t('A required select list does not have an empty key.'));
$this->assertFalse($this->xpath('//select[@id=:id]//option[@value=""]', array(':id' => 'edit-card-2-' . $langcode)), 'A required select list does not have an empty key.');
// We do not have to test that a required select list with one option is
// auto-selected because the browser does it for us.
@@ -393,8 +410,8 @@ class OptionsWidgetsTestCase extends FieldTestCase {
$this->assertNoOptionSelected("edit-card-2-$langcode", 0);
$this->assertNoOptionSelected("edit-card-2-$langcode", 1);
$this->assertNoOptionSelected("edit-card-2-$langcode", 2);
$this->assertRaw('Some dangerous &amp; unescaped markup', t('Option text was properly filtered.'));
$this->assertRaw('Group 1', t('Option groups are displayed.'));
$this->assertRaw('Some dangerous &amp; unescaped markup', 'Option text was properly filtered.');
$this->assertRaw('Group 1', 'Option groups are displayed.');
// Submit form: select first option.
$edit = array("card_2[$langcode][]" => array(0 => 0));
@@ -438,7 +455,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
// Display form: with no field data, option is unchecked.
$this->drupalGet('test-entity/manage/' . $entity->ftid . '/edit');
$this->assertNoFieldChecked("edit-bool-$langcode");
$this->assertRaw('Some dangerous &amp; unescaped <strong>markup</strong>', t('Option text was properly filtered.'));
$this->assertRaw('Some dangerous &amp; unescaped <strong>markup</strong>', 'Option text was properly filtered.');
// Submit form: check the option.
$edit = array("bool[$langcode]" => TRUE);
@@ -459,7 +476,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
$this->assertNoFieldChecked("edit-bool-$langcode");
// Create admin user.
$admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer taxonomy'));
$admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer taxonomy', 'administer fields'));
$this->drupalLogin($admin_user);
// Create a test field instance.
@@ -483,13 +500,13 @@ class OptionsWidgetsTestCase extends FieldTestCase {
$this->assertText(
'Use field label instead of the "On value" as label ',
t('Display setting checkbox available.')
'Display setting checkbox available.'
);
$this->assertFieldByXPath(
'*//label[@for="edit-' . $this->bool['field_name'] . '-und" and text()="MyOnValue "]',
TRUE,
t('Default case shows "On value"')
'Default case shows "On value"'
);
// Enable setting
@@ -502,16 +519,16 @@ class OptionsWidgetsTestCase extends FieldTestCase {
$this->drupalGet($fieldEditUrl);
$this->assertText(
'Use field label instead of the "On value" as label ',
t('Display setting checkbox is available')
'Display setting checkbox is available'
);
$this->assertFieldChecked(
'edit-instance-widget-settings-display-label',
t('Display settings checkbox checked')
'Display settings checkbox checked'
);
$this->assertFieldByXPath(
'*//label[@for="edit-' . $this->bool['field_name'] . '-und" and text()="' . $this->bool['field_name'] . ' "]',
TRUE,
t('Display label changes label of the checkbox')
'Display label changes label of the checkbox'
);
}
}
+3 -4
View File
@@ -7,8 +7,7 @@ dependencies[] = field
files[] = text.test
required = TRUE
; Information added by drupal.org packaging script on 2013-04-03
version = "7.22"
; Information added by Drupal.org packaging script on 2020-09-16
version = "7.73"
project = "drupal"
datestamp = "1365027012"
datestamp = "1600272641"
+17 -13
View File
@@ -12,9 +12,9 @@ Drupal.behaviors.textSummary = {
$summaries.once('text-summary-wrapper').each(function(index) {
var $summary = $(this);
var $summaryLabel = $summary.find('label');
var $summaryLabel = $summary.find('label').first();
var $full = $widget.find('.text-full').eq(index).closest('.form-item');
var $fullLabel = $full.find('label');
var $fullLabel = $full.find('label').first();
// Create a placeholder label when the field cardinality is
// unlimited or greater than 1.
@@ -23,24 +23,28 @@ Drupal.behaviors.textSummary = {
}
// Setup the edit/hide summary link.
var $link = $('<span class="field-edit-link">(<a class="link-edit-summary" href="#">' + Drupal.t('Hide summary') + '</a>)</span>').toggle(
function () {
var $link = $('<span class="field-edit-link">(<a class="link-edit-summary" href="#">' + Drupal.t('Hide summary') + '</a>)</span>');
var $a = $link.find('a');
var toggleClick = true;
$link.bind('click', function (e) {
if (toggleClick) {
$summary.hide();
$(this).find('a').html(Drupal.t('Edit summary')).end().appendTo($fullLabel);
return false;
},
function () {
$summary.show();
$(this).find('a').html(Drupal.t('Hide summary')).end().appendTo($summaryLabel);
return false;
$a.html(Drupal.t('Edit summary'));
$link.appendTo($fullLabel);
}
).appendTo($summaryLabel);
else {
$summary.show();
$a.html(Drupal.t('Hide summary'));
$link.appendTo($summaryLabel);
}
toggleClick = !toggleClick;
return false;
}).appendTo($summaryLabel);
// If no summary is set, hide the summary field.
if ($(this).find('.text-summary').val() == '') {
$link.click();
}
return;
});
});
}
+4 -2
View File
@@ -223,11 +223,13 @@ function text_field_formatter_settings_form($field, $instance, $view_mode, $form
if (strpos($display['type'], '_trimmed') !== FALSE) {
$element['trim_length'] = array(
'#title' => t('Trim length'),
'#title' => t('Trimmed limit'),
'#type' => 'textfield',
'#field_suffix' => t('characters'),
'#size' => 10,
'#default_value' => $settings['trim_length'],
'#element_validate' => array('element_validate_integer_positive'),
'#description' => t('If the summary is not set, the trimmed %label field will be shorter than this character limit.', array('%label' => $instance['label'])),
'#required' => TRUE,
);
}
@@ -245,7 +247,7 @@ function text_field_formatter_settings_summary($field, $instance, $view_mode) {
$summary = '';
if (strpos($display['type'], '_trimmed') !== FALSE) {
$summary = t('Trim length') . ': ' . $settings['trim_length'];
$summary = t('Trimmed limit: @trim_length characters', array('@trim_length' => $settings['trim_length']));
}
return $summary;
+21 -20
View File
@@ -110,8 +110,8 @@ class TextFieldTestCase extends DrupalWebTestCase {
// Display creation form.
$this->drupalGet('test-entity/add/test-bundle');
$this->assertFieldByName("{$this->field_name}[$langcode][0][value]", '', t('Widget is displayed'));
$this->assertNoFieldByName("{$this->field_name}[$langcode][0][format]", '1', t('Format selector is not displayed'));
$this->assertFieldByName("{$this->field_name}[$langcode][0][value]", '', 'Widget is displayed');
$this->assertNoFieldByName("{$this->field_name}[$langcode][0][format]", '1', 'Format selector is not displayed');
// Submit with some value.
$value = $this->randomName();
@@ -121,7 +121,7 @@ class TextFieldTestCase extends DrupalWebTestCase {
$this->drupalPost(NULL, $edit, t('Save'));
preg_match('|test-entity/manage/(\d+)/edit|', $this->url, $match);
$id = $match[1];
$this->assertRaw(t('test_entity @id has been created.', array('@id' => $id)), t('Entity was created'));
$this->assertRaw(t('test_entity @id has been created.', array('@id' => $id)), 'Entity was created');
// Display the entity.
$entity = field_test_entity_test_load($id);
@@ -179,8 +179,8 @@ class TextFieldTestCase extends DrupalWebTestCase {
// Display the creation form. Since the user only has access to one format,
// no format selector will be displayed.
$this->drupalGet('test-entity/add/test-bundle');
$this->assertFieldByName("{$this->field_name}[$langcode][0][value]", '', t('Widget is displayed'));
$this->assertNoFieldByName("{$this->field_name}[$langcode][0][format]", '', t('Format selector is not displayed'));
$this->assertFieldByName("{$this->field_name}[$langcode][0][value]", '', 'Widget is displayed');
$this->assertNoFieldByName("{$this->field_name}[$langcode][0][format]", '', 'Format selector is not displayed');
// Submit with data that should be filtered.
$value = '<em>' . $this->randomName() . '</em>';
@@ -190,14 +190,14 @@ class TextFieldTestCase extends DrupalWebTestCase {
$this->drupalPost(NULL, $edit, t('Save'));
preg_match('|test-entity/manage/(\d+)/edit|', $this->url, $match);
$id = $match[1];
$this->assertRaw(t('test_entity @id has been created.', array('@id' => $id)), t('Entity was created'));
$this->assertRaw(t('test_entity @id has been created.', array('@id' => $id)), 'Entity was created');
// Display the entity.
$entity = field_test_entity_test_load($id);
$entity->content = field_attach_view($entity_type, $entity, 'full');
$this->content = drupal_render($entity->content);
$this->assertNoRaw($value, t('HTML tags are not displayed.'));
$this->assertRaw(check_plain($value), t('Escaped HTML is displayed correctly.'));
$this->assertNoRaw($value, 'HTML tags are not displayed.');
$this->assertRaw(check_plain($value), 'Escaped HTML is displayed correctly.');
// Create a new text format that does not escape HTML, and grant the user
// access to it.
@@ -219,21 +219,21 @@ class TextFieldTestCase extends DrupalWebTestCase {
// Display edition form.
// We should now have a 'text format' selector.
$this->drupalGet('test-entity/manage/' . $id . '/edit');
$this->assertFieldByName("{$this->field_name}[$langcode][0][value]", NULL, t('Widget is displayed'));
$this->assertFieldByName("{$this->field_name}[$langcode][0][format]", NULL, t('Format selector is displayed'));
$this->assertFieldByName("{$this->field_name}[$langcode][0][value]", NULL, 'Widget is displayed');
$this->assertFieldByName("{$this->field_name}[$langcode][0][format]", NULL, 'Format selector is displayed');
// Edit and change the text format to the new one that was created.
$edit = array(
"{$this->field_name}[$langcode][0][format]" => $format_id,
);
$this->drupalPost(NULL, $edit, t('Save'));
$this->assertRaw(t('test_entity @id has been updated.', array('@id' => $id)), t('Entity was updated'));
$this->assertRaw(t('test_entity @id has been updated.', array('@id' => $id)), 'Entity was updated');
// Display the entity.
$entity = field_test_entity_test_load($id);
$entity->content = field_attach_view($entity_type, $entity, 'full');
$this->content = drupal_render($entity->content);
$this->assertRaw($value, t('Value is displayed unfiltered'));
$this->assertRaw($value, 'Value is displayed unfiltered');
}
}
@@ -383,7 +383,7 @@ class TextSummaryTestCase extends DrupalWebTestCase {
*/
function callTextSummary($text, $expected, $format = NULL, $size = NULL) {
$summary = text_summary($text, $format, $size);
$this->assertIdentical($summary, $expected, t('Generated summary "@summary" matches expected "@expected".', array('@summary' => $summary, '@expected' => $expected)));
$this->assertIdentical($summary, $expected, format_string('Generated summary "@summary" matches expected "@expected".', array('@summary' => $summary, '@expected' => $expected)));
}
/**
@@ -401,7 +401,7 @@ class TextSummaryTestCase extends DrupalWebTestCase {
$this->drupalPost('node/add/article', $edit, t('Save'));
$node = $this->drupalGetNodeByTitle($edit['title']);
$this->assertIdentical($node->body['und'][0]['summary'], $summary, t('Article with with summary and no body has been submitted.'));
$this->assertIdentical($node->body['und'][0]['summary'], $summary, 'Article with with summary and no body has been submitted.');
}
}
@@ -424,6 +424,7 @@ class TextTranslationTestCase extends DrupalWebTestCase {
'administer content types',
'access administration pages',
'bypass node access',
'administer fields',
filter_permission_name($full_html_format),
));
$this->translator = $this->drupalCreateUser(array('create article content', 'edit own article content', 'translate content'));
@@ -436,7 +437,7 @@ class TextTranslationTestCase extends DrupalWebTestCase {
// Set "Article" content type to use multilingual support with translation.
$edit = array('language_content_type' => 2);
$this->drupalPost('admin/structure/types/manage/article', $edit, t('Save content type'));
$this->assertRaw(t('The content type %type has been updated.', array('%type' => 'Article')), t('Article content type has been updated.'));
$this->assertRaw(t('The content type %type has been updated.', array('%type' => 'Article')), 'Article content type has been updated.');
}
/**
@@ -464,7 +465,7 @@ class TextTranslationTestCase extends DrupalWebTestCase {
$node = $this->drupalGetNodeByTitle($edit['title']);
$this->drupalGet("node/$node->nid/translate");
$this->clickLink(t('add translation'));
$this->assertFieldByXPath("//textarea[@name='body[$langcode][0][value]']", $body, t('The textfield widget is populated.'));
$this->assertFieldByXPath("//textarea[@name='body[$langcode][0][value]']", $body, 'The textfield widget is populated.');
}
/**
@@ -476,7 +477,7 @@ class TextTranslationTestCase extends DrupalWebTestCase {
$edit = array('field[cardinality]' => -1);
$this->drupalPost('admin/structure/types/manage/article/fields/body', $edit, t('Save settings'));
$this->drupalGet('node/add/article');
$this->assertFieldByXPath("//input[@name='body_add_more']", t('Add another item'), t('Body field cardinality set to multiple.'));
$this->assertFieldByXPath("//input[@name='body_add_more']", t('Add another item'), 'Body field cardinality set to multiple.');
$body = array(
$this->randomName(),
@@ -501,7 +502,7 @@ class TextTranslationTestCase extends DrupalWebTestCase {
"body[$langcode][$delta][format]" => array_shift($formats),
);
$this->drupalPost('node/1/edit', $edit, t('Save'));
$this->assertText($body[$delta], t('The body field with delta @delta has been saved.', array('@delta' => $delta)));
$this->assertText($body[$delta], format_string('The body field with delta @delta has been saved.', array('@delta' => $delta)));
}
// Login as translator.
@@ -511,7 +512,7 @@ class TextTranslationTestCase extends DrupalWebTestCase {
$node = $this->drupalGetNodeByTitle($title);
$this->drupalGet("node/$node->nid/translate");
$this->clickLink(t('add translation'));
$this->assertNoText($body[0], t('The body field with delta @delta is hidden.', array('@delta' => 0)));
$this->assertText($body[1], t('The body field with delta @delta is shown.', array('@delta' => 1)));
$this->assertNoText($body[0], format_string('The body field with delta @delta is hidden.', array('@delta' => 0)));
$this->assertText($body[1], format_string('The body field with delta @delta is shown.', array('@delta' => 1)));
}
}
File diff suppressed because it is too large Load Diff
+3 -1
View File
@@ -28,7 +28,9 @@ function field_test_field_info() {
'shape' => array(
'label' => t('Shape'),
'description' => t('Another dummy field type.'),
'settings' => array(),
'settings' => array(
'foreign_key_name' => 'shape',
),
'instance_settings' => array(),
'default_widget' => 'test_field_widget',
'default_formatter' => 'field_test_default',
+3 -4
View File
@@ -6,8 +6,7 @@ files[] = field_test.entity.inc
version = VERSION
hidden = TRUE
; Information added by drupal.org packaging script on 2013-04-03
version = "7.22"
; Information added by Drupal.org packaging script on 2020-09-16
version = "7.73"
project = "drupal"
datestamp = "1365027012"
datestamp = "1600272641"
+15 -3
View File
@@ -60,7 +60,7 @@ function field_test_schema() {
'description' => 'The base table for test entities with a bundle key.',
'fields' => array(
'ftid' => array(
'description' => 'The primary indentifier for a test_entity_bundle_key.',
'description' => 'The primary identifier for a test_entity_bundle_key.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
@@ -79,7 +79,7 @@ function field_test_schema() {
'description' => 'The base table for test entities with a bundle.',
'fields' => array(
'ftid' => array(
'description' => 'The primary indentifier for a test_entity_bundle.',
'description' => 'The primary identifier for a test_entity_bundle.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
@@ -132,6 +132,18 @@ function field_test_field_schema($field) {
);
}
else {
$foreign_keys = array();
// The 'foreign keys' key is not always used in tests.
if (!empty($field['settings']['foreign_key_name'])) {
$foreign_keys['foreign keys'] = array(
// This is a dummy foreign key definition, references a table that
// doesn't exist, but that's not a problem.
$field['settings']['foreign_key_name'] => array(
'table' => $field['settings']['foreign_key_name'],
'columns' => array($field['settings']['foreign_key_name'] => 'id'),
),
);
}
return array(
'columns' => array(
'shape' => array(
@@ -145,6 +157,6 @@ function field_test_field_schema($field) {
'not null' => FALSE,
),
),
);
) + $foreign_keys;
}
}
+16 -4
View File
@@ -204,10 +204,7 @@ function field_test_dummy_field_storage_query(EntityFieldQuery $query) {
}
/**
* Entity label callback.
*
* @param $entity
* The entity object.
* Implements callback_entity_info_label().
*
* @return
* The label of the entity prefixed with "label callback".
@@ -223,6 +220,10 @@ function field_test_field_attach_view_alter(&$output, $context) {
if (!empty($context['display']['settings']['alter'])) {
$output['test_field'][] = array('#markup' => 'field_test_field_attach_view_alter');
}
if (isset($output['test_field'])) {
$output['test_field'][] = array('#markup' => 'field language is ' . $context['language']);
}
}
/**
@@ -270,3 +271,14 @@ function field_test_query_efq_table_prefixing_test_alter(&$query) {
// exception if the EFQ does not properly prefix the base table.
$query->join('test_entity','te2','%alias.ftid = test_entity.ftid');
}
/**
* Implements hook_query_TAG_alter() for tag 'store_global_test_query'.
*/
function field_test_query_store_global_test_query_alter($query) {
// Save the query in a global variable so that it can be examined by tests.
// This can be used by any test which needs to check a query, but see
// FieldSqlStorageTestCase::testFieldSqlStorageMultipleConditionsSameColumn()
// for an example.
$GLOBALS['test_query'] = $query;
}
+3 -3
View File
@@ -455,13 +455,13 @@ function field_test_field_attach_rename_bundle($bundle_old, $bundle_new) {
function field_test_field_attach_delete_bundle($entity_type, $bundle, $instances) {
$data = _field_test_storage_data();
foreach ($instances as $field_name => $instance) {
$field = field_info_field($field_name);
foreach ($instances as $instance) {
$field = field_info_field_by_id($instance['field_id']);
if ($field['storage']['type'] == 'field_test_storage') {
$field_data = &$data[$field['id']];
foreach (array('current', 'revisions') as $sub_table) {
foreach ($field_data[$sub_table] as &$row) {
if ($row->bundle == $bundle_old) {
if ($row->bundle == $bundle) {
$row->deleted = TRUE;
}
}
+5 -3
View File
@@ -4,8 +4,10 @@
* @file field.tpl.php
* Default template implementation to display the value of a field.
*
* This file is not used and is here as a starting point for customization only.
* @see theme_field()
* This file is not used by Drupal core, which uses theme functions instead for
* performance reasons. The markup is the same, though, so if you want to use
* template files rather than functions to extend field theming, copy this to
* your custom theme. See theme_field() for a discussion of performance.
*
* Available variables:
* - $items: An array of field values. Use render() to output them.
@@ -45,7 +47,7 @@
*/
?>
<!--
THIS FILE IS NOT USED AND IS HERE AS A STARTING POINT FOR CUSTOMIZATION ONLY.
This file is not used by Drupal core, which uses theme functions instead.
See http://api.drupal.org/api/function/theme_field/7 for details.
After copying this file to your theme's folder and customizing it, remove this
HTML comment.