cms/drupal/modules/field/field.crud.inc
changeset 541 e756a8c72c3d
equal deleted inserted replaced
540:07239de796bb 541:e756a8c72c3d
       
     1 <?php
       
     2 
       
     3 /**
       
     4  * @file
       
     5  * Field CRUD API, handling field and field instance creation and deletion.
       
     6  */
       
     7 
       
     8 /**
       
     9  * @defgroup field_crud Field CRUD API
       
    10  * @{
       
    11  * Create, update, and delete Field API fields, bundles, and instances.
       
    12  *
       
    13  * Modules use this API, often in hook_install(), to create custom
       
    14  * data structures. UI modules will use it to create a user interface.
       
    15  *
       
    16  * The Field CRUD API uses
       
    17  * @link field Field API data structures @endlink.
       
    18  *
       
    19  * See @link field Field API @endlink for information about the other parts of
       
    20  * the Field API.
       
    21  */
       
    22 
       
    23 /**
       
    24  * Creates a field.
       
    25  *
       
    26  * This function does not bind the field to any bundle; use
       
    27  * field_create_instance() for that.
       
    28  *
       
    29  * @param $field
       
    30  *   A field definition array. The field_name and type properties are required.
       
    31  *   Other properties, if omitted, will be given the following default values:
       
    32  *   - cardinality: 1
       
    33  *   - locked: FALSE
       
    34  *   - indexes: the field-type indexes, specified by the field type's
       
    35  *     hook_field_schema(). The indexes specified in $field are added
       
    36  *     to those default indexes. It is possible to override the
       
    37  *     definition of a field-type index by providing an index with the
       
    38  *     same name, or to remove it by redefining it as an empty array
       
    39  *     of columns. Overriding field-type indexes should be done
       
    40  *     carefully, for it might seriously affect the site's performance.
       
    41  *   - settings: each omitted setting is given the default value defined in
       
    42  *     hook_field_info().
       
    43  *   - storage:
       
    44  *     - type: the storage backend specified in the 'field_storage_default'
       
    45  *       system variable.
       
    46  *     - settings: each omitted setting is given the default value specified in
       
    47  *       hook_field_storage_info().
       
    48  *
       
    49  * @return
       
    50  *   The $field array with the id property filled in.
       
    51  *
       
    52  * @throws FieldException
       
    53  *
       
    54  * See: @link field Field API data structures @endlink.
       
    55  */
       
    56 function field_create_field($field) {
       
    57   // Field name is required.
       
    58   if (empty($field['field_name'])) {
       
    59     throw new FieldException('Attempt to create an unnamed field.');
       
    60   }
       
    61   // Field type is required.
       
    62   if (empty($field['type'])) {
       
    63     throw new FieldException(format_string('Attempt to create field @field_name with no type.', array('@field_name' => $field['field_name'])));
       
    64   }
       
    65   // Field name cannot contain invalid characters.
       
    66   if (!preg_match('/^[_a-z]+[_a-z0-9]*$/', $field['field_name'])) {
       
    67     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'])));
       
    68   }
       
    69 
       
    70   // Field name cannot be longer than 32 characters. We use drupal_strlen()
       
    71   // because the DB layer assumes that column widths are given in characters,
       
    72   // not bytes.
       
    73   if (drupal_strlen($field['field_name']) > 32) {
       
    74     throw new FieldException(t('Attempt to create a field with a name longer than 32 characters: %name',
       
    75       array('%name' => $field['field_name'])));
       
    76   }
       
    77 
       
    78   // Ensure the field name is unique over active and disabled fields.
       
    79   // We do not care about deleted fields.
       
    80   $prior_field = field_read_field($field['field_name'], array('include_inactive' => TRUE));
       
    81   if (!empty($prior_field)) {
       
    82     $message = $prior_field['active']?
       
    83       t('Attempt to create field name %name which already exists and is active.', array('%name' => $field['field_name'])):
       
    84       t('Attempt to create field name %name which already exists, although it is inactive.', array('%name' => $field['field_name']));
       
    85     throw new FieldException($message);
       
    86   }
       
    87 
       
    88   // Disallow reserved field names. This can't prevent all field name
       
    89   // collisions with existing entity properties, but some is better
       
    90   // than none.
       
    91   foreach (entity_get_info() as $type => $info) {
       
    92     if (in_array($field['field_name'], $info['entity keys'])) {
       
    93       throw new FieldException(t('Attempt to create field name %name which is reserved by entity type %type.', array('%name' => $field['field_name'], '%type' => $type)));
       
    94     }
       
    95   }
       
    96 
       
    97   $field += array(
       
    98     'entity_types' => array(),
       
    99     'cardinality' => 1,
       
   100     'translatable' => FALSE,
       
   101     'locked' => FALSE,
       
   102     'settings' => array(),
       
   103     'storage' => array(),
       
   104     'deleted' => 0,
       
   105   );
       
   106 
       
   107   // Check that the field type is known.
       
   108   $field_type = field_info_field_types($field['type']);
       
   109   if (!$field_type) {
       
   110     throw new FieldException(t('Attempt to create a field of unknown type %type.', array('%type' => $field['type'])));
       
   111   }
       
   112   // Create all per-field-type properties (needed here as long as we have
       
   113   // settings that impact column definitions).
       
   114   $field['settings'] += field_info_field_settings($field['type']);
       
   115   $field['module'] = $field_type['module'];
       
   116   $field['active'] = 1;
       
   117 
       
   118   // Provide default storage.
       
   119   $field['storage'] += array(
       
   120     'type' => variable_get('field_storage_default', 'field_sql_storage'),
       
   121     'settings' => array(),
       
   122   );
       
   123   // Check that the storage type is known.
       
   124   $storage_type = field_info_storage_types($field['storage']['type']);
       
   125   if (!$storage_type) {
       
   126     throw new FieldException(t('Attempt to create a field with unknown storage type %type.', array('%type' => $field['storage']['type'])));
       
   127   }
       
   128   // Provide default storage settings.
       
   129   $field['storage']['settings'] += field_info_storage_settings($field['storage']['type']);
       
   130   $field['storage']['module'] = $storage_type['module'];
       
   131   $field['storage']['active'] = 1;
       
   132   // Collect storage information.
       
   133   module_load_install($field['module']);
       
   134   $schema = (array) module_invoke($field['module'], 'field_schema', $field);
       
   135   $schema += array('columns' => array(), 'indexes' => array(), 'foreign keys' => array());
       
   136   // 'columns' are hardcoded in the field type.
       
   137   $field['columns'] = $schema['columns'];
       
   138   // 'foreign keys' are hardcoded in the field type.
       
   139   $field['foreign keys'] = $schema['foreign keys'];
       
   140   // 'indexes' can be both hardcoded in the field type, and specified in the
       
   141   // incoming $field definition.
       
   142   $field += array(
       
   143     'indexes' => array(),
       
   144   );
       
   145   $field['indexes'] += $schema['indexes'];
       
   146 
       
   147   // The serialized 'data' column contains everything from $field that does not
       
   148   // have its own column and is not automatically populated when the field is
       
   149   // read.
       
   150   $data = $field;
       
   151   unset($data['columns'], $data['field_name'], $data['type'], $data['active'], $data['module'], $data['storage_type'], $data['storage_active'], $data['storage_module'], $data['locked'], $data['cardinality'], $data['deleted']);
       
   152   // Additionally, do not save the 'bundles' property populated by
       
   153   // field_info_field().
       
   154   unset($data['bundles']);
       
   155 
       
   156   $record = array(
       
   157     'field_name' => $field['field_name'],
       
   158     'type' => $field['type'],
       
   159     'module' => $field['module'],
       
   160     'active' => $field['active'],
       
   161     'storage_type' => $field['storage']['type'],
       
   162     'storage_module' => $field['storage']['module'],
       
   163     'storage_active' => $field['storage']['active'],
       
   164     'locked' => $field['locked'],
       
   165     'data' => $data,
       
   166     'cardinality' => $field['cardinality'],
       
   167     'translatable' => $field['translatable'],
       
   168     'deleted' => $field['deleted'],
       
   169   );
       
   170 
       
   171   // Store the field and get the id back.
       
   172   drupal_write_record('field_config', $record);
       
   173   $field['id'] = $record['id'];
       
   174 
       
   175   // Invoke hook_field_storage_create_field after the field is
       
   176   // complete (e.g. it has its id).
       
   177   try {
       
   178     // Invoke hook_field_storage_create_field after
       
   179     // drupal_write_record() sets the field id.
       
   180     module_invoke($storage_type['module'], 'field_storage_create_field', $field);
       
   181   }
       
   182   catch (Exception $e) {
       
   183     // If storage creation failed, remove the field_config record before
       
   184     // rethrowing the exception.
       
   185     db_delete('field_config')
       
   186       ->condition('id', $field['id'])
       
   187       ->execute();
       
   188     throw $e;
       
   189   }
       
   190 
       
   191   // Clear caches
       
   192   field_cache_clear();
       
   193 
       
   194   // Invoke external hooks after the cache is cleared for API consistency.
       
   195   module_invoke_all('field_create_field', $field);
       
   196 
       
   197   return $field;
       
   198 }
       
   199 
       
   200 /**
       
   201  * Updates a field.
       
   202  *
       
   203  * Any module may forbid any update for any reason. For example, the
       
   204  * field's storage module might forbid an update if it would change
       
   205  * the storage schema while data for the field exists. A field type
       
   206  * module might forbid an update if it would change existing data's
       
   207  * semantics, or if there are external dependencies on field settings
       
   208  * that cannot be updated.
       
   209  *
       
   210  * @param $field
       
   211  *   A field structure. $field['field_name'] must provided; it
       
   212  *   identifies the field that will be updated to match this
       
   213  *   structure. Any other properties of the field that are not
       
   214  *   specified in $field will be left unchanged, so it is not
       
   215  *   necessary to pass in a fully populated $field structure.
       
   216  * @return
       
   217  *   Throws a FieldException if the update cannot be performed.
       
   218  * @see field_create_field()
       
   219  */
       
   220 function field_update_field($field) {
       
   221   // Check that the specified field exists.
       
   222   $prior_field = field_read_field($field['field_name']);
       
   223   if (empty($prior_field)) {
       
   224     throw new FieldException('Attempt to update a non-existent field.');
       
   225   }
       
   226 
       
   227   // Use the prior field values for anything not specifically set by the new
       
   228   // field to be sure that all values are set.
       
   229   $field += $prior_field;
       
   230   $field['settings'] += $prior_field['settings'];
       
   231 
       
   232   // Some updates are always disallowed.
       
   233   if ($field['type'] != $prior_field['type']) {
       
   234     throw new FieldException("Cannot change an existing field's type.");
       
   235   }
       
   236   if ($field['entity_types'] != $prior_field['entity_types']) {
       
   237     throw new FieldException("Cannot change an existing field's entity_types property.");
       
   238   }
       
   239   if ($field['storage']['type'] != $prior_field['storage']['type']) {
       
   240     throw new FieldException("Cannot change an existing field's storage type.");
       
   241   }
       
   242 
       
   243   // Collect the new storage information, since what is in
       
   244   // $prior_field may no longer be right.
       
   245   module_load_install($field['module']);
       
   246   $schema = (array) module_invoke($field['module'], 'field_schema', $field);
       
   247   $schema += array('columns' => array(), 'indexes' => array(), 'foreign keys' => array());
       
   248   // 'columns' are hardcoded in the field type.
       
   249   $field['columns'] = $schema['columns'];
       
   250   // 'foreign keys' are hardcoded in the field type.
       
   251   $field['foreign keys'] = $schema['foreign keys'];
       
   252   // 'indexes' can be both hardcoded in the field type, and specified in the
       
   253   // incoming $field definition.
       
   254   $field += array(
       
   255     'indexes' => array(),
       
   256   );
       
   257   $field['indexes'] += $schema['indexes'];
       
   258 
       
   259   $has_data = field_has_data($field);
       
   260 
       
   261   // See if any module forbids the update by throwing an exception.
       
   262   foreach (module_implements('field_update_forbid') as $module) {
       
   263     $function = $module . '_field_update_forbid';
       
   264     $function($field, $prior_field, $has_data);
       
   265   }
       
   266 
       
   267   // Tell the storage engine to update the field. Do this before
       
   268   // saving the new definition since it still might fail.
       
   269   $storage_type = field_info_storage_types($field['storage']['type']);
       
   270   module_invoke($storage_type['module'], 'field_storage_update_field', $field, $prior_field, $has_data);
       
   271 
       
   272   // Save the new field definition. @todo: refactor with
       
   273   // field_create_field.
       
   274 
       
   275   // The serialized 'data' column contains everything from $field that does not
       
   276   // have its own column and is not automatically populated when the field is
       
   277   // read.
       
   278   $data = $field;
       
   279   unset($data['columns'], $data['field_name'], $data['type'], $data['locked'], $data['module'], $data['cardinality'], $data['active'], $data['deleted']);
       
   280   // Additionally, do not save the 'bundles' property populated by
       
   281   // field_info_field().
       
   282   unset($data['bundles']);
       
   283 
       
   284   $field['data'] = $data;
       
   285 
       
   286   // Store the field and create the id.
       
   287   $primary_key = array('id');
       
   288   drupal_write_record('field_config', $field, $primary_key);
       
   289 
       
   290   // Clear caches
       
   291   field_cache_clear();
       
   292 
       
   293   // Invoke external hooks after the cache is cleared for API consistency.
       
   294   module_invoke_all('field_update_field', $field, $prior_field, $has_data);
       
   295 }
       
   296 
       
   297 /**
       
   298  * Reads a single field record directly from the database.
       
   299  *
       
   300  * Generally, you should use the field_info_field() instead.
       
   301  *
       
   302  * This function will not return deleted fields. Use
       
   303  * field_read_fields() instead for this purpose.
       
   304  *
       
   305  * @param $field_name
       
   306  *   The field name to read.
       
   307  * @param array $include_additional
       
   308  *   The default behavior of this function is to not return a field that
       
   309  *   is inactive. Setting
       
   310  *   $include_additional['include_inactive'] to TRUE will override this
       
   311  *   behavior.
       
   312  * @return
       
   313  *   A field definition array, or FALSE.
       
   314  */
       
   315 function field_read_field($field_name, $include_additional = array()) {
       
   316   $fields = field_read_fields(array('field_name' => $field_name), $include_additional);
       
   317   return $fields ? current($fields) : FALSE;
       
   318 }
       
   319 
       
   320 /**
       
   321  * Reads in fields that match an array of conditions.
       
   322  *
       
   323  * @param array $params
       
   324  *   An array of conditions to match against. Keys are columns from the
       
   325  *   'field_config' table, values are conditions to match. Additionally,
       
   326  *   conditions on the 'entity_type' and 'bundle' columns from the
       
   327  *   'field_config_instance' table are supported (select fields having an
       
   328  *   instance on a given bundle).
       
   329  * @param array $include_additional
       
   330  *   The default behavior of this function is to not return fields that
       
   331  *   are inactive or have been deleted. Setting
       
   332  *   $include_additional['include_inactive'] or
       
   333  *   $include_additional['include_deleted'] to TRUE will override this
       
   334  *   behavior.
       
   335  * @return
       
   336  *   An array of fields matching $params. If
       
   337  *   $include_additional['include_deleted'] is TRUE, the array is keyed
       
   338  *   by field id, otherwise it is keyed by field name.
       
   339  */
       
   340 function field_read_fields($params = array(), $include_additional = array()) {
       
   341   $query = db_select('field_config', 'fc', array('fetch' => PDO::FETCH_ASSOC));
       
   342   $query->fields('fc');
       
   343 
       
   344   // Turn the conditions into a query.
       
   345   foreach ($params as $key => $value) {
       
   346     // Allow filtering on the 'entity_type' and 'bundle' columns of the
       
   347     // field_config_instance table.
       
   348     if ($key == 'entity_type' || $key == 'bundle') {
       
   349       if (empty($fci_join)) {
       
   350         $fci_join = $query->join('field_config_instance', 'fci', 'fc.id = fci.field_id');
       
   351       }
       
   352       $key = 'fci.' . $key;
       
   353     }
       
   354     else {
       
   355       $key = 'fc.' . $key;
       
   356     }
       
   357 
       
   358     $query->condition($key, $value);
       
   359   }
       
   360 
       
   361   if (!isset($include_additional['include_inactive']) || !$include_additional['include_inactive']) {
       
   362     $query
       
   363       ->condition('fc.active', 1)
       
   364       ->condition('fc.storage_active', 1);
       
   365   }
       
   366   $include_deleted = (isset($include_additional['include_deleted']) && $include_additional['include_deleted']);
       
   367   if (!$include_deleted) {
       
   368     $query->condition('fc.deleted', 0);
       
   369   }
       
   370 
       
   371   $fields = array();
       
   372   $results = $query->execute();
       
   373   foreach ($results as $record) {
       
   374     $field = unserialize($record['data']);
       
   375     $field['id'] = $record['id'];
       
   376     $field['field_name'] = $record['field_name'];
       
   377     $field['type'] = $record['type'];
       
   378     $field['module'] = $record['module'];
       
   379     $field['active'] = $record['active'];
       
   380     $field['storage']['type'] = $record['storage_type'];
       
   381     $field['storage']['module'] = $record['storage_module'];
       
   382     $field['storage']['active'] = $record['storage_active'];
       
   383     $field['locked'] = $record['locked'];
       
   384     $field['cardinality'] = $record['cardinality'];
       
   385     $field['translatable'] = $record['translatable'];
       
   386     $field['deleted'] = $record['deleted'];
       
   387 
       
   388     module_invoke_all('field_read_field', $field);
       
   389 
       
   390     // Populate storage information.
       
   391     module_load_install($field['module']);
       
   392     $schema = (array) module_invoke($field['module'], 'field_schema', $field);
       
   393     $schema += array('columns' => array(), 'indexes' => array());
       
   394     $field['columns'] = $schema['columns'];
       
   395 
       
   396     $field_name = $field['field_name'];
       
   397     if ($include_deleted) {
       
   398       $field_name = $field['id'];
       
   399     }
       
   400     $fields[$field_name] = $field;
       
   401   }
       
   402   return $fields;
       
   403 }
       
   404 
       
   405 /**
       
   406  * Marks a field and its instances and data for deletion.
       
   407  *
       
   408  * @param $field_name
       
   409  *   The field name to delete.
       
   410  */
       
   411 function field_delete_field($field_name) {
       
   412   // Delete all non-deleted instances.
       
   413   $field = field_info_field($field_name);
       
   414   if (isset($field['bundles'])) {
       
   415     foreach ($field['bundles'] as $entity_type => $bundles) {
       
   416       foreach ($bundles as $bundle) {
       
   417         $instance = field_info_instance($entity_type, $field_name, $bundle);
       
   418         field_delete_instance($instance, FALSE);
       
   419       }
       
   420     }
       
   421   }
       
   422 
       
   423   // Mark field data for deletion.
       
   424   module_invoke($field['storage']['module'], 'field_storage_delete_field', $field);
       
   425 
       
   426   // Mark the field for deletion.
       
   427   db_update('field_config')
       
   428     ->fields(array('deleted' => 1))
       
   429     ->condition('field_name', $field_name)
       
   430     ->execute();
       
   431 
       
   432   // Clear the cache.
       
   433   field_cache_clear();
       
   434 
       
   435   module_invoke_all('field_delete_field', $field);
       
   436 }
       
   437 
       
   438 /**
       
   439  * Creates an instance of a field, binding it to a bundle.
       
   440  *
       
   441  * @param $instance
       
   442  *   A field instance definition array. The field_name, entity_type and
       
   443  *   bundle properties are required. Other properties, if omitted,
       
   444  *   will be given the following default values:
       
   445  *   - label: the field name
       
   446  *   - description: empty string
       
   447  *   - required: FALSE
       
   448  *   - default_value_function: empty string
       
   449  *   - settings: each omitted setting is given the default value specified in
       
   450  *     hook_field_info().
       
   451  *   - widget:
       
   452  *     - type: the default widget specified in hook_field_info().
       
   453  *     - settings: each omitted setting is given the default value specified in
       
   454  *       hook_field_widget_info().
       
   455  *   - display:
       
   456  *     Settings for the 'default' view mode will be added if not present, and
       
   457  *     each view mode in the definition will be completed with the following
       
   458  *     default values:
       
   459  *     - label: 'above'
       
   460  *     - type: the default formatter specified in hook_field_info().
       
   461  *     - settings: each omitted setting is given the default value specified in
       
   462  *       hook_field_formatter_info().
       
   463  *     View modes not present in the definition are left empty, and the field
       
   464  *     will not be displayed in this mode.
       
   465  *
       
   466  * @return
       
   467  *   The $instance array with the id property filled in.
       
   468  *
       
   469  * @throws FieldException
       
   470  *
       
   471  * See: @link field Field API data structures @endlink.
       
   472  */
       
   473 function field_create_instance($instance) {
       
   474   $field = field_read_field($instance['field_name']);
       
   475   if (empty($field)) {
       
   476     throw new FieldException(t("Attempt to create an instance of a field @field_name that doesn't exist or is currently inactive.", array('@field_name' => $instance['field_name'])));
       
   477   }
       
   478   // Check that the required properties exists.
       
   479   if (empty($instance['entity_type'])) {
       
   480     throw new FieldException(t('Attempt to create an instance of field @field_name without an entity type.', array('@field_name' => $instance['field_name'])));
       
   481   }
       
   482   if (empty($instance['bundle'])) {
       
   483     throw new FieldException(t('Attempt to create an instance of field @field_name without a bundle.', array('@field_name' => $instance['field_name'])));
       
   484   }
       
   485   // Check that the field can be attached to this entity type.
       
   486   if (!empty($field['entity_types']) && !in_array($instance['entity_type'], $field['entity_types'])) {
       
   487     throw new FieldException(t('Attempt to create an instance of field @field_name on forbidden entity type @entity_type.', array('@field_name' => $instance['field_name'], '@entity_type' => $instance['entity_type'])));
       
   488   }
       
   489 
       
   490   // Set the field id.
       
   491   $instance['field_id'] = $field['id'];
       
   492 
       
   493   // Note that we do *not* prevent creating a field on non-existing bundles,
       
   494   // because that would break the 'Body as field' upgrade for contrib
       
   495   // node types.
       
   496 
       
   497   // TODO: Check that the widget type is known and can handle the field type ?
       
   498   // TODO: Check that the formatters are known and can handle the field type ?
       
   499   // TODO: Check that the display view modes are known for the entity type ?
       
   500   // Those checks should probably happen in _field_write_instance() ?
       
   501   // Problem : this would mean that a UI module cannot update an instance with a disabled formatter.
       
   502 
       
   503   // Ensure the field instance is unique within the bundle.
       
   504   // We only check for instances of active fields, since adding an instance of
       
   505   // a disabled field is not supported.
       
   506   $prior_instance = field_read_instance($instance['entity_type'], $instance['field_name'], $instance['bundle']);
       
   507   if (!empty($prior_instance)) {
       
   508     $message = t('Attempt to create an instance of field @field_name on bundle @bundle that already has an instance of that field.', array('@field_name' => $instance['field_name'], '@bundle' => $instance['bundle']));
       
   509     throw new FieldException($message);
       
   510   }
       
   511 
       
   512   _field_write_instance($instance);
       
   513 
       
   514   // Clear caches
       
   515   field_cache_clear();
       
   516 
       
   517   // Invoke external hooks after the cache is cleared for API consistency.
       
   518   module_invoke_all('field_create_instance', $instance);
       
   519 
       
   520   return $instance;
       
   521 }
       
   522 
       
   523 /**
       
   524  * Updates an instance of a field.
       
   525  *
       
   526  * @param $instance
       
   527  *   An associative array representing an instance structure. The following
       
   528  *   required array elements specify which field instance is being updated:
       
   529  *   - entity_type: The type of the entity the field is attached to.
       
   530  *   - bundle: The bundle this field belongs to.
       
   531  *   - field_name: The name of an existing field.
       
   532  *   The other array elements represent properties of the instance, and all
       
   533  *   properties must be specified or their default values will be used (except
       
   534  *   internal-use properties, which are assigned automatically). To avoid
       
   535  *   losing the previously stored properties of the instance when making a
       
   536  *   change, first load the instance with field_info_instance(), then override
       
   537  *   the values you want to override, and finally save using this function.
       
   538  *   Example:
       
   539  *   @code
       
   540  *   // Fetch an instance info array.
       
   541  *   $instance_info = field_info_instance($entity_type, $field_name, $bundle_name);
       
   542  *   // Change a single property in the instance definition.
       
   543  *   $instance_info['required'] = TRUE;
       
   544  *   // Write the changed definition back.
       
   545  *   field_update_instance($instance_info);
       
   546  *   @endcode
       
   547  *
       
   548  * @throws FieldException
       
   549  *
       
   550  * @see field_info_instance()
       
   551  * @see field_create_instance()
       
   552  */
       
   553 function field_update_instance($instance) {
       
   554   // Check that the specified field exists.
       
   555   $field = field_read_field($instance['field_name']);
       
   556   if (empty($field)) {
       
   557     throw new FieldException(t('Attempt to update an instance of a nonexistent field @field.', array('@field' => $instance['field_name'])));
       
   558   }
       
   559 
       
   560   // Check that the field instance exists (even if it is inactive, since we
       
   561   // want to be able to replace inactive widgets with new ones).
       
   562   $prior_instance = field_read_instance($instance['entity_type'], $instance['field_name'], $instance['bundle'], array('include_inactive' => TRUE));
       
   563   if (empty($prior_instance)) {
       
   564     throw new FieldException(t("Attempt to update an instance of field @field on bundle @bundle that doesn't exist.", array('@field' => $instance['field_name'], '@bundle' => $instance['bundle'])));
       
   565   }
       
   566 
       
   567   $instance['id'] = $prior_instance['id'];
       
   568   $instance['field_id'] = $prior_instance['field_id'];
       
   569 
       
   570   _field_write_instance($instance, TRUE);
       
   571 
       
   572   // Clear caches.
       
   573   field_cache_clear();
       
   574 
       
   575   module_invoke_all('field_update_instance', $instance, $prior_instance);
       
   576 }
       
   577 
       
   578 /**
       
   579  * Stores an instance record in the field configuration database.
       
   580  *
       
   581  * @param $instance
       
   582  *   An instance structure.
       
   583  * @param $update
       
   584  *   Whether this is a new or existing instance.
       
   585  */
       
   586 function _field_write_instance($instance, $update = FALSE) {
       
   587   $field = field_read_field($instance['field_name']);
       
   588   $field_type = field_info_field_types($field['type']);
       
   589 
       
   590   // Set defaults.
       
   591   $instance += array(
       
   592     'settings' => array(),
       
   593     'display' => array(),
       
   594     'widget' => array(),
       
   595     'required' => FALSE,
       
   596     'label' => $instance['field_name'],
       
   597     'description' => '',
       
   598     'deleted' => 0,
       
   599   );
       
   600 
       
   601   // Set default instance settings.
       
   602   $instance['settings'] += field_info_instance_settings($field['type']);
       
   603 
       
   604   // Set default widget and settings.
       
   605   $instance['widget'] += array(
       
   606     // TODO: what if no 'default_widget' specified ?
       
   607     'type' => $field_type['default_widget'],
       
   608     'settings' => array(),
       
   609   );
       
   610   // If no weight specified, make sure the field sinks at the bottom.
       
   611   if (!isset($instance['widget']['weight'])) {
       
   612     $max_weight = field_info_max_weight($instance['entity_type'], $instance['bundle'], 'form');
       
   613     $instance['widget']['weight'] = isset($max_weight) ? $max_weight + 1 : 0;
       
   614   }
       
   615   // Check widget module.
       
   616   $widget_type = field_info_widget_types($instance['widget']['type']);
       
   617   $instance['widget']['module'] = $widget_type['module'];
       
   618   $instance['widget']['settings'] += field_info_widget_settings($instance['widget']['type']);
       
   619 
       
   620   // Make sure there are at least display settings for the 'default' view mode,
       
   621   // and fill in defaults for each view mode specified in the definition.
       
   622   $instance['display'] += array(
       
   623     'default' => array(),
       
   624   );
       
   625   foreach ($instance['display'] as $view_mode => $display) {
       
   626     $display += array(
       
   627       'label' => 'above',
       
   628       'type' => isset($field_type['default_formatter']) ? $field_type['default_formatter'] : 'hidden',
       
   629       'settings' => array(),
       
   630     );
       
   631     if ($display['type'] != 'hidden') {
       
   632       $formatter_type = field_info_formatter_types($display['type']);
       
   633       $display['module'] = $formatter_type['module'];
       
   634       $display['settings'] += field_info_formatter_settings($display['type']);
       
   635     }
       
   636     // If no weight specified, make sure the field sinks at the bottom.
       
   637     if (!isset($display['weight'])) {
       
   638       $max_weight = field_info_max_weight($instance['entity_type'], $instance['bundle'], $view_mode);
       
   639       $display['weight'] = isset($max_weight) ? $max_weight + 1 : 0;
       
   640     }
       
   641     $instance['display'][$view_mode] = $display;
       
   642   }
       
   643 
       
   644   // The serialized 'data' column contains everything from $instance that does
       
   645   // not have its own column and is not automatically populated when the
       
   646   // instance is read.
       
   647   $data = $instance;
       
   648   unset($data['id'], $data['field_id'], $data['field_name'], $data['entity_type'], $data['bundle'], $data['deleted']);
       
   649 
       
   650   $record = array(
       
   651     'field_id' => $instance['field_id'],
       
   652     'field_name' => $instance['field_name'],
       
   653     'entity_type' => $instance['entity_type'],
       
   654     'bundle' => $instance['bundle'],
       
   655     'data' => $data,
       
   656     'deleted' => $instance['deleted'],
       
   657   );
       
   658   // We need to tell drupal_update_record() the primary keys to trigger an
       
   659   // update.
       
   660   if ($update) {
       
   661     $record['id'] = $instance['id'];
       
   662     $primary_key = array('id');
       
   663   }
       
   664   else {
       
   665     $primary_key = array();
       
   666   }
       
   667   drupal_write_record('field_config_instance', $record, $primary_key);
       
   668 }
       
   669 
       
   670 /**
       
   671  * Reads a single instance record from the database.
       
   672  *
       
   673  * Generally, you should use field_info_instance() instead, as it
       
   674  * provides caching and allows other modules the opportunity to
       
   675  * append additional formatters, widgets, and other information.
       
   676  *
       
   677  * @param $entity_type
       
   678  *   The type of entity to which the field is bound.
       
   679  * @param $field_name
       
   680  *   The field name to read.
       
   681  * @param $bundle
       
   682  *   The bundle to which the field is bound.
       
   683  * @param array $include_additional
       
   684  *   The default behavior of this function is to not return an instance that
       
   685  *   has been deleted, or whose field is inactive. Setting
       
   686  *   $include_additional['include_inactive'] or
       
   687  *   $include_additional['include_deleted'] to TRUE will override this
       
   688  *   behavior.
       
   689  * @return
       
   690  *   An instance structure, or FALSE.
       
   691  */
       
   692 function field_read_instance($entity_type, $field_name, $bundle, $include_additional = array()) {
       
   693   $instances = field_read_instances(array('entity_type' => $entity_type, 'field_name' => $field_name, 'bundle' => $bundle), $include_additional);
       
   694   return $instances ? current($instances) : FALSE;
       
   695 }
       
   696 
       
   697 /**
       
   698  * Reads in field instances that match an array of conditions.
       
   699  *
       
   700  * @param $param
       
   701  *   An array of properties to use in selecting a field
       
   702  *   instance. Valid keys include any column of the
       
   703  *   field_config_instance table. If NULL, all instances will be returned.
       
   704  * @param $include_additional
       
   705  *   The default behavior of this function is to not return field
       
   706  *   instances that have been marked deleted, or whose field is inactive.
       
   707  *   Setting $include_additional['include_inactive'] or
       
   708  *   $include_additional['include_deleted'] to TRUE will override this
       
   709  *   behavior.
       
   710  * @return
       
   711  *   An array of instances matching the arguments.
       
   712  */
       
   713 function field_read_instances($params = array(), $include_additional = array()) {
       
   714   $include_inactive = isset($include_additional['include_inactive']) && $include_additional['include_inactive'];
       
   715   $include_deleted = isset($include_additional['include_deleted']) && $include_additional['include_deleted'];
       
   716 
       
   717   $query = db_select('field_config_instance', 'fci', array('fetch' => PDO::FETCH_ASSOC));
       
   718   $query->join('field_config', 'fc', 'fc.id = fci.field_id');
       
   719   $query->fields('fci');
       
   720 
       
   721   // Turn the conditions into a query.
       
   722   foreach ($params as $key => $value) {
       
   723     $query->condition('fci.' . $key, $value);
       
   724   }
       
   725   if (!$include_inactive) {
       
   726     $query
       
   727       ->condition('fc.active', 1)
       
   728       ->condition('fc.storage_active', 1);
       
   729   }
       
   730   if (!$include_deleted) {
       
   731     $query->condition('fc.deleted', 0);
       
   732     $query->condition('fci.deleted', 0);
       
   733   }
       
   734 
       
   735   $instances = array();
       
   736   $results = $query->execute();
       
   737 
       
   738   foreach ($results as $record) {
       
   739     // Filter out instances on unknown entity types (for instance because the
       
   740     // module exposing them was disabled).
       
   741     $entity_info = entity_get_info($record['entity_type']);
       
   742     if ($include_inactive || $entity_info) {
       
   743       $instance = unserialize($record['data']);
       
   744       $instance['id'] = $record['id'];
       
   745       $instance['field_id'] = $record['field_id'];
       
   746       $instance['field_name'] = $record['field_name'];
       
   747       $instance['entity_type'] = $record['entity_type'];
       
   748       $instance['bundle'] = $record['bundle'];
       
   749       $instance['deleted'] = $record['deleted'];
       
   750 
       
   751       module_invoke_all('field_read_instance', $instance);
       
   752       $instances[] = $instance;
       
   753     }
       
   754   }
       
   755   return $instances;
       
   756 }
       
   757 
       
   758 /**
       
   759  * Marks a field instance and its data for deletion.
       
   760  *
       
   761  * @param $instance
       
   762  *   An instance structure.
       
   763  * @param $field_cleanup
       
   764  *   If TRUE, the field will be deleted as well if its last instance is being
       
   765  *   deleted. If FALSE, it is the caller's responsibility to handle the case of
       
   766  *   fields left without instances. Defaults to TRUE.
       
   767  */
       
   768 function field_delete_instance($instance, $field_cleanup = TRUE) {
       
   769   // Mark the field instance for deletion.
       
   770   db_update('field_config_instance')
       
   771     ->fields(array('deleted' => 1))
       
   772     ->condition('field_name', $instance['field_name'])
       
   773     ->condition('entity_type', $instance['entity_type'])
       
   774     ->condition('bundle', $instance['bundle'])
       
   775     ->execute();
       
   776 
       
   777   // Clear the cache.
       
   778   field_cache_clear();
       
   779 
       
   780   // Mark instance data for deletion.
       
   781   $field = field_info_field($instance['field_name']);
       
   782   module_invoke($field['storage']['module'], 'field_storage_delete_instance', $instance);
       
   783 
       
   784   // Let modules react to the deletion of the instance.
       
   785   module_invoke_all('field_delete_instance', $instance);
       
   786 
       
   787   // Delete the field itself if we just deleted its last instance.
       
   788   if ($field_cleanup && count($field['bundles']) == 0) {
       
   789     field_delete_field($field['field_name']);
       
   790   }
       
   791 }
       
   792 
       
   793 /**
       
   794  * @} End of "defgroup field_crud".
       
   795  */
       
   796 
       
   797 /**
       
   798  * @defgroup field_purge Field API bulk data deletion
       
   799  * @{
       
   800  * Clean up after Field API bulk deletion operations.
       
   801  *
       
   802  * Field API provides functions for deleting data attached to individual
       
   803  * entities as well as deleting entire fields or field instances in a single
       
   804  * operation.
       
   805  *
       
   806  * Deleting field data items for an entity with field_attach_delete() involves
       
   807  * three separate operations:
       
   808  * - Invoking the Field Type API hook_field_delete() for each field on the
       
   809  * entity. The hook for each field type receives the entity and the specific
       
   810  * field being deleted. A file field module might use this hook to delete
       
   811  * uploaded files from the filesystem.
       
   812  * - Invoking the Field Storage API hook_field_storage_delete() to remove
       
   813  * data from the primary field storage. The hook implementation receives the
       
   814  * entity being deleted and deletes data for all of the entity's bundle's
       
   815  * fields.
       
   816  * - Invoking the global Field Attach API hook_field_attach_delete() for all
       
   817  * modules that implement it. Each hook implementation receives the entity
       
   818  * being deleted and can operate on whichever subset of the entity's bundle's
       
   819  * fields it chooses to.
       
   820  *
       
   821  * These hooks are invoked immediately when field_attach_delete() is
       
   822  * called. Similar operations are performed for field_attach_delete_revision().
       
   823  *
       
   824  * When a field, bundle, or field instance is deleted, it is not practical to
       
   825  * invoke these hooks immediately on every affected entity in a single page
       
   826  * request; there could be thousands or millions of them. Instead, the
       
   827  * appropriate field data items, instances, and/or fields are marked as deleted
       
   828  * so that subsequent load or query operations will not return them. Later, a
       
   829  * separate process cleans up, or "purges", the marked-as-deleted data by going
       
   830  * through the three-step process described above and, finally, removing
       
   831  * deleted field and instance records.
       
   832  *
       
   833  * Purging field data is made somewhat tricky by the fact that, while
       
   834  * field_attach_delete() has a complete entity to pass to the various deletion
       
   835  * hooks, the Field API purge process only has the field data it has previously
       
   836  * stored. It cannot reconstruct complete original entities to pass to the
       
   837  * deletion hooks. It is even possible that the original entity to which some
       
   838  * Field API data was attached has been itself deleted before the field purge
       
   839  * operation takes place.
       
   840  *
       
   841  * Field API resolves this problem by using "pseudo-entities" during purge
       
   842  * operations. A pseudo-entity contains only the information from the original
       
   843  * entity that Field API knows about: entity type, id, revision id, and
       
   844  * bundle. It also contains the field data for whichever field instance is
       
   845  * currently being purged. For example, suppose that the node type 'story' used
       
   846  * to contain a field called 'subtitle' but the field was deleted. If node 37
       
   847  * was a story with a subtitle, the pseudo-entity passed to the purge hooks
       
   848  * would look something like this:
       
   849  *
       
   850  * @code
       
   851  *   $entity = stdClass Object(
       
   852  *     [nid] => 37,
       
   853  *     [vid] => 37,
       
   854  *     [type] => 'story',
       
   855  *     [subtitle] => array(
       
   856  *       [0] => array(
       
   857  *         'value' => 'subtitle text',
       
   858  *       ),
       
   859  *     ),
       
   860  *   );
       
   861  * @endcode
       
   862  *
       
   863  * See @link field Field API @endlink for information about the other parts of
       
   864  * the Field API.
       
   865  */
       
   866 
       
   867 /**
       
   868  * Purges a batch of deleted Field API data, instances, or fields.
       
   869  *
       
   870  * This function will purge deleted field data in batches. The batch size
       
   871  * is defined as an argument to the function, and once each batch is finished,
       
   872  * it continues with the next batch until all have completed. If a deleted field
       
   873  * instance with no remaining data records is found, the instance itself will
       
   874  * be purged. If a deleted field with no remaining field instances is found, the
       
   875  * field itself will be purged.
       
   876  *
       
   877  * @param $batch_size
       
   878  *   The maximum number of field data records to purge before returning.
       
   879  */
       
   880 function field_purge_batch($batch_size) {
       
   881   // Retrieve all deleted field instances. We cannot use field_info_instances()
       
   882   // because that function does not return deleted instances.
       
   883   $instances = field_read_instances(array('deleted' => 1), array('include_deleted' => 1));
       
   884 
       
   885   foreach ($instances as $instance) {
       
   886     // field_purge_data() will need the field array.
       
   887     $field = field_info_field_by_id($instance['field_id']);
       
   888     // Retrieve some entities.
       
   889     $query = new EntityFieldQuery();
       
   890     $results = $query
       
   891       ->fieldCondition($field)
       
   892       ->entityCondition('bundle', $instance['bundle'])
       
   893       ->deleted(TRUE)
       
   894       ->range(0, $batch_size)
       
   895       ->execute();
       
   896 
       
   897     if ($results) {
       
   898       foreach ($results as $entity_type => $stub_entities) {
       
   899         field_attach_load($entity_type, $stub_entities, FIELD_LOAD_CURRENT, array('field_id' => $field['id'], 'deleted' => 1));
       
   900         foreach ($stub_entities as $stub_entity) {
       
   901           // Purge the data for the entity.
       
   902           field_purge_data($entity_type, $stub_entity, $field, $instance);
       
   903         }
       
   904       }
       
   905     }
       
   906     else {
       
   907       // No field data remains for the instance, so we can remove it.
       
   908       field_purge_instance($instance);
       
   909     }
       
   910   }
       
   911 
       
   912   // Retrieve all deleted fields. Any that have no instances can be purged.
       
   913   $fields = field_read_fields(array('deleted' => 1), array('include_deleted' => 1));
       
   914   foreach ($fields as $field) {
       
   915     $instances = field_read_instances(array('field_id' => $field['id']), array('include_deleted' => 1));
       
   916     if (empty($instances)) {
       
   917       field_purge_field($field);
       
   918     }
       
   919   }
       
   920 }
       
   921 
       
   922 /**
       
   923  * Purges the field data for a single field on a single pseudo-entity.
       
   924  *
       
   925  * This is basically the same as field_attach_delete() except it only applies
       
   926  * to a single field. The entity itself is not being deleted, and it is quite
       
   927  * possible that other field data will remain attached to it.
       
   928  *
       
   929  * @param $entity_type
       
   930  *   The type of $entity; e.g. 'node' or 'user'.
       
   931  * @param $entity
       
   932  *   The pseudo-entity whose field data is being purged.
       
   933  * @param $field
       
   934  *   The (possibly deleted) field whose data is being purged.
       
   935  * @param $instance
       
   936  *   The deleted field instance whose data is being purged.
       
   937  */
       
   938 function field_purge_data($entity_type, $entity, $field, $instance) {
       
   939   // Each field type's hook_field_delete() only expects to operate on a single
       
   940   // field at a time, so we can use it as-is for purging.
       
   941   $options = array('field_id' => $instance['field_id'], 'deleted' => TRUE);
       
   942   _field_invoke('delete', $entity_type, $entity, $dummy, $dummy, $options);
       
   943 
       
   944   // Tell the field storage system to purge the data.
       
   945   module_invoke($field['storage']['module'], 'field_storage_purge', $entity_type, $entity, $field, $instance);
       
   946 
       
   947   // Let other modules act on purging the data.
       
   948   foreach (module_implements('field_attach_purge') as $module) {
       
   949     $function = $module . '_field_attach_purge';
       
   950     $function($entity_type, $entity, $field, $instance);
       
   951   }
       
   952 }
       
   953 
       
   954 /**
       
   955  * Purges a field instance record from the database.
       
   956  *
       
   957  * This function assumes all data for the instance has already been purged, and
       
   958  * should only be called by field_purge_batch().
       
   959  *
       
   960  * @param $instance
       
   961  *   The instance record to purge.
       
   962  */
       
   963 function field_purge_instance($instance) {
       
   964   db_delete('field_config_instance')
       
   965     ->condition('id', $instance['id'])
       
   966     ->execute();
       
   967 
       
   968   // Notify the storage engine.
       
   969   $field = field_info_field_by_id($instance['field_id']);
       
   970   module_invoke($field['storage']['module'], 'field_storage_purge_instance', $instance);
       
   971 
       
   972   // Clear the cache.
       
   973   field_info_cache_clear();
       
   974 
       
   975   // Invoke external hooks after the cache is cleared for API consistency.
       
   976   module_invoke_all('field_purge_instance', $instance);
       
   977 }
       
   978 
       
   979 /**
       
   980  * Purges a field record from the database.
       
   981  *
       
   982  * This function assumes all instances for the field has already been purged,
       
   983  * and should only be called by field_purge_batch().
       
   984  *
       
   985  * @param $field
       
   986  *   The field record to purge.
       
   987  */
       
   988 function field_purge_field($field) {
       
   989   $instances = field_read_instances(array('field_id' => $field['id']), array('include_deleted' => 1));
       
   990   if (count($instances) > 0) {
       
   991     throw new FieldException(t('Attempt to purge a field @field_name that still has instances.', array('@field_name' => $field['field_name'])));
       
   992   }
       
   993 
       
   994   db_delete('field_config')
       
   995     ->condition('id', $field['id'])
       
   996     ->execute();
       
   997 
       
   998   // Notify the storage engine.
       
   999   module_invoke($field['storage']['module'], 'field_storage_purge_field', $field);
       
  1000 
       
  1001   // Clear the cache.
       
  1002   field_info_cache_clear();
       
  1003 
       
  1004   // Invoke external hooks after the cache is cleared for API consistency.
       
  1005   module_invoke_all('field_purge_field', $field);
       
  1006 }
       
  1007 
       
  1008 /**
       
  1009  * @} End of "defgroup field_purge".
       
  1010  */