|
@@ -27,7 +27,9 @@ function tripal_fields_field_storage_write($entity_type, $entity, $op, $fields)
|
|
|
|
|
|
// Convert the fields into a key/value list of fields and their values.
|
|
|
$field_vals = tripal_fields_field_storage_unnest_fields($fields, $entity_type, $entity);
|
|
|
-
|
|
|
+ $data_table = NULL;
|
|
|
+ $type_field = NULL;
|
|
|
+ $record_id = NULL;
|
|
|
switch ($op) {
|
|
|
case FIELD_STORAGE_INSERT:
|
|
|
// Use the cvterm_id to look up tables where this term is used
|
|
@@ -43,8 +45,21 @@ function tripal_fields_field_storage_write($entity_type, $entity, $op, $fields)
|
|
|
$data_table = $usage->data_table;
|
|
|
//$type_table = $usage->type_table;
|
|
|
$type_field = $usage->field;
|
|
|
+
|
|
|
+ // Recursively write fields for the base table.
|
|
|
tripal_fields_field_storage_write_recursive($entity_type, $entity,
|
|
|
$op, $field_vals, $data_table, $type_field);
|
|
|
+
|
|
|
+ // Now get the new chado_entity that was just added.
|
|
|
+ $details = db_select('chado_entity', 'ce')
|
|
|
+ ->fields('ce')
|
|
|
+ ->condition('entity_id', $entity->id)
|
|
|
+ ->execute()
|
|
|
+ ->fetchObject();
|
|
|
+ $data_table = $details->data_table;
|
|
|
+ $type_field = $details->field;
|
|
|
+ $record_id = $details->record_id;
|
|
|
+
|
|
|
}
|
|
|
break;
|
|
|
|
|
@@ -56,17 +71,31 @@ function tripal_fields_field_storage_write($entity_type, $entity, $op, $fields)
|
|
|
->condition('entity_id', $entity->id)
|
|
|
->execute()
|
|
|
->fetchObject();
|
|
|
- $tablename = $details->data_table;
|
|
|
+ $data_table = $details->data_table;
|
|
|
$type_field = $details->field;
|
|
|
$record_id = $details->record_id;
|
|
|
|
|
|
tripal_fields_field_storage_write_recursive($entity_type, $entity,
|
|
|
- $op, $field_vals, $tablename, $type_field, $record_id);
|
|
|
+ $op, $field_vals, $data_table, $type_field, $record_id);
|
|
|
if (!$details) {
|
|
|
// TODO: what to do if record is missing!
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
+
|
|
|
+ // Recursively write fields for any referring tables that have
|
|
|
+ // values in the $field_vals array. There should be a key for each
|
|
|
+ // FK table in the $field_vals array.
|
|
|
+ $schema = chado_get_schema($data_table);
|
|
|
+ $rtables = $schema['referring_tables'];
|
|
|
+ dpm($schema);
|
|
|
+ foreach ($rtables as $rtable) {
|
|
|
+ dpm($rtable);
|
|
|
+ if (array_key_exists($rtable, $field_vals)) {
|
|
|
+ tripal_fields_field_storage_write_recursive($entity_type, $entity,
|
|
|
+ $op, $field_vals, $rtable, $type_field, $record_id, 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -86,7 +115,7 @@ function tripal_fields_field_storage_write_recursive($entity_type, $entity,
|
|
|
$fkey_fields_list = array();
|
|
|
|
|
|
// STEP 1: Recurse on the FK fields.
|
|
|
- // Loop through the foreign keys os that we can recurse on those first.
|
|
|
+ // Loop through the foreign keys so that we can recurse on those first.
|
|
|
foreach ($fkey_fields as $fk_table => $details) {
|
|
|
foreach ($details['columns'] as $local_id => $remote_id) {
|
|
|
// If this is the base table then do not recurse on the type_id. The
|
|
@@ -96,6 +125,7 @@ function tripal_fields_field_storage_write_recursive($entity_type, $entity,
|
|
|
$values[$local_id] = $entity->cvterm_id;
|
|
|
continue;
|
|
|
}
|
|
|
+
|
|
|
// Keep track of the FK fields so that in STEP 2 we don't have to
|
|
|
// loop through the $fk_fields again.
|
|
|
$fkey_fields_list[] = $local_id;
|
|
@@ -103,7 +133,22 @@ function tripal_fields_field_storage_write_recursive($entity_type, $entity,
|
|
|
// Get the value of the FK field as provided by the user.
|
|
|
$fk_val = NULL;
|
|
|
$fk_field_name = $tablename . '__' . $local_id;
|
|
|
- $fk_val = array_key_exists($fk_field_name, $field_vals) ? $field_vals[$fk_field_name] : NULL;
|
|
|
+
|
|
|
+ // If this is the base table then we'll find any values for the FK
|
|
|
+ // fields as any other field. IF we are not at the base table,
|
|
|
+ // then the FK values are in a sub element of the array where the
|
|
|
+ // key of the field is the table name. Because we are looping
|
|
|
+ // on FKs that are members of the current table we should always only
|
|
|
+ // have one value.
|
|
|
+ if ($depth == 0) {
|
|
|
+ $fk_val = array_key_exists($fk_field_name, $field_vals) ? $field_vals[$fk_field_name] : NULL;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if (array_key_exists($fk_table, $field_vals) and
|
|
|
+ array_key_exists($fk_field_name, $field_vals[$fk_table])) {
|
|
|
+ $fk_val = $field_vals[$fk_table][$fk_field_name];
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
// Don't recurse if the value of the FK field is set to NULL. The
|
|
|
// Tripal Chado API value for NULL is '__NULL__'.
|
|
@@ -214,12 +259,13 @@ function tripal_fields_field_storage_load($entity_type, $entities, $age, $fields
|
|
|
|
|
|
foreach ($entities as $id => $entity) {
|
|
|
|
|
|
- // Get the base table and record id for the fields of this entity.
|
|
|
- $details = db_select('chado_entity', 'ce')
|
|
|
+ // Get the base table and record id for the fields of this entity.
|
|
|
+ $details = db_select('chado_entity', 'ce')
|
|
|
->fields('ce')
|
|
|
->condition('entity_id', $entity->id)
|
|
|
->execute()
|
|
|
->fetchObject();
|
|
|
+
|
|
|
if (!$details) {
|
|
|
// TODO: what to do if record is missing!
|
|
|
}
|
|
@@ -275,32 +321,55 @@ function tripal_fields_field_storage_load($entity_type, $entities, $age, $fields
|
|
|
*/
|
|
|
function tripal_fields_field_storage_unnest_fields($fields, $entity_type, $entity) {
|
|
|
$new_fields = array();
|
|
|
+
|
|
|
foreach ($fields as $field_id => $ids) {
|
|
|
$field = field_info_field_by_id($field_id);
|
|
|
$field_name = $field['field_name'];
|
|
|
+
|
|
|
// Currently, we only support one language, but for for the sake of
|
|
|
// thoroughness we'll iterate through all possible languages.
|
|
|
$all_languages = field_available_languages($entity_type, $field);
|
|
|
$field_languages = array_intersect($all_languages, array_keys((array) $entity->$field_name));
|
|
|
foreach ($field_languages as $langcode) {
|
|
|
- $items = (array) $entity->{$field_name}[$langcode];
|
|
|
+
|
|
|
// The number of items is related to the cardinatily of the field.
|
|
|
- // We should always only have one item because this is a field in a
|
|
|
- // table. But we loop anyway.
|
|
|
+ $items = (array) $entity->{$field_name}[$langcode];
|
|
|
foreach ($items as $delta => $item) {
|
|
|
- // If the $value is an array then this field has nested fields. We
|
|
|
- // want to add those to our $new_fields list.
|
|
|
- if (is_array($item['value'])) {
|
|
|
- foreach ($item['value'] as $children) {
|
|
|
- foreach ($children as $child_field_name => $child_value) {
|
|
|
- if (preg_match('/^.*?__.*?$/', $child_field_name)) {
|
|
|
+ // There must be a 'value' field.
|
|
|
+ if (!array_key_exists('value', $item)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Case 1: base table fields.
|
|
|
+ // If the value is not an array then we can just use the value as is.
|
|
|
+ // This occurs for fields of the base table.
|
|
|
+ if (!is_array($item['value'])) {
|
|
|
+ $new_fields[$field_name] = $item['value'];
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Case 2: foreign key fields.
|
|
|
+ // If the value is an array then there are sub fields. This occurs
|
|
|
+ // for fields that represent FKs with the base table.
|
|
|
+ $i = 0;
|
|
|
+ foreach ($item['value'] as $children) {
|
|
|
+ foreach ($children as $child_field_name => $child_value) {
|
|
|
+ $matches = array();
|
|
|
+ if (preg_match('/^(.*?)__.*?$/', $child_field_name, $matches)) {
|
|
|
+ $table_name = $matches[1];
|
|
|
+ // Case 2a: the FK field is in the basee table.
|
|
|
+ if ($table_name == $entity->chado_entity->data_table) {
|
|
|
$new_fields[$child_field_name] = $child_value;
|
|
|
}
|
|
|
+ // Case 2b: the fields of the FK relationship are in the non
|
|
|
+ // base table. We store these in an array with the key being
|
|
|
+ // the table name.
|
|
|
+ else {
|
|
|
+ $new_fields[$table_name][$i][$child_field_name] = $child_value;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
- else {
|
|
|
- $new_fields[$field_name] = $item['value'];
|
|
|
+ $i++;
|
|
|
}
|
|
|
}
|
|
|
}
|