| Drupal | PHP Cross Reference | Content Management Systems |
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
Body
title
Description
Body
title
Description
Body
title
Body
title