| 198 |
} |
} |
| 199 |
|
|
| 200 |
/** |
/** |
| 201 |
* Synchronize a single bundle table from its constituent field |
* Initialize a single bundle table from its constituent field |
| 202 |
* tables. |
* tables. |
| 203 |
* |
* |
|
* TODO: Synchronize revisions. |
|
|
* TODO: This function has not been maintained and is probably out of |
|
|
* date/broken. |
|
|
* |
|
| 204 |
* @param $bundle |
* @param $bundle |
| 205 |
* The bundle to synchronize. |
* The bundle to initialize. |
| 206 |
*/ |
*/ |
| 207 |
function pbs_synchronize_bundle($bundle) { |
function pbs_initialize_bundle($bundle) { |
| 208 |
$bundle_table = pbs_tablename($bundle); |
$bundle_table = pbs_tablename($bundle); |
| 209 |
|
$revision_table = pbs_revision_tablename($bundle); |
| 210 |
|
|
| 211 |
$instances = field_info_instances($bundle); |
$instances = field_info_instances($bundle); |
| 212 |
foreach ($instances as $instance) { |
foreach ($instances as $instance) { |
| 213 |
$field = field_info_field($instance['field_name']); |
$field = field_info_field($instance['field_name']); |
|
$field_table = _field_sql_storage_tablename($field); |
|
| 214 |
if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED) { |
if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED) { |
| 215 |
$query = db_select($field_table, 't', array('fetch' => PDO::FETCH_ASSOC))->fields('t'); |
$field_table = _field_sql_storage_tablename($field); |
| 216 |
$results = $query->condition('bundle', $bundle)->execute(); |
$field_revision_table = _field_sql_storage_revision_tablename($field); |
| 217 |
|
_pbs_initialize_bundle_field($field, 'entity_id', $bundle_table, $field_table); |
| 218 |
$pkey = array('etid' => 0, 'entity_id' => 1); |
_pbs_initialize_bundle_field($field, 'entity_id', $revision_table, $field_revision_table); |
| 219 |
foreach ($results as $row) { |
} |
| 220 |
$delta = $row['delta']; |
} |
| 221 |
unset($row['bundle'], $row['delta'], $row['deleted']); |
} |
| 222 |
$keys = array_intersect_key($row, $pkey); |
|
| 223 |
foreach ($field['columns'] as $name => $spec) { |
function _pbs_initialize_bundle_field($field, $id_key, $bundle_table, $field_table) { |
| 224 |
$column_name = $field['field_name'] .'_'. $name; |
$pkey = array('etid' => 0, $id_key => 1, 'language' => 2); |
| 225 |
$row[$column_name .'_'. $delta] = $row[$column_name]; |
$results = db_select($field_table, 't', array('fetch' => PDO::FETCH_ASSOC)) |
| 226 |
unset($row[$column_name]); |
->fields('t') |
| 227 |
} |
->condition('bundle', $bundle) |
| 228 |
$query = db_merge($bundle_table)->fields($row)->key($keys); |
->condition('deleted', 0) |
| 229 |
$query->execute(); |
->execute(); |
| 230 |
} |
foreach ($results as $row) { |
| 231 |
|
$delta = $row['delta']; |
| 232 |
|
unset($row['bundle'], $row['delta'], $row['deleted']); |
| 233 |
|
$keys = array_intersect_key($row, $pkey); |
| 234 |
|
foreach ($field['columns'] as $name => $spec) { |
| 235 |
|
$column_name = $field['field_name'] .'_'. $name; |
| 236 |
|
$row[$column_name .'_'. $delta] = $row[$column_name]; |
| 237 |
|
unset($row[$column_name]); |
| 238 |
} |
} |
| 239 |
|
db_merge($bundle_table)->fields($row)->key($keys)->execute(); |
| 240 |
} |
} |
| 241 |
} |
} |
| 242 |
|
|
| 254 |
$bundle_ids = array(); |
$bundle_ids = array(); |
| 255 |
$delta_count = array(); |
$delta_count = array(); |
| 256 |
foreach ($objects as $obj) { |
foreach ($objects as $obj) { |
| 257 |
list($id, $vid, $bundle) = field_attach_extract_ids($obj_type, $obj); |
list($id, $vid, $bundle) = field_extract_ids($obj_type, $obj); |
| 258 |
$bundle_ids[$bundle][] = $load_current ? $id : $vid; |
$bundle_ids[$bundle][] = $load_current ? $id : $vid; |
| 259 |
} |
} |
| 260 |
|
|
| 277 |
->fields('t') |
->fields('t') |
| 278 |
->condition('etid', $etid) |
->condition('etid', $etid) |
| 279 |
->condition($load_current ? 'entity_id' : 'revision_id', $ids, 'IN') |
->condition($load_current ? 'entity_id' : 'revision_id', $ids, 'IN') |
|
// TODO ->condition('deleted', 0) |
|
| 280 |
->execute(); |
->execute(); |
| 281 |
|
|
| 282 |
// For each row, for every field in the bundle, construct field |
// For each row, for every field in the bundle, construct field |
| 326 |
*/ |
*/ |
| 327 |
function pbs_field_attach_pre_update($obj_type, $object, &$skip_fields) { |
function pbs_field_attach_pre_update($obj_type, $object, &$skip_fields) { |
| 328 |
$etid = _field_sql_storage_etid($obj_type); |
$etid = _field_sql_storage_etid($obj_type); |
| 329 |
list($id, $vid, $bundle, $cacheable) = field_attach_extract_ids($obj_type, $object); |
list($id, $vid, $bundle, $cacheable) = field_extract_ids($obj_type, $object); |
| 330 |
$bundle_table = pbs_tablename($bundle); |
$bundle_table = pbs_tablename($bundle); |
| 331 |
$revision_table = pbs_revision_tablename($bundle); |
$revision_table = pbs_revision_tablename($bundle); |
| 332 |
$all_fields = array(); |
$all_fields = array(); |
| 435 |
} |
} |
| 436 |
|
|
| 437 |
/** |
/** |
|
* Implement hook_field_storage_query(). |
|
|
* |
|
|
* To query a single field, query all the per-bundle tables in which |
|
|
* that field appears. Also, if the field's cardinality is greater |
|
|
* than 1, query all the columnname_N columns for each condition. |
|
|
*/ |
|
|
function x_pbs_field_attach_pre_query($field_name, $conditions, $result_format, $age, &$skip_field) { |
|
|
$field = field_info_field($field_name); |
|
|
// We do not store unlimited cardinality fields. |
|
|
if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED) { |
|
|
return; |
|
|
} |
|
|
// We store shared fields, but the base storage module does too, and |
|
|
// it will be able to make only one query instead of the multiple |
|
|
// queries we would need. |
|
|
if (PBS_DUPLICATE_SHARED_FIELDS && count($field['bundles']) == 1) { |
|
|
return; |
|
|
} |
|
|
|
|
|
$load_values = $result_format == FIELD_QUERY_RETURN_VALUES; |
|
|
$load_current = $age == FIELD_LOAD_CURRENT; |
|
|
$field_columns = array_keys($field['columns']); |
|
|
$return = array(); |
|
|
|
|
|
// Get the fields to load for each bundle. |
|
|
$bundle_fields = variable_get('pbs_field_map', array()); |
|
|
|
|
|
// We know there is only one bundle, but this code will work if we |
|
|
// ever decide not to store shared fields in per-field storage and |
|
|
// instead require multiple queries into per-bundle storage. |
|
|
foreach ($field['bundles'] as $bundle) { |
|
|
$table = $load_current ? pbs_tablename($bundle) : pbs_revision_tablename($bundle); |
|
|
|
|
|
// Build the query. |
|
|
$query = db_select($table, 't'); |
|
|
$query->join('field_config_entity_type', 'e', 't.etid = e.etid'); |
|
|
$query->fields('e', array('type')); |
|
|
// TODO ->condition('deleted', 0) |
|
|
// Add fields, depending on the return format. |
|
|
if ($load_values) { |
|
|
$query->fields('t'); |
|
|
} |
|
|
else { |
|
|
$query->fields('t', array('entity_id', 'revision_id')); |
|
|
} |
|
|
// Add conditions. |
|
|
foreach ($conditions as $condition) { |
|
|
// A condition is either a (column, value, operator) triple, or a |
|
|
// (column, value) pair with implied operator. |
|
|
@list($column, $value, $operator) = $condition; |
|
|
|
|
|
// TODO |
|
|
if ($column == 'bundle') { |
|
|
continue; |
|
|
} |
|
|
|
|
|
// Translate operator. |
|
|
switch ($operator) { |
|
|
case NULL: |
|
|
$operator = is_array($value) ? 'IN' : '='; |
|
|
break; |
|
|
|
|
|
case 'starts_with': |
|
|
$operator = 'LIKE'; |
|
|
$value .= '%'; |
|
|
break; |
|
|
|
|
|
case 'contains': |
|
|
$operator = 'LIKE'; |
|
|
$value = "%$value%"; |
|
|
break; |
|
|
} |
|
|
// Translate field columns into prefixed db columns. |
|
|
if (in_array($column, $field_columns)) { |
|
|
$or = db_or(); |
|
|
for ($delta = 0; $delta < $field['cardinality']; ++$delta) { |
|
|
$columnname = _field_sql_storage_columnname($field_name, $column) .'_'. $delta; |
|
|
$or->condition($columnname, $value, $operator); |
|
|
} |
|
|
$query->condition($or); |
|
|
} |
|
|
else { |
|
|
$query->condition($column, $value, $operator); |
|
|
} |
|
|
} |
|
|
|
|
|
$results = $query->execute(); |
|
|
|
|
|
// Build results |
|
|
foreach ($results as $row) { |
|
|
// If querying all revisions and the entity type has revisions, we need to |
|
|
// key the results by revision_ids. |
|
|
$entity_type = field_info_fieldable_types($row->type); |
|
|
$id = ($load_current || empty($entity_type['revision key'])) ? $row->entity_id : $row->revision_id; |
|
|
|
|
|
if ($load_values) { |
|
|
$item = array(); |
|
|
|
|
|
// Initialize the 'pseudo object' if needed. |
|
|
if (!isset($return[$row->type][$id])) { |
|
|
$return[$row->type][$id] = field_attach_create_stub_object($row->type, array($row->entity_id, $row->revision_id, $bundle)); |
|
|
} |
|
|
|
|
|
// TODO: refactor with load |
|
|
foreach ($bundle_fields[$bundle] as $column_name => $tuple) { |
|
|
list($field_name, $field_id, $item_name, $delta) = $tuple; |
|
|
if (!is_null($row->{$column_name})) { |
|
|
// We must explicitly include $delta in the assignment |
|
|
// below. Consider a field 'foo' with two columns, e.g. value |
|
|
// and format. Without using $delta, the row containing |
|
|
// foo_value_0 and foo_format_0 would end up stored as |
|
|
// $obj->foo[0]['value'] and $obj->foo[1/*BZZZ!*/]['format']. |
|
|
$return[$row->type][$id]->{$field_name}[$delta][$item_name] = $row->{$column_name}; |
|
|
} |
|
|
else if (!isset($return[$row->type][$id]->{$field_name})) { |
|
|
$return[$row->type][$id]->{$field_name} = array(); |
|
|
} |
|
|
} |
|
|
} |
|
|
else { |
|
|
// Simply return the list of selected ids. |
|
|
$return[$row->type][$id] = $row->entity_id; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
$skip_field = TRUE; |
|
|
|
|
|
return $return; |
|
|
} |
|
|
|
|
|
/** |
|
| 438 |
* Implementation of hook_field_attach_delete. |
* Implementation of hook_field_attach_delete. |
| 439 |
*/ |
*/ |
| 440 |
function pbs_field_attach_delete($obj_type, $object) { |
function pbs_field_attach_delete($obj_type, $object) { |
| 441 |
$etid = _field_sql_storage_etid($obj_type); |
$etid = _field_sql_storage_etid($obj_type); |
| 442 |
list($id, $vid, $bundle, $cacheable) = field_attach_extract_ids($obj_type, $object); |
list($id, $vid, $bundle, $cacheable) = field_extract_ids($obj_type, $object); |
| 443 |
$bundle_table = pbs_tablename($bundle); |
$bundle_table = pbs_tablename($bundle); |
| 444 |
$revision_table = pbs_revision_tablename($bundle); |
$revision_table = pbs_revision_tablename($bundle); |
| 445 |
db_delete($bundle_table)->condition('etid', $etid)->condition('entity_id', $id)->execute(); |
db_delete($bundle_table)->condition('etid', $etid)->condition('entity_id', $id)->execute(); |
| 451 |
*/ |
*/ |
| 452 |
function pbs_field_attach_delete_revision($obj_type, $object) { |
function pbs_field_attach_delete_revision($obj_type, $object) { |
| 453 |
$etid = _field_sql_storage_etid($obj_type); |
$etid = _field_sql_storage_etid($obj_type); |
| 454 |
list($id, $vid, $bundle, $cacheable) = field_attach_extract_ids($obj_type, $object); |
list($id, $vid, $bundle, $cacheable) = field_extract_ids($obj_type, $object); |
| 455 |
$revision_table = pbs_revision_tablename($bundle); |
$revision_table = pbs_revision_tablename($bundle); |
| 456 |
db_delete($revision_table)->condition('etid', $etid)->condition('entity_id', $id)->condition('revision_id', $vid)->execute(); |
db_delete($revision_table)->condition('etid', $etid)->condition('entity_id', $id)->condition('revision_id', $vid)->execute(); |
| 457 |
} |
} |