Drupal PHP Cross Reference Content Management Systems

Source: /modules/field/modules/field_sql_storage/field_sql_storage.module - 755 lines - 27054 bytes - Summary - Text - Print

   1  <?php
   2  
   3  /**
   4   * @file
   5   * Default implementation of the field storage API.
   6   */
   7  
   8  /**
   9   * Implements hook_help().
  10   */
  11  function field_sql_storage_help($path, $arg) {
  12    switch ($path) {
  13      case 'admin/help#field_sql_storage':
  14        $output = '';
  15        $output .= '<h3>' . t('About') . '</h3>';
  16        $output .= '<p>' . t('The Field SQL storage module stores field data in the database. It is the default field storage module; other field storage mechanisms may be available as contributed modules. See the <a href="@field-help">Field module help page</a> for more information about fields.', array('@field-help' => url('admin/help/field'))) . '</p>';
  17        return $output;
  18    }
  19  }
  20  
  21  /**
  22   * Implements hook_field_storage_info().
  23   */
  24  function field_sql_storage_field_storage_info() {
  25    return array(
  26      'field_sql_storage' => array(
  27        'label' => t('Default SQL storage'),
  28        'description' => t('Stores fields in the local SQL database, using per-field tables.'),
  29      ),
  30    );
  31  }
  32  
  33  /**
  34   * Generate a table name for a field data table.
  35   *
  36   * @param $field
  37   *   The field structure.
  38   * @return
  39   *   A string containing the generated name for the database table
  40   */
  41  function _field_sql_storage_tablename($field) {
  42    if ($field['deleted']) {
  43      return "field_deleted_data_{$field['id']}";
  44    }
  45    else {
  46      return "field_data_{$field['field_name']}";
  47    }
  48  }
  49  
  50  /**
  51   * Generate a table name for a field revision archive table.
  52   *
  53   * @param $name
  54   *   The field structure.
  55   * @return
  56   *   A string containing the generated name for the database table
  57   */
  58  function _field_sql_storage_revision_tablename($field) {
  59    if ($field['deleted']) {
  60      return "field_deleted_revision_{$field['id']}";
  61    }
  62    else {
  63      return "field_revision_{$field['field_name']}";
  64    }
  65  }
  66  
  67  /**
  68   * Generate a column name for a field data table.
  69   *
  70   * @param $name
  71   *   The name of the field
  72   * @param $column
  73   *   The name of the column
  74   * @return
  75   *   A string containing a generated column name for a field data
  76   *   table that is unique among all other fields.
  77   */
  78  function _field_sql_storage_columnname($name, $column) {
  79    return $name . '_' . $column;
  80  }
  81  
  82  /**
  83   * Generate an index name for a field data table.
  84   *
  85   * @param $name
  86   *   The name of the field
  87   * @param $column
  88   *   The name of the index
  89   * @return
  90   *   A string containing a generated index name for a field data
  91   *   table that is unique among all other fields.
  92   */
  93  function _field_sql_storage_indexname($name, $index) {
  94    return $name . '_' . $index;
  95  }
  96  
  97  /**
  98   * Return the database schema for a field. This may contain one or
  99   * more tables. Each table will contain the columns relevant for the
 100   * specified field. Leave the $field's 'columns' and 'indexes' keys
 101   * empty to get only the base schema.
 102   *
 103   * @param $field
 104   *   The field structure for which to generate a database schema.
 105   * @return
 106   *   One or more tables representing the schema for the field.
 107   */
 108  function _field_sql_storage_schema($field) {
 109    $deleted = $field['deleted'] ? 'deleted ' : '';
 110    $current = array(
 111      'description' => "Data storage for {$deleted}field {$field['id']} ({$field['field_name']})",
 112      'fields' => array(
 113        'entity_type' => array(
 114          'type' => 'varchar',
 115          'length' => 128,
 116          'not null' => TRUE,
 117          'default' => '',
 118          'description' => 'The entity type this data is attached to',
 119        ),
 120        'bundle' => array(
 121          'type' => 'varchar',
 122          'length' => 128,
 123          'not null' => TRUE,
 124          'default' => '',
 125          'description' => 'The field instance bundle to which this row belongs, used when deleting a field instance',
 126        ),
 127        'deleted' => array(
 128          'type' => 'int',
 129          'size' => 'tiny',
 130          'not null' => TRUE,
 131          'default' => 0,
 132          'description' => 'A boolean indicating whether this data item has been deleted'
 133        ),
 134        'entity_id' => array(
 135          'type' => 'int',
 136          'unsigned' => TRUE,
 137          'not null' => TRUE,
 138          'description' => 'The entity id this data is attached to',
 139        ),
 140        'revision_id' => array(
 141          'type' => 'int',
 142          'unsigned' => TRUE,
 143          'not null' => FALSE,
 144          'description' => 'The entity revision id this data is attached to, or NULL if the entity type is not versioned',
 145        ),
 146        // @todo Consider storing language as integer.
 147        'language' => array(
 148          'type' => 'varchar',
 149          'length' => 32,
 150          'not null' => TRUE,
 151          'default' => '',
 152          'description' => 'The language for this data item.',
 153        ),
 154        'delta' => array(
 155          'type' => 'int',
 156          'unsigned' => TRUE,
 157          'not null' => TRUE,
 158          'description' => 'The sequence number for this data item, used for multi-value fields',
 159        ),
 160      ),
 161      'primary key' => array('entity_type', 'entity_id', 'deleted', 'delta', 'language'),
 162      'indexes' => array(
 163        'entity_type' => array('entity_type'),
 164        'bundle' => array('bundle'),
 165        'deleted' => array('deleted'),
 166        'entity_id' => array('entity_id'),
 167        'revision_id' => array('revision_id'),
 168        'language' => array('language'),
 169      ),
 170    );
 171  
 172    $field += array('columns' => array(), 'indexes' => array(), 'foreign keys' => array());
 173    // Add field columns.
 174    foreach ($field['columns'] as $column_name => $attributes) {
 175      $real_name = _field_sql_storage_columnname($field['field_name'], $column_name);
 176      $current['fields'][$real_name] = $attributes;
 177    }
 178  
 179    // Add indexes.
 180    foreach ($field['indexes'] as $index_name => $columns) {
 181      $real_name = _field_sql_storage_indexname($field['field_name'], $index_name);
 182      foreach ($columns as $column_name) {
 183        $current['indexes'][$real_name][] = _field_sql_storage_columnname($field['field_name'], $column_name);
 184      }
 185    }
 186  
 187    // Add foreign keys.
 188    foreach ($field['foreign keys'] as $specifier => $specification) {
 189      $real_name = _field_sql_storage_indexname($field['field_name'], $specifier);
 190      $current['foreign keys'][$real_name]['table'] = $specification['table'];
 191      foreach ($specification['columns'] as $column => $referenced) {
 192        $sql_storage_column = _field_sql_storage_columnname($field['field_name'], $column_name);
 193        $current['foreign keys'][$real_name]['columns'][$sql_storage_column] = $referenced;
 194      }
 195    }
 196  
 197    // Construct the revision table.
 198    $revision = $current;
 199    $revision['description'] = "Revision archive storage for {$deleted}field {$field['id']} ({$field['field_name']})";
 200    $revision['primary key'] = array('entity_type', 'entity_id', 'revision_id', 'deleted', 'delta', 'language');
 201    $revision['fields']['revision_id']['not null'] = TRUE;
 202    $revision['fields']['revision_id']['description'] = 'The entity revision id this data is attached to';
 203  
 204    return array(
 205      _field_sql_storage_tablename($field) => $current,
 206      _field_sql_storage_revision_tablename($field) => $revision,
 207    );
 208  }
 209  
 210  /**
 211   * Implements hook_field_storage_create_field().
 212   */
 213  function field_sql_storage_field_storage_create_field($field) {
 214    $schema = _field_sql_storage_schema($field);
 215    foreach ($schema as $name => $table) {
 216      db_create_table($name, $table);
 217    }
 218    drupal_get_schema(NULL, TRUE);
 219  }
 220  
 221  /**
 222   * Implements hook_field_update_forbid().
 223   *
 224   * Forbid any field update that changes column definitions if there is
 225   * any data.
 226   */
 227  function field_sql_storage_field_update_forbid($field, $prior_field, $has_data) {
 228    if ($has_data && $field['columns'] != $prior_field['columns']) {
 229      throw new FieldUpdateForbiddenException("field_sql_storage cannot change the schema for an existing field with data.");
 230    }
 231  }
 232  
 233  /**
 234   * Implements hook_field_storage_update_field().
 235   */
 236  function field_sql_storage_field_storage_update_field($field, $prior_field, $has_data) {
 237    if (! $has_data) {
 238      // There is no data. Re-create the tables completely.
 239  
 240      if (Database::getConnection()->supportsTransactionalDDL()) {
 241        // If the database supports transactional DDL, we can go ahead and rely
 242        // on it. If not, we will have to rollback manually if something fails.
 243        $transaction = db_transaction();
 244      }
 245  
 246      try {
 247        $prior_schema = _field_sql_storage_schema($prior_field);
 248        foreach ($prior_schema as $name => $table) {
 249          db_drop_table($name, $table);
 250        }
 251        $schema = _field_sql_storage_schema($field);
 252        foreach ($schema as $name => $table) {
 253          db_create_table($name, $table);
 254        }
 255      }
 256      catch (Exception $e) {
 257        if (Database::getConnection()->supportsTransactionalDDL()) {
 258          $transaction->rollback();
 259        }
 260        else {
 261          // Recreate tables.
 262          $prior_schema = _field_sql_storage_schema($prior_field);
 263          foreach ($prior_schema as $name => $table) {
 264            if (!db_table_exists($name)) {
 265              db_create_table($name, $table);
 266            }
 267          }
 268        }
 269        throw $e;
 270      }
 271    }
 272    else {
 273      // There is data, so there are no column changes. Drop all the
 274      // prior indexes and create all the new ones, except for all the
 275      // priors that exist unchanged.
 276      $table = _field_sql_storage_tablename($prior_field);
 277      $revision_table = _field_sql_storage_revision_tablename($prior_field);
 278      foreach ($prior_field['indexes'] as $name => $columns) {
 279        if (!isset($field['indexes'][$name]) || $columns != $field['indexes'][$name]) {
 280          $real_name = _field_sql_storage_indexname($field['field_name'], $name);
 281          db_drop_index($table, $real_name);
 282          db_drop_index($revision_table, $real_name);
 283        }
 284      }
 285      $table = _field_sql_storage_tablename($field);
 286      $revision_table = _field_sql_storage_revision_tablename($field);
 287      foreach ($field['indexes'] as $name => $columns) {
 288        if (!isset($prior_field['indexes'][$name]) || $columns != $prior_field['indexes'][$name]) {
 289          $real_name = _field_sql_storage_indexname($field['field_name'], $name);
 290          $real_columns = array();
 291          foreach ($columns as $column_name) {
 292            $real_columns[] = _field_sql_storage_columnname($field['field_name'], $column_name);
 293          }
 294          db_add_index($table, $real_name, $real_columns);
 295          db_add_index($revision_table, $real_name, $real_columns);
 296        }
 297      }
 298    }
 299    drupal_get_schema(NULL, TRUE);
 300  }
 301  
 302  /**
 303   * Implements hook_field_storage_delete_field().
 304   */
 305  function field_sql_storage_field_storage_delete_field($field) {
 306    // Mark all data associated with the field for deletion.
 307    $field['deleted'] = 0;
 308    $table = _field_sql_storage_tablename($field);
 309    $revision_table = _field_sql_storage_revision_tablename($field);
 310    db_update($table)
 311      ->fields(array('deleted' => 1))
 312      ->execute();
 313  
 314    // Move the table to a unique name while the table contents are being deleted.
 315    $field['deleted'] = 1;
 316    $new_table = _field_sql_storage_tablename($field);
 317    $revision_new_table = _field_sql_storage_revision_tablename($field);
 318    db_rename_table($table, $new_table);
 319    db_rename_table($revision_table, $revision_new_table);
 320    drupal_get_schema(NULL, TRUE);
 321  }
 322  
 323  /**
 324   * Implements hook_field_storage_load().
 325   */
 326  function field_sql_storage_field_storage_load($entity_type, $entities, $age, $fields, $options) {
 327    $field_info = field_info_field_by_ids();
 328    $load_current = $age == FIELD_LOAD_CURRENT;
 329  
 330    foreach ($fields as $field_id => $ids) {
 331      $field = $field_info[$field_id];
 332      $field_name = $field['field_name'];
 333      $table = $load_current ? _field_sql_storage_tablename($field) : _field_sql_storage_revision_tablename($field);
 334  
 335      $query = db_select($table, 't')
 336        ->fields('t')
 337        ->condition('entity_type', $entity_type)
 338        ->condition($load_current ? 'entity_id' : 'revision_id', $ids, 'IN')
 339        ->condition('language', field_available_languages($entity_type, $field), 'IN')
 340        ->orderBy('delta');
 341  
 342      if (empty($options['deleted'])) {
 343        $query->condition('deleted', 0);
 344      }
 345  
 346      $results = $query->execute();
 347  
 348      $delta_count = array();
 349      foreach ($results as $row) {
 350        if (!isset($delta_count[$row->entity_id][$row->language])) {
 351          $delta_count[$row->entity_id][$row->language] = 0;
 352        }
 353  
 354        if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED || $delta_count[$row->entity_id][$row->language] < $field['cardinality']) {
 355          $item = array();
 356          // For each column declared by the field, populate the item
 357          // from the prefixed database column.
 358          foreach ($field['columns'] as $column => $attributes) {
 359            $column_name = _field_sql_storage_columnname($field_name, $column);
 360            $item[$column] = $row->$column_name;
 361          }
 362  
 363          // Add the item to the field values for the entity.
 364          $entities[$row->entity_id]->{$field_name}[$row->language][] = $item;
 365          $delta_count[$row->entity_id][$row->language]++;
 366        }
 367      }
 368    }
 369  }
 370  
 371  /**
 372   * Implements hook_field_storage_write().
 373   */
 374  function field_sql_storage_field_storage_write($entity_type, $entity, $op, $fields) {
 375    list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
 376    if (!isset($vid)) {
 377      $vid = $id;
 378    }
 379  
 380    foreach ($fields as $field_id) {
 381      $field = field_info_field_by_id($field_id);
 382      $field_name = $field['field_name'];
 383      $table_name = _field_sql_storage_tablename($field);
 384      $revision_name = _field_sql_storage_revision_tablename($field);
 385  
 386      $all_languages = field_available_languages($entity_type, $field);
 387      $field_languages = array_intersect($all_languages, array_keys((array) $entity->$field_name));
 388  
 389      // Delete and insert, rather than update, in case a value was added.
 390      if ($op == FIELD_STORAGE_UPDATE) {
 391        // Delete languages present in the incoming $entity->$field_name.
 392        // Delete all languages if $entity->$field_name is empty.
 393        $languages = !empty($entity->$field_name) ? $field_languages : $all_languages;
 394        if ($languages) {
 395          db_delete($table_name)
 396            ->condition('entity_type', $entity_type)
 397            ->condition('entity_id', $id)
 398            ->condition('language', $languages, 'IN')
 399            ->execute();
 400          db_delete($revision_name)
 401            ->condition('entity_type', $entity_type)
 402            ->condition('entity_id', $id)
 403            ->condition('revision_id', $vid)
 404            ->condition('language', $languages, 'IN')
 405            ->execute();
 406        }
 407      }
 408  
 409      // Prepare the multi-insert query.
 410      $do_insert = FALSE;
 411      $columns = array('entity_type', 'entity_id', 'revision_id', 'bundle', 'delta', 'language');
 412      foreach ($field['columns'] as $column => $attributes) {
 413        $columns[] = _field_sql_storage_columnname($field_name, $column);
 414      }
 415      $query = db_insert($table_name)->fields($columns);
 416      $revision_query = db_insert($revision_name)->fields($columns);
 417  
 418      foreach ($field_languages as $langcode) {
 419        $items = (array) $entity->{$field_name}[$langcode];
 420        $delta_count = 0;
 421        foreach ($items as $delta => $item) {
 422          // We now know we have someting to insert.
 423          $do_insert = TRUE;
 424          $record = array(
 425            'entity_type' => $entity_type,
 426            'entity_id' => $id,
 427            'revision_id' => $vid,
 428            'bundle' => $bundle,
 429            'delta' => $delta,
 430            'language' => $langcode,
 431          );
 432          foreach ($field['columns'] as $column => $attributes) {
 433            $record[_field_sql_storage_columnname($field_name, $column)] = isset($item[$column]) ? $item[$column] : NULL;
 434          }
 435          $query->values($record);
 436          if (isset($vid)) {
 437            $revision_query->values($record);
 438          }
 439  
 440          if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED && ++$delta_count == $field['cardinality']) {
 441            break;
 442          }
 443        }
 444      }
 445  
 446      // Execute the query if we have values to insert.
 447      if ($do_insert) {
 448        $query->execute();
 449        $revision_query->execute();
 450      }
 451    }
 452  }
 453  
 454  /**
 455   * Implements hook_field_storage_delete().
 456   *
 457   * This function deletes data for all fields for an entity from the database.
 458   */
 459  function field_sql_storage_field_storage_delete($entity_type, $entity, $fields) {
 460    list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
 461  
 462    foreach (field_info_instances($entity_type, $bundle) as $instance) {
 463      if (isset($fields[$instance['field_id']])) {
 464        $field = field_info_field_by_id($instance['field_id']);
 465        field_sql_storage_field_storage_purge($entity_type, $entity, $field, $instance);
 466      }
 467    }
 468  }
 469  
 470  /**
 471   * Implements hook_field_storage_purge().
 472   *
 473   * This function deletes data from the database for a single field on
 474   * an entity.
 475   */
 476  function field_sql_storage_field_storage_purge($entity_type, $entity, $field, $instance) {
 477    list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
 478  
 479    $table_name = _field_sql_storage_tablename($field);
 480    $revision_name = _field_sql_storage_revision_tablename($field);
 481    db_delete($table_name)
 482      ->condition('entity_type', $entity_type)
 483      ->condition('entity_id', $id)
 484      ->execute();
 485    db_delete($revision_name)
 486      ->condition('entity_type', $entity_type)
 487      ->condition('entity_id', $id)
 488      ->execute();
 489  }
 490  
 491  /**
 492   * Implements hook_field_storage_query().
 493   */
 494  function field_sql_storage_field_storage_query(EntityFieldQuery $query) {
 495    if ($query->age == FIELD_LOAD_CURRENT) {
 496      $tablename_function = '_field_sql_storage_tablename';
 497      $id_key = 'entity_id';
 498    }
 499    else {
 500      $tablename_function = '_field_sql_storage_revision_tablename';
 501      $id_key = 'revision_id';
 502    }
 503    $table_aliases = array();
 504    // Add tables for the fields used.
 505    foreach ($query->fields as $key => $field) {
 506      $tablename = $tablename_function($field);
 507      // Every field needs a new table.
 508      $table_alias = $tablename . $key;
 509      $table_aliases[$key] = $table_alias;
 510      if ($key) {
 511        $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");
 512      }
 513      else {
 514        $select_query = db_select($tablename, $table_alias);
 515        // Allow queries internal to the Field API to opt out of the access
 516        // check, for situations where the query's results should not depend on
 517        // the access grants for the current user.
 518        if (!isset($query->tags['DANGEROUS_ACCESS_CHECK_OPT_OUT'])) {
 519          $select_query->addTag('entity_field_access');
 520        }
 521        $select_query->addMetaData('base_table', $tablename);
 522        $select_query->fields($table_alias, array('entity_type', 'entity_id', 'revision_id', 'bundle'));
 523        $field_base_table = $table_alias;
 524      }
 525      if ($field['cardinality'] != 1 || $field['translatable']) {
 526        $select_query->distinct();
 527      }
 528    }
 529  
 530    // Add field conditions. We need a fresh grouping cache.
 531    drupal_static_reset('_field_sql_storage_query_field_conditions');
 532    _field_sql_storage_query_field_conditions($query, $select_query, $query->fieldConditions, $table_aliases, '_field_sql_storage_columnname');
 533  
 534    // Add field meta conditions.
 535    _field_sql_storage_query_field_conditions($query, $select_query, $query->fieldMetaConditions, $table_aliases, '_field_sql_storage_query_columnname');
 536  
 537    if (isset($query->deleted)) {
 538      $select_query->condition("$field_base_table.deleted", (int) $query->deleted);
 539    }
 540  
 541    // Is there a need to sort the query by property?
 542    $has_property_order = FALSE;
 543    foreach ($query->order as $order) {
 544      if ($order['type'] == 'property') {
 545        $has_property_order = TRUE;
 546      }
 547    }
 548  
 549    if ($query->propertyConditions || $has_property_order) {
 550      if (empty($query->entityConditions['entity_type']['value'])) {
 551        throw new EntityFieldQueryException('Property conditions and orders must have an entity type defined.');
 552      }
 553      $entity_type = $query->entityConditions['entity_type']['value'];
 554      $entity_base_table = _field_sql_storage_query_join_entity($select_query, $entity_type, $field_base_table);
 555      $query->entityConditions['entity_type']['operator'] = '=';
 556      foreach ($query->propertyConditions as $property_condition) {
 557        $query->addCondition($select_query, "$entity_base_table." . $property_condition['column'], $property_condition);
 558      }
 559    }
 560    foreach ($query->entityConditions as $key => $condition) {
 561      $query->addCondition($select_query, "$field_base_table.$key", $condition);
 562    }
 563  
 564    // Order the query.
 565    foreach ($query->order as $order) {
 566      if ($order['type'] == 'entity') {
 567        $key = $order['specifier'];
 568        $select_query->orderBy("$field_base_table.$key", $order['direction']);
 569      }
 570      elseif ($order['type'] == 'field') {
 571        $specifier = $order['specifier'];
 572        $field = $specifier['field'];
 573        $table_alias = $table_aliases[$specifier['index']];
 574        $sql_field = "$table_alias." . _field_sql_storage_columnname($field['field_name'], $specifier['column']);
 575        $select_query->orderBy($sql_field, $order['direction']);
 576      }
 577      elseif ($order['type'] == 'property') {
 578        $select_query->orderBy("$entity_base_table." . $order['specifier'], $order['direction']);
 579      }
 580    }
 581  
 582    return $query->finishQuery($select_query, $id_key);
 583  }
 584  
 585  /**
 586   * Adds the base entity table to a field query object.
 587   *
 588   * @param SelectQuery $select_query
 589   *   A SelectQuery containing at least one table as specified by
 590   *   _field_sql_storage_tablename().
 591   * @param $entity_type
 592   *   The entity type for which the base table should be joined.
 593   * @param $field_base_table
 594   *   Name of a table in $select_query. As only INNER JOINs are used, it does
 595   *   not matter which.
 596   *
 597   * @return
 598   *   The name of the entity base table joined in.
 599   */
 600  function _field_sql_storage_query_join_entity(SelectQuery $select_query, $entity_type, $field_base_table) {
 601    $entity_info = entity_get_info($entity_type);
 602    $entity_base_table = $entity_info['base table'];
 603    $entity_field = $entity_info['entity keys']['id'];
 604    $select_query->join($entity_base_table, $entity_base_table, "$entity_base_table.$entity_field = $field_base_table.entity_id");
 605    return $entity_base_table;
 606  }
 607  
 608  /**
 609   * Adds field (meta) conditions to the given query objects respecting groupings.
 610   *
 611   * @param EntityFieldQuery $query
 612   *   The field query object to be processed.
 613   * @param SelectQuery $select_query
 614   *   The SelectQuery that should get grouping conditions.
 615   * @param condtions
 616   *   The conditions to be added.
 617   * @param $table_aliases
 618   *   An associative array of table aliases keyed by field index.
 619   * @param $column_callback
 620   *   A callback that should return the column name to be used for the field
 621   *   conditions. Accepts a field name and a field column name as parameters.
 622   */
 623  function _field_sql_storage_query_field_conditions(EntityFieldQuery $query, SelectQuery $select_query, $conditions, $table_aliases, $column_callback) {
 624    $groups = &drupal_static(__FUNCTION__, array());
 625    foreach ($conditions as $key => $condition) {
 626      $table_alias = $table_aliases[$key];
 627      $field = $condition['field'];
 628      // Add the specified condition.
 629      $sql_field = "$table_alias." . $column_callback($field['field_name'], $condition['column']);
 630      $query->addCondition($select_query, $sql_field, $condition);
 631      // Add delta / language group conditions.
 632      foreach (array('delta', 'language') as $column) {
 633        if (isset($condition[$column . '_group'])) {
 634          $group_name = $condition[$column . '_group'];
 635          if (!isset($groups[$column][$group_name])) {
 636            $groups[$column][$group_name] = $table_alias;
 637          }
 638          else {
 639            $select_query->where("$table_alias.$column = " . $groups[$column][$group_name] . ".$column");
 640          }
 641        }
 642      }
 643    }
 644  }
 645  
 646  /**
 647   * Field meta condition column callback.
 648   */
 649  function _field_sql_storage_query_columnname($field_name, $column) {
 650    return $column;
 651  }
 652  
 653  /**
 654   * Implements hook_field_storage_delete_revision().
 655   *
 656   * This function actually deletes the data from the database.
 657   */
 658  function field_sql_storage_field_storage_delete_revision($entity_type, $entity, $fields) {
 659    list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
 660  
 661    if (isset($vid)) {
 662      foreach ($fields as $field_id) {
 663        $field = field_info_field_by_id($field_id);
 664        $revision_name = _field_sql_storage_revision_tablename($field);
 665        db_delete($revision_name)
 666          ->condition('entity_type', $entity_type)
 667          ->condition('entity_id', $id)
 668          ->condition('revision_id', $vid)
 669          ->execute();
 670      }
 671    }
 672  }
 673  
 674  /**
 675   * Implements hook_field_storage_delete_instance().
 676   *
 677   * This function simply marks for deletion all data associated with the field.
 678   */
 679  function field_sql_storage_field_storage_delete_instance($instance) {
 680    $field = field_info_field($instance['field_name']);
 681    $table_name = _field_sql_storage_tablename($field);
 682    $revision_name = _field_sql_storage_revision_tablename($field);
 683    db_update($table_name)
 684      ->fields(array('deleted' => 1))
 685      ->condition('entity_type', $instance['entity_type'])
 686      ->condition('bundle', $instance['bundle'])
 687      ->execute();
 688    db_update($revision_name)
 689      ->fields(array('deleted' => 1))
 690      ->condition('entity_type', $instance['entity_type'])
 691      ->condition('bundle', $instance['bundle'])
 692      ->execute();
 693  }
 694  
 695  /**
 696   * Implements hook_field_attach_rename_bundle().
 697   */
 698  function field_sql_storage_field_attach_rename_bundle($entity_type, $bundle_old, $bundle_new) {
 699    // We need to account for deleted or inactive fields and instances.
 700    $instances = field_read_instances(array('entity_type' => $entity_type, 'bundle' => $bundle_new), array('include_deleted' => TRUE, 'include_inactive' => TRUE));
 701    foreach ($instances as $instance) {
 702      $field = field_info_field_by_id($instance['field_id']);
 703      if ($field['storage']['type'] == 'field_sql_storage') {
 704        $table_name = _field_sql_storage_tablename($field);
 705        $revision_name = _field_sql_storage_revision_tablename($field);
 706        db_update($table_name)
 707          ->fields(array('bundle' => $bundle_new))
 708          ->condition('entity_type', $entity_type)
 709          ->condition('bundle', $bundle_old)
 710          ->execute();
 711        db_update($revision_name)
 712          ->fields(array('bundle' => $bundle_new))
 713          ->condition('entity_type', $entity_type)
 714          ->condition('bundle', $bundle_old)
 715          ->execute();
 716      }
 717    }
 718  }
 719  
 720  /**
 721   * Implements hook_field_storage_purge_field().
 722   *
 723   * All field data items and instances have already been purged, so all
 724   * that is left is to delete the table.
 725   */
 726  function field_sql_storage_field_storage_purge_field($field) {
 727    $table_name = _field_sql_storage_tablename($field);
 728    $revision_name = _field_sql_storage_revision_tablename($field);
 729    db_drop_table($table_name);
 730    db_drop_table($revision_name);
 731  }
 732  
 733  /**
 734   * Implements hook_field_storage_details().
 735   */
 736  function field_sql_storage_field_storage_details($field) {
 737    $details = array();
 738    if (!empty($field['columns'])) {
 739       // Add field columns.
 740      foreach ($field['columns'] as $column_name => $attributes) {
 741        $real_name = _field_sql_storage_columnname($field['field_name'], $column_name);
 742        $columns[$column_name] = $real_name;
 743      }
 744      return array(
 745        'sql' => array(
 746          FIELD_LOAD_CURRENT => array(
 747            _field_sql_storage_tablename($field) => $columns,
 748          ),
 749          FIELD_LOAD_REVISION => array(
 750            _field_sql_storage_revision_tablename($field) => $columns,
 751          ),
 752        ),
 753      );
 754    }
 755  }

title

Description

title

Description

title

Description

title

title

Body