tripal_chado.field_storage.inc 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269
  1. <?php
  2. /**
  3. * Implements hook_field_storage_info().
  4. */
  5. function tripal_chado_field_storage_info() {
  6. return array(
  7. 'field_chado_storage' => array(
  8. 'label' => t('Chado'),
  9. 'description' => t('Stores fields in the local Chado database.'),
  10. 'settings' => array(),
  11. // The logo_url key is supported by Tripal. It's not a Drupal key. It's
  12. // used for adding a logo or picture for the data store to help make it
  13. // more easily recognized on the field_ui_field_overview_form. Ideally
  14. // the URL should point to a relative path on the local Drupal site.
  15. 'logo_url' => url(drupal_get_path('module', 'tripal') . '/theme/images/250px-ChadoLogo.png'),
  16. ),
  17. );
  18. }
  19. /**
  20. * Implements hook_field_storage_write().
  21. */
  22. function tripal_chado_field_storage_write($entity_type, $entity, $op, $fields) {
  23. // Get the bundle and the term for this entity.
  24. $bundle = tripal_load_bundle_entity(array('name' => $entity->bundle));
  25. $term = entity_load('TripalTerm', array('id' => $entity->term_id));
  26. $term = reset($term);
  27. // Convert the Tripal term entity into the appropriate record in Chado.
  28. $dbxref = tripal_get_dbxref(array('accession' => $term->accession, 'db_id' => array('name' => $term->vocab->vocabulary)));
  29. $cvterm = tripal_get_cvterm(array('dbxref_id' => $dbxref->dbxref_id));
  30. // Get the base table, type field and record_id from the entity.
  31. $base_table = $entity->chado_table;
  32. $type_field = $entity->chado_column;
  33. $record = $entity->chado_record;
  34. $record_id = $entity->chado_record_id;
  35. $base_schema = chado_get_schema($base_table);
  36. $base_pkey = $base_schema['primary key'][0];
  37. // Convert the fields into a key/value list of fields and their values.
  38. $field_vals = tripal_chado_field_storage_write_merge_fields($fields, $entity_type, $entity);
  39. // First, write the record for the base table. If we have a record id then
  40. // this is an update and we need to set the primary key. If not, then this
  41. // is an insert and we need to set the type_id if the table supports it.
  42. $values = $field_vals[$base_table];
  43. if ($record_id) {
  44. $values[$base_pkey] = $record_id;
  45. }
  46. elseif ($type_field) {
  47. $values[$type_field] = $cvterm->cvterm_id;
  48. }
  49. $base_record_id = tripal_chado_field_storage_write_table($base_table, $values);
  50. // If this is an insert then add the chado_entity record.
  51. if ($op == FIELD_STORAGE_INSERT) {
  52. // Add the record to the proper chado entity table
  53. $chado_entity_table = chado_get_bundle_entity_table($bundle);
  54. $record = array(
  55. 'entity_id' => $entity->id,
  56. 'record_id' => $base_record_id,
  57. );
  58. $success = drupal_write_record($chado_entity_table, $record);
  59. if (!$success) {
  60. drupal_set_message('Unable to insert new Chado entity.', 'error');
  61. }
  62. }
  63. // Now that we have handled the base table, we need to handle linking tables.
  64. foreach ($field_vals as $table_name => $details) {
  65. // Skip the base table as we've already dealt with it.
  66. if ($table_name == $base_table) {
  67. continue;
  68. }
  69. foreach ($details as $delta => $values) {
  70. $record_id = tripal_chado_field_storage_write_table($table_name, $values);
  71. }
  72. }
  73. }
  74. /**
  75. * Write (inserts/updates/deletes) values for a Chado table.
  76. *
  77. * The $values array is of the same format used by chado_insert_record() and
  78. * chado_update_record(). However, both of those methods will use any nested
  79. * arrays (i.e. representing foreign keys) to select an appropriate record ID
  80. * that can be substituted as the value. Here, the nested arrays are
  81. * either inserted or updated as well, but the choice is determined if the
  82. * primary key value is present. If present an update occurs, if not present
  83. * then an insert occurs.
  84. *
  85. * This function is recursive and nested arrays from the lowest point of the
  86. * "tree" are dealt with first.
  87. *
  88. * @param $table_name
  89. * The name of the table on which the insertion/update is performed.
  90. * @param $values
  91. * The values array for the insertion.
  92. *
  93. * @throws Exception
  94. *
  95. * @return
  96. * The unique record ID.
  97. */
  98. function tripal_chado_field_storage_write_table($table_name, $values) {
  99. $schema = chado_get_schema($table_name);
  100. $fkeys = $schema['foreign keys'];
  101. $pkey = $schema['primary key'][0];
  102. // Fields with a cardinality greater than 1 will often submit an
  103. // empty form. We want to remove these empty submissions. We can detect
  104. // them if all of the fields are empty.
  105. $num_empty = 0;
  106. foreach ($values as $column => $value) {
  107. if (!$value) {
  108. $num_empty++;
  109. }
  110. }
  111. if ($num_empty == count(array_keys($values))) {
  112. return '';
  113. }
  114. // If the primary key column has a value but all other values are empty then
  115. // this is a delete.
  116. if (array_key_exists($pkey, $values) and $values[$pkey]) {
  117. $num_vals = 0;
  118. foreach ($values as $value) {
  119. if ($value) {
  120. $num_vals++;
  121. }
  122. }
  123. if ($num_vals == 1) {
  124. $new_vals[$pkey] = $values[$pkey];
  125. if (!chado_delete_record($table_name, $new_vals)) {
  126. throw new Exception('Could not delete record from table: "' . $table_name . '".');
  127. }
  128. return '';
  129. }
  130. }
  131. // If the primary key column does not have a value then this is an insert.
  132. if (!array_key_exists($pkey, $values) or !$values[$pkey] or !isset($values[$pkey])) {
  133. // Before inserting, we want to make sure the record does not
  134. // already exist. Using the unique constraint check for a matching record.
  135. $options = array('is_duplicate' => TRUE);
  136. $is_duplicate = chado_select_record($table_name, array('*'), $values, $options);
  137. if($is_duplicate) {
  138. $record = chado_select_record($table_name, array('*'), $values);
  139. return $record[0]->$pkey;
  140. }
  141. // Insert the values array as a new record in the table but remove the
  142. // pkey as it should be set.
  143. $new_vals = $values;
  144. unset($new_vals[$pkey]);
  145. $record = chado_insert_record($table_name, $new_vals);
  146. if ($record === FALSE) {
  147. throw new Exception('Could not insert Chado record into table: "' . $table_name . '".');
  148. }
  149. return $record[$pkey];
  150. }
  151. // If we've made it to this point then this is an update.
  152. // TODO: what if the unique constraint matches another record? That is
  153. // not being tested for here.
  154. $match[$pkey] = $values[$pkey];
  155. if (!chado_update_record($table_name, $match, $values)) {
  156. drupal_set_message("Could not update Chado record in table: $table_name.", 'error');
  157. }
  158. return $values[$pkey];
  159. }
  160. /**
  161. * Implements hook_field_storage_pre_load().
  162. *
  163. * Adds a 'chado_record' object containing the base record for the
  164. * entity.
  165. */
  166. function tripal_chado_field_storage_pre_load($entity_type, $entities, $age,
  167. $fields, $options) {
  168. // Itereate through the entities and add in the Chado record.
  169. foreach ($entities as $id => $entity) {
  170. // Only deal with Tripal Entities.
  171. if ($entity_type != 'TripalEntity') {
  172. continue;
  173. }
  174. $record_id = NULL;
  175. if (property_exists($entity, 'chado_table')) {
  176. // Get the base table and record id for the fields of this entity.
  177. $base_table = $entity->chado_table;
  178. $type_field = $entity->chado_column;
  179. $record_id = $entity->chado_record_id;
  180. }
  181. else {
  182. $bundle = tripal_load_bundle_entity(array('name' => $entity->bundle));
  183. $base_table = $bundle->data_table;
  184. $type_field = $bundle->type_column;
  185. // Get the record id for the fields of this entity.
  186. $chado_entity_table = chado_get_bundle_entity_table($bundle);
  187. $details = db_select($chado_entity_table, 'ce')
  188. ->fields('ce')
  189. ->condition('entity_id', $entity->id)
  190. ->execute()
  191. ->fetchObject();
  192. if ($details) {
  193. $record_id = isset($details->record_id) ? $details->record_id : '';
  194. }
  195. $entity->chado_table = $base_table;
  196. $entity->chado_record_id = $record_id;
  197. $entity->chado_column = $type_field;
  198. }
  199. if ($record_id) {
  200. // Get this table's schema.
  201. $schema = chado_get_schema($base_table);
  202. $pkey_field = $schema['primary key'][0];
  203. // Get the base record if one exists
  204. $columns = array('*');
  205. $match = array($pkey_field => $record_id);
  206. $record = chado_generate_var($base_table, $match);
  207. $entity->chado_record = $record;
  208. }
  209. }
  210. }
  211. /**
  212. * Implements hook_field_storage_load().
  213. *
  214. * Responsible for loading the fields from the Chado database and adding
  215. * their values to the entity.
  216. */
  217. function tripal_chado_field_storage_load($entity_type, $entities, $age,
  218. $fields, $options) {
  219. $load_current = $age == FIELD_LOAD_CURRENT;
  220. global $language;
  221. $langcode = $language->language;
  222. foreach ($entities as $id => $entity) {
  223. $base_table = $entity->chado_table;
  224. $type_field = $entity->chado_column;
  225. $record_id = $entity->chado_record_id;
  226. $record = $entity->chado_record;
  227. $schema = chado_get_schema($base_table);
  228. // Iterate through the entity's fields so we can get the column names
  229. // that need to be selected from each of the tables represented.
  230. $tables = array();
  231. foreach ($fields as $field_id => $ids) {
  232. // By the time this hook runs, the relevant field definitions have been
  233. // populated and cached in FieldInfo, so calling field_info_field_by_id()
  234. // on each field individually is more efficient than loading all fields in
  235. // memory upfront with field_info_field_by_ids().
  236. $field = field_info_field_by_id($field_id);
  237. $field_name = $field['field_name'];
  238. $field_type = $field['type'];
  239. $field_module = $field['module'];
  240. // Get the instance for this field. If no instance exists then skip
  241. // loading of this field. This can happen when a field is deleted from
  242. // a bundle using the user UI form.
  243. // TODO: how to deal with deleted fields?
  244. $instance = field_info_instance($entity_type, $field_name, $entity->bundle);
  245. if (!$instance) {
  246. continue;
  247. }
  248. // Skip fields that don't map to a Chado table.
  249. if (!array_key_exists('settings', $instance) or
  250. !array_key_exists('chado_table', $instance['settings'])) {
  251. continue;
  252. }
  253. // Get the Chado table and column for this field.
  254. $field_table = $instance['settings']['chado_table'];
  255. $field_column = $instance['settings']['chado_column'];
  256. // There are only two types of fields: 1) fields that represent a single
  257. // column of the base table, or 2) fields that represent a linked record
  258. // in a many-to-one relationship with the base table.
  259. // Type 1: fields from base tables.
  260. if ($field_table == $base_table) {
  261. // Set an empty value by default, and if there is a record, then update.
  262. $entity->{$field_name}['und'][0]['value'] = '';
  263. if ($record and property_exists($record, $field_column)) {
  264. // If the field column is an object then it's a FK to another table.
  265. // and because $record object is created by the chado_generate_var()
  266. // function we must go one more level deeper to get the value
  267. if (is_object($record->$field_column)) {
  268. $fkey_column = $field_column;
  269. foreach($schema['foreign keys'] as $table => $fk_details) {
  270. foreach($fk_details['columns'] as $lfkey => $rfkey) {
  271. if ($lfkey == $field_column) {
  272. $fkey_column = $rfkey;
  273. }
  274. }
  275. }
  276. $entity->{$field_name}['und'][0]['chado-' . $field_table . '__' . $field_column] = $record->$field_column->$fkey_column;
  277. }
  278. else {
  279. // For non FK fields we'll make the field value be the same
  280. // as the column value.
  281. $entity->{$field_name}['und'][0]['value'] = $record->$field_column;
  282. $entity->{$field_name}['und'][0]['chado-' . $field_table . '__' . $field_column] = $record->$field_column;
  283. }
  284. }
  285. // Allow the creating module to alter the value if desired. The
  286. // module should do this if the field has any other form elements
  287. // that need populationg besides the value which was set above.
  288. tripal_load_include_field_class($field_type);
  289. if (class_exists($field_type) and is_subclass_of($field_type, 'TripalField')) {
  290. $tfield = new $field_type($field, $instance);
  291. $tfield->load($entity, array('record' => $record));
  292. }
  293. // For text fields that were not handled by a TripalField class we
  294. // want to automatically expand those fields.
  295. else {
  296. if ($schema['fields'][$field_column]['type'] == 'text') {
  297. $record = chado_expand_var($record, 'field', "$field_table.$field_column");
  298. $entity->{$field_name}['und'][0]['value'] = $record->$field_column;
  299. // Text fields that have a text_processing == 1 setting need a
  300. // special 'format' element too:
  301. if (array(key_exists('text_processing', $instance['settings']) and
  302. $instance['settings']['text_processing'] == 1)) {
  303. // TODO: we need a way to write the format back to the
  304. // instance settings if the user changes it when using the form.
  305. $entity->{$field_name}['und'][0]['format'] = array_key_exists('format', $instance['settings']) ? $instance['settings']['format'] : 'full_html';
  306. }
  307. }
  308. }
  309. }
  310. // Type 2: fields for linked records. These fields will have any number
  311. // of form elements that might need populating so we'll offload the
  312. // loading of these fields to the field itself.
  313. if ($field_table != $base_table) {
  314. // Set an empty value by default, and let the hook function update it.
  315. $entity->{$field_name}['und'][0]['value'] = '';
  316. tripal_load_include_field_class($field_type);
  317. if (class_exists($field_type) && method_exists($field_type, 'load')) {
  318. $tfield = new $field_type($field, $instance);
  319. $tfield->load($entity, array('record' => $record));
  320. }
  321. }
  322. } // end: foreach ($fields as $field_id => $ids) {
  323. } // end: foreach ($entities as $id => $entity) {
  324. }
  325. /**
  326. * Merges the values of all fields into a single array keyed by table name.
  327. */
  328. function tripal_chado_field_storage_write_merge_fields($fields, $entity_type, $entity) {
  329. $all_fields = array();
  330. $base_fields = array();
  331. // Iterate through all of the fields and organize them into a
  332. // new fields array keyed by the table name
  333. foreach ($fields as $field_id => $ids) {
  334. // Get the field name and information about it.
  335. $field = field_info_field_by_id($field_id);
  336. $field_name = $field['field_name'];
  337. $instance = field_info_instance('TripalEntity', $field['field_name'], $entity->bundle);
  338. // Some fields (e.g. chado_linker_cvterm_adder) don't add data to
  339. // Chado so they don't have a table, but they are still attached to the
  340. // entity. Just skip these.
  341. if (!array_key_exists('chado_table', $instance['settings'])) {
  342. continue;
  343. }
  344. $chado_table = $instance['settings']['chado_table'];
  345. $chado_column = $instance['settings']['chado_column'];
  346. $base_table = $instance['settings']['base_table'];
  347. // Iterate through the field's items. Fields with cardinality ($delta) > 1
  348. // are multi-valued.
  349. $items = field_get_items($entity_type, $entity, $field_name);
  350. $temp = array();
  351. foreach ($items as $delta => $item) {
  352. // A field may have multiple items. The field can use items
  353. // indexed with "chado-" to represent values that should map directly
  354. // to chado tables and fields.
  355. $value_set = FALSE;
  356. foreach ($item as $item_name => $value) {
  357. $matches = array();
  358. if (preg_match('/^chado-(.*?)__(.*?)$/', $item_name, $matches)) {
  359. $table_name = $matches[1];
  360. $column_name = $matches[2];
  361. // If this field belongs to the base table then we just add
  362. // those values in... there's no delta.
  363. if ($table_name == $base_table) {
  364. $base_fields[$table_name][$column_name] = $value;
  365. }
  366. else {
  367. $temp[$table_name][$delta][$column_name] = $value;
  368. }
  369. $value_set = TRUE;
  370. }
  371. }
  372. // If there is no value set for the field using the
  373. // chado-[table_name]__[field name] naming schema then check if a 'value'
  374. // item is present and if so use that for the table column value.
  375. if (!$value_set and array_key_exists('value', $items[$delta]) and
  376. !is_array($items[$delta]['value'])) {
  377. // If this field belongs to the base table then we just add
  378. // those values in... there's no delta.
  379. if ($base_table == $chado_table) {
  380. $base_fields[$chado_table][$chado_column] = $item['value'];
  381. }
  382. else {
  383. $temp[$chado_table][$delta][$chado_column] = $item['value'];
  384. }
  385. }
  386. }
  387. // Now merge the records for this field with the $new_fields array
  388. foreach ($temp as $table_name => $details) {
  389. foreach ($details as $delta => $list) {
  390. $all_fields[$table_name][] = $list;
  391. }
  392. }
  393. }
  394. $all_fields = array_merge($base_fields, $all_fields);
  395. return $all_fields;
  396. }
  397. /**
  398. * Implements hook_field_storage_query().
  399. */
  400. function tripal_chado_field_storage_query($query) {
  401. // Initialize the result array.
  402. $result = array(
  403. 'TripalEntity' => array()
  404. );
  405. // There must always be an entity filter that includes the bundle. Otherwise
  406. // it would be too overwhelming to search every table of every content type
  407. // for a matching field.
  408. if (!array_key_exists('bundle', $query->entityConditions)) {
  409. return $result;
  410. }
  411. $bundle = tripal_load_bundle_entity(array('name' => $query->entityConditions['bundle']));
  412. if (!$bundle) {
  413. return;
  414. }
  415. $data_table = $bundle->data_table;
  416. $type_column = $bundle->type_column;
  417. $type_id = $bundle->type_id;
  418. $schema = chado_get_schema($data_table);
  419. $pkey = $schema['primary key'][0];
  420. // Initialize the Query object.
  421. $cquery = chado_db_select($data_table, 'base');
  422. $cquery->fields('base', array($pkey));
  423. // Iterate through all the conditions and add to the filters array
  424. // a chado_select_record compatible set of filters.
  425. foreach ($query->fieldConditions as $index => $condition) {
  426. $field = $condition['field'];
  427. $field_name = $field['field_name'];
  428. $field_type = $field['type'];
  429. // Skip conditions that don't belong to this storage type.
  430. if ($field['storage']['type'] != 'field_chado_storage') {
  431. continue;
  432. }
  433. // The Chado settings for a field are part of the instance and each bundle
  434. // can have the same field but with different Chado mappings. Therefore,
  435. // we need to iterate through the bundles to get the field instances.
  436. foreach ($field['bundles']['TripalEntity'] as $bundle_name) {
  437. // If there is a bundle filter for the entity and if the field is not
  438. // associated with the bundle then skip it.
  439. if (array_key_exists('bundle', $query->entityConditions)) {
  440. if (strtolower($query->entityConditions['bundle']['operator']) == 'in' and
  441. !array_key_exists($bundle_name, $query->entityConditions['bundle']['value'])) {
  442. continue;
  443. }
  444. else if ($query->entityConditions['bundle']['value'] != $bundle_name) {
  445. continue;
  446. }
  447. }
  448. // Allow the field to update the query object.
  449. $instance = field_info_instance('TripalEntity', $field['field_name'], $bundle_name);
  450. if (tripal_load_include_field_class($field_type)) {
  451. $field_obj = new $field_type($field, $instance);
  452. $field_obj->query($cquery, $condition);
  453. }
  454. // If there is no ChadoField class for this field then add the
  455. // condition as is.
  456. else {
  457. $alias = $field['field_name'];
  458. $chado_table = $instance['settings']['chado_table'];
  459. $base_table = $instance['settings']['base_table'];
  460. $bschema = chado_get_schema($base_table);
  461. $bpkey = $bschema['primary key'][0];
  462. if ($chado_table == $base_table) {
  463. // Get the base table column that is associated with the term
  464. // passed as $condition['column'].
  465. $base_field = tripal_get_chado_semweb_column($chado_table, $condition['column']);
  466. $cquery->condition('base.' . $base_field , $condition['value'], $condition['operator']);
  467. }
  468. if ($chado_table != $base_table) {
  469. // TODO: I don't think we'll get here because linker fields will
  470. // always have a custom field that should implement a query()
  471. // function. But just in case here's a note to handle it.
  472. }
  473. }
  474. }
  475. } // end foreach ($query->fieldConditions as $index => $condition) {
  476. // Now join with the chado entity table to get published records only.
  477. $chado_entity_table = chado_get_bundle_entity_table($bundle);
  478. $cquery->join($chado_entity_table, 'CE', "CE.record_id = base.$pkey");
  479. $cquery->join('tripal_entity', 'TE', "CE.entity_id = TE.id");
  480. $cquery->fields('CE', array('entity_id'));
  481. $cquery->fields('TE', array('bundle'));
  482. if (array_key_exists('start', $query->range)) {
  483. $cquery->range($query->range['start'], $query->range['length']);
  484. }
  485. // Make sure we only get records of the correct entity type
  486. $cquery->condition('TE.bundle', $query->entityConditions['bundle']['value']);
  487. // Now set any ordering.
  488. foreach ($query->order as $index => $sort) {
  489. // Add in property ordering.
  490. if ($order['type'] == 'property') {
  491. }
  492. // Add in filter ordering
  493. if ($sort['type'] == 'field') {
  494. $field = $sort['specifier']['field'];
  495. $field_type = $field['type'];
  496. $field_name = $field['field_name'];
  497. // Skip sorts that don't belong to this storage type.
  498. if ($field['storage']['type'] != 'field_chado_storage') {
  499. continue;
  500. }
  501. $column = $sort['specifier']['column'];
  502. $direction = $sort['direction'];
  503. // The Chado settings for a field are part of the instance and each bundle
  504. // can have the same field but with different Chado mappings. Therefore,
  505. // we need to iterate through the bundles to get the field instances.
  506. foreach ($field['bundles']['TripalEntity'] as $bundle_name) {
  507. // If there is a bundle filter for the entity and if the field is not
  508. // associated with the bundle then skip it.
  509. if (array_key_exists('bundle', $query->entityConditions)) {
  510. if (strtolower($query->entityConditions['bundle']['operator']) == 'in' and
  511. !array_key_exists($bundle_name, $query->entityConditions['bundle']['value'])) {
  512. continue;
  513. }
  514. else if ($query->entityConditions['bundle']['value'] != $bundle_name) {
  515. continue;
  516. }
  517. }
  518. // See if there is a ChadoField class for this instance. If not then do
  519. // our best to order the field.
  520. $instance = field_info_instance('TripalEntity', $field_name, $bundle_name);
  521. if (tripal_load_include_field_class($field_type)) {
  522. $field_obj = new $field_type($field, $instance);
  523. $field_obj->queryOrder($cquery, array('column' => $column, 'direction' => $direction));
  524. }
  525. // There is no class so do our best to order the data by this field
  526. else {
  527. $base_table = $instance['settings']['base_table'];
  528. $chado_table = $instance['settings']['chado_table'];
  529. $table_column = tripal_get_chado_semweb_column($chado_table, $column);
  530. if ($table_column) {
  531. if ($chado_table == $base_table) {
  532. $cquery->orderBy('base.' . $table_column, $direction);
  533. }
  534. else {
  535. // TODO: how do we handle a field that doesn't map to the base table.
  536. // We would expect that all of these would be custom field and
  537. // the ChadoField::queryOrder() function would be implemented.
  538. }
  539. }
  540. else {
  541. // TODO: handle when the name can't be matched to a table column.
  542. }
  543. }
  544. } // end foreach ($field['bundles']['TripalEntity'] as $bundle_name) {
  545. } // end if ($sort['type'] == 'field') {
  546. } // end foreach ($query->order as $index => $sort) {
  547. //print_r($cquery->__toString());
  548. //print_r($cquery->getArguments());
  549. $records = $cquery->execute();
  550. $result = array();
  551. while ($record = $records->fetchObject()) {
  552. $ids = array($record->entity_id, 0, $record->bundle);
  553. $result['TripalEntity'][$record->entity_id] = entity_create_stub_entity('TripalEntity', $ids);
  554. }
  555. return $result;
  556. }
  557. /**
  558. * Implements hook_field_storage_bundle_mapping_form().
  559. *
  560. * This is a Tripal added hook to the field storage API.
  561. */
  562. function tripal_chado_field_storage_bundle_mapping_form($form, &$form_state,
  563. $term, &$submit_disabled) {
  564. $selected_term_id = $term->cvterm_id;
  565. // Initialize the form.
  566. $form = array();
  567. // Get the form default values.
  568. $default = array(
  569. 'table' => '',
  570. 'has_all' => 'No',
  571. 'use_cvterm' => 'cv',
  572. 'cv_id' => '',
  573. 'use_linker' => 'Yes',
  574. 'use_prop' => 'Yes',
  575. 'type_column' => '',
  576. 'prop_term_name' => '',
  577. 'prop_term_value' => '',
  578. );
  579. if (array_key_exists('base_chado_table', $form_state['values'])
  580. and $form_state['values']['base_chado_table']) {
  581. $default['table'] = $form_state['values']['base_chado_table'];
  582. }
  583. else {
  584. $mapped_table = chado_get_cvterm_mapping(array('cvterm_id' => $selected_term_id));
  585. if ($mapped_table) {
  586. $default['table'] = $mapped_table->chado_table;
  587. }
  588. }
  589. if (array_key_exists('chado_table_has_all', $form_state['values'])
  590. and $form_state['values']['chado_table_has_all']) {
  591. $default['has_all'] = $form_state['values']['chado_table_has_all'];
  592. }
  593. if (array_key_exists('chado_type_use_linker', $form_state['values'])
  594. and $form_state['values']['chado_type_use_linker']) {
  595. $default['use_linker'] = $form_state['values']['chado_type_use_linker'];
  596. }
  597. if (array_key_exists('chado_type_use_prop', $form_state['values'])
  598. and $form_state['values']['chado_type_use_prop']) {
  599. $default['use_prop'] = $form_state['values']['chado_type_use_prop'];
  600. }
  601. if (array_key_exists('type_column', $form_state['values'])
  602. and $form_state['values']['type_column']) {
  603. $default['type_column'] = $form_state['values']['type_column'];
  604. }
  605. if (array_key_exists('prop_term_name', $form_state['values'])
  606. and $form_state['values']['prop_term_name']) {
  607. $default['prop_term_name'] = $form_state['values']['prop_term_name'];
  608. }
  609. if (array_key_exists('prop_term_value', $form_state['values'])
  610. and $form_state['values']['prop_term_value']) {
  611. $default['prop_term_value'] = $form_state['values']['prop_term_value'];
  612. }
  613. if (array_key_exists('chado_type_use_cv', $form_state['values'])
  614. and $form_state['values']['chado_type_use_cv']) {
  615. $default['use_cvterm'] = $form_state['values']['chado_type_use_cv'];
  616. }
  617. if (array_key_exists('chado_type_cv_id', $form_state['values'])
  618. and $form_state['values']['chado_type_cv_id']) {
  619. $default['cv_id'] = $form_state['values']['chado_type_cv_id'];
  620. }
  621. $form['selected_cvterm_id'] = array(
  622. '#type' => 'value',
  623. '#value' => $selected_term_id,
  624. );
  625. $base_tables = chado_get_base_tables();
  626. $options = array(0 => '-- Select table --');
  627. foreach ($base_tables AS $tablename) {
  628. $options[$tablename] = $tablename;
  629. }
  630. $form['base_chado_table'] = array(
  631. '#type' => 'select',
  632. '#title' => 'Chado table',
  633. '#options' => $options,
  634. '#description' => 'Select the Chado table into which the primary records for this content type will be stored.',
  635. '#default_value' => $default['table'],
  636. '#ajax' => array(
  637. 'callback' => "tripal_admin_add_type_form_ajax_callback",
  638. 'wrapper' => "tripal-vocab-select-form",
  639. 'effect' => 'fade',
  640. 'method' => 'replace'
  641. ),
  642. );
  643. $form_state['input']['base_chado_table'] = $default['table'];
  644. // Return now if the user hasn't provided a table.
  645. if (!$default['table']) {
  646. return $form;
  647. }
  648. // Get the schema for this table.
  649. $schema = chado_get_schema($default['table']);
  650. // If the selected base table is 'cvterm' then handle it specially.
  651. if ($default['table'] == 'cvterm') {
  652. tripal_chado_field_storage_bundle_mapping_form_add_cvterm($form,
  653. $form_state, $term, $default);
  654. if ($default['use_cvterm'] == 'cv' and $default['cv_id']) {
  655. $submit_disabled = FALSE;
  656. }
  657. if ($default['use_cvterm'] == 'parent') {
  658. $submit_disabled = FALSE;
  659. }
  660. return $form;
  661. }
  662. // Ask the user if all of the records in the default table are of one type.
  663. tripal_chado_field_storage_bundle_mapping_form_add_allrecs($form,
  664. $form_state, $term, $default);
  665. // If all the records in the table are of this type then we're done.
  666. if ($default['has_all'] == 'Yes') {
  667. $submit_disabled = FALSE;
  668. return $form;
  669. }
  670. // If this table has a field that maps to a cvterm record then we want
  671. // to ask if the user wants to use that field.
  672. tripal_chado_field_storage_bundle_mapping_form_add_type($form,
  673. $form_state, $term, $default);
  674. // If the type_column is set then we're done! We know the deafult table
  675. // and column to map this data type.
  676. if (!empty($default['type_column'])) {
  677. $submit_disabled = FALSE;
  678. return $form;
  679. }
  680. // Let's set the names of the linker and prop table for use below.
  681. $linker_table = $default['table'] . '_cvterm';
  682. $prop_table = $default['table']. 'prop';
  683. $linker_exists = chado_table_exists($linker_table);
  684. $prop_exists = chado_table_exists($prop_table);
  685. // Ask the user if they want to use a linker table if it exists.
  686. if($prop_exists) {
  687. tripal_chado_field_storage_bundle_mapping_form_add_prop($form,
  688. $form_state, $term, $prop_table, $default);
  689. // If the user wants to use the property table then we're done!
  690. if ($default['use_prop'] == 'Yes') {
  691. $submit_disabled = FALSE;
  692. return $form;
  693. }
  694. // Ask if the user wants to use the linker table if it exists.
  695. if ($linker_exists) {
  696. tripal_chado_field_storage_bundle_mapping_form_add_linker($form,
  697. $form_state, $term, $linker_table, $default);
  698. // If the user wants to use the linker table then we're done!
  699. if ($default['use_linker'] == 'Yes') {
  700. $submit_disabled = FALSE;
  701. return $form;
  702. }
  703. }
  704. }
  705. // A prop table doesn't exist then ask the user if they want
  706. // to use the linker table to associate records.
  707. else if ($linker_exists) {
  708. tripal_chado_field_storage_bundle_mapping_form_add_prop($form,
  709. $form_state, $term, $prop_table, $default);
  710. // If the user wants to use the linker table then we're done!
  711. if ($default['use_linker'] == 'Yes') {
  712. $submit_disabled = FALSE;
  713. return $form;
  714. }
  715. }
  716. $form['notice'] = array(
  717. '#type' => 'item',
  718. '#markup' => '<font color="red">Unfortunately, the options selected above do not allow for mapping of this content type to records in Chado.</font>'
  719. );
  720. return $form;
  721. }
  722. /**
  723. *
  724. */
  725. function tripal_chado_field_storage_bundle_mapping_form_add_type(&$form,
  726. &$form_state, $term, &$default){
  727. $term_name = $term->name;
  728. // Get the list of columns in the default table.
  729. $schema = chado_get_schema($default['table']);
  730. $column_options = array('none' => '--None--');
  731. $cvt_fkeys = array_keys($schema['foreign keys']['cvterm']['columns']);
  732. foreach ($schema['fields'] as $column_name => $column_details) {
  733. if (in_array($column_name, $cvt_fkeys)) {
  734. $column_options[$column_name] = $column_name;
  735. }
  736. }
  737. // If this table has no types then just return.
  738. if (count($column_options) == 1) {
  739. $default['type_column'] = '';
  740. return;
  741. }
  742. $default_column = !empty($default['type_column']) ? $default['type_column'] : 'type_id';
  743. $form['type_column'] = array(
  744. '#type' => 'select',
  745. '#title' => 'Type Column',
  746. '#options' => $column_options,
  747. '#description' => 'Please select the column in the "' .
  748. $default['table'] . '" table that will identify a record as being of type "' .
  749. $term_name . '". If you select "--None--" then you will be asked
  750. if you the type can be identified using a property or linker table.
  751. Only fields that have a foreign key to the cvterm table will be listed.',
  752. '#default_value' => $default_column,
  753. '#ajax' => array(
  754. 'callback' => "tripal_admin_add_type_form_ajax_callback",
  755. 'wrapper' => "tripal-vocab-select-form",
  756. 'effect' => 'fade',
  757. 'method' => 'replace'
  758. ),
  759. );
  760. // Set the default value so we can short circuit the form.
  761. $default['type_column'] = $default_column;
  762. if ($default['type_column'] == 'none') {
  763. $default['type_column'] = '';
  764. }
  765. }
  766. /**
  767. *
  768. */
  769. function tripal_chado_field_storage_bundle_mapping_form_add_allrecs(&$form,
  770. &$form_state, $term, $default) {
  771. $term_name = $term->name;
  772. // Form elements to determine if all records in base table are of this type.
  773. $form['chado_table_has_all'] = array(
  774. '#type' => 'radios',
  775. '#options' => array(
  776. 'Yes' => 'Yes',
  777. 'No' => 'No'
  778. ),
  779. '#title' => 'Are all records in the "' . $default['table'] .
  780. '" table of type "'. $term_name . '"?',
  781. '#description' => 'Select "No" if the "' .
  782. $default['table'] . '" table houses more that just data of type "' .
  783. $term_name . '".',
  784. '#default_value' => $default['has_all'],
  785. '#ajax' => array(
  786. 'callback' => "tripal_admin_add_type_form_ajax_callback",
  787. 'wrapper' => "tripal-vocab-select-form",
  788. 'effect' => 'fade',
  789. 'method' => 'replace'
  790. ),
  791. );
  792. }
  793. /**
  794. *
  795. */
  796. function tripal_chado_field_storage_bundle_mapping_form_add_linker(&$form,
  797. &$form_state, $term, $linker_table, $default){
  798. $form['chado_type_use_linker'] = array(
  799. '#type' => 'radios',
  800. '#title' => 'Do you want to use the "' . $linker_table . '" table
  801. to distinguish between content types?',
  802. '#options' => array(
  803. 'Yes' => 'Yes',
  804. 'No' => 'No'
  805. ),
  806. '#description' => t('Sometimes records can be distringuished
  807. using a linker table, especially if there is no column
  808. in the specified Chado table to identify the
  809. record type. In these cases the linker table can be used.'),
  810. '#default_value' => $default['use_linker'],
  811. '#ajax' => array(
  812. 'callback' => "tripal_admin_add_type_form_ajax_callback",
  813. 'wrapper' => "tripal-vocab-select-form",
  814. 'effect' => 'fade',
  815. 'method' => 'replace'
  816. ),
  817. );
  818. }
  819. /**
  820. *
  821. */
  822. function tripal_chado_field_storage_bundle_mapping_form_add_prop(&$form,
  823. &$form_state, $term, $prop_table, $default){
  824. $form['chado_type_use_prop'] = array(
  825. '#type' => 'radios',
  826. '#title' => 'Do you want to use the "' . $prop_table . '" table
  827. to distinguish between content types?',
  828. '#options' => array(
  829. 'Yes' => 'Yes',
  830. 'No' => 'No'
  831. ),
  832. '#description' => t('Sometimes records can be distringuished
  833. using a value in property table, especially if there is no column
  834. in the specified Chado table to identify the
  835. record type. In these cases the property table can be used.'),
  836. '#default_value' => $default['use_prop'],
  837. '#ajax' => array(
  838. 'callback' => "tripal_admin_add_type_form_ajax_callback",
  839. 'wrapper' => "tripal-vocab-select-form",
  840. 'effect' => 'fade',
  841. 'method' => 'replace'
  842. ),
  843. );
  844. if ($default['use_prop'] == 'Yes') {
  845. $prop_term_name = $default['prop_term_name'];
  846. $prop_term_value = $default['prop_term_value'];
  847. $form['prop_term_name'] = array(
  848. '#title' => t('Property Type'),
  849. '#type' => 'textfield',
  850. '#description' => t('The content type "' . $term->name . '" must be
  851. associated with a property type. The property type must be the
  852. name of a term in a controlled vocabulary and the controlled
  853. vocabulary should already be loaded into Tripal. Please select
  854. the property type that will be used to identify records of this
  855. type'),
  856. '#required' => TRUE,
  857. '#default_value' => $prop_term_name,
  858. '#autocomplete_path' => "admin/tripal/storage/chado/auto_name/cvterm/",
  859. );
  860. $form['prop_term_select_button'] = array(
  861. '#type' => 'submit',
  862. '#value' => t('Lookup Term'),
  863. '#name' => 'select_prop_cvterm',
  864. '#ajax' => array(
  865. 'callback' => "tripal_admin_add_type_form_ajax_callback",
  866. 'wrapper' => "tripal-vocab-select-form",
  867. 'effect' => 'fade',
  868. 'method' => 'replace'
  869. ),
  870. );
  871. // If the term has been provided by the user then we want to search for
  872. // matching terms in the database and let them select among any matches.
  873. if ($prop_term_name) {
  874. $form['prop_terms_list'] = array(
  875. '#type' => 'fieldset',
  876. '#title' => t('Matching Terms'),
  877. '#description' => t('Please select the term the best matches the
  878. property type.')
  879. );
  880. $match = array(
  881. 'name' => $prop_term_name,
  882. );
  883. $pterms = chado_generate_var('cvterm', $match, array('return_array' => TRUE));
  884. $pterms = chado_expand_var($pterms, 'field', 'cvterm.definition');
  885. $num_terms = 0;
  886. // Let the user select from any matching terms. Sometimes there may be
  887. // more than one that match.
  888. foreach ($pterms as $pterm) {
  889. // Save the user a click by setting the default value as 1 if there's
  890. // only one matching term.
  891. $default = FALSE;
  892. $attrs = array();
  893. if ($num_terms == 0 and count($pterms) == 1) {
  894. $default = TRUE;
  895. $attrs = array('checked' => 'checked');
  896. }
  897. $term_element_name = 'prop_term-' . $pterm->cvterm_id;
  898. $form['prop_terms_list'][$term_element_name] = array(
  899. '#type' => 'checkbox',
  900. '#title' => $pterm->name,
  901. '#default_value' => $default,
  902. '#attributes' => $attrs,
  903. '#description' => '<b>Vocabulary:</b> ' . $pterm->cv_id->name . ' (' . $pterm->dbxref_id->db_id->name . ') ' . $pterm->cv_id->definition .
  904. '<br><b>Term: </b> ' . $pterm->dbxref_id->db_id->name . ':' . $pterm->dbxref_id->accession . '. ' .
  905. '<br><b>Definition:</b> ' . $pterm->definition,
  906. '#ajax' => array(
  907. 'callback' => "tripal_admin_add_type_form_ajax_callback",
  908. 'wrapper' => "tripal-vocab-select-form",
  909. 'effect' => 'fade',
  910. 'method' => 'replace'
  911. ),
  912. );
  913. $num_terms++;
  914. }
  915. $form['prop_term_value'] = array(
  916. '#type' => 'textfield',
  917. '#title' => 'Property Value',
  918. '#description' => t('All properties have a type and a value. Above you
  919. indicated the type of property. Now you must specify the value
  920. that this properly must have in order to be considered of
  921. type "' . $term->name . '".'),
  922. '#default_value' => $prop_term_value,
  923. '#required' => TRUE,
  924. );
  925. }
  926. }
  927. }
  928. /**
  929. *
  930. */
  931. function tripal_chado_field_storage_bundle_mapping_form_add_cvterm(&$form,
  932. &$form_state, $term, &$default){
  933. $form['chado_type_use_cv'] = array(
  934. '#type' => 'radios',
  935. '#title' => 'How do you want to distinguish the "' . $term->name . '" records
  936. within the cvterm table?',
  937. '#options' => array(
  938. 'cv' => 'All records that belong to a single controlled vocabulary?',
  939. 'parent' => 'All child records of the specified term?'
  940. ),
  941. '#description' => t('Records in the cvterm table are often not used for content
  942. types. The records in the cvterm table are meant to be vocabulary terms.
  943. However, there are times when records in the cvterm table can be
  944. used for a content type. One example is for trait "pages" that
  945. use phenotype values stored in the phenotype table. Because records in
  946. the cvterm table are vocabulary terms they do not have "types" so the
  947. only ways to distinguish them are 1) to use the controlled vocabulary to
  948. distinguish the records or 2) to use all children records of the
  949. selected term. Please select the appropriate value for this case.'),
  950. '#default_value' => $default['use_cvterm'],
  951. '#ajax' => array(
  952. 'callback' => "tripal_admin_add_type_form_ajax_callback",
  953. 'wrapper' => "tripal-vocab-select-form",
  954. 'effect' => 'fade',
  955. 'method' => 'replace'
  956. ),
  957. );
  958. if ($default['use_cvterm'] == 'cv') {
  959. $cvs = tripal_get_cv_select_options();
  960. $form['chado_type_cv_id'] = array(
  961. '#type' => select,
  962. '#options' => $cvs,
  963. '#title' => t('Select a controlled vocabulary'),
  964. '#default_value' => $default['cv_id'],
  965. '#ajax' => array(
  966. 'callback' => "tripal_admin_add_type_form_ajax_callback",
  967. 'wrapper' => "tripal-vocab-select-form",
  968. 'effect' => 'fade',
  969. 'method' => 'replace'
  970. ),
  971. );
  972. }
  973. }
  974. /**
  975. * Implements hook_field_stoage_bundle_mapping_form_validate().
  976. */
  977. function tripal_chado_field_storage_bundle_mapping_form_validate($form, &$form_state) {
  978. // Get the form values
  979. $default = array(
  980. 'table' => '',
  981. 'has_all' => 'No',
  982. 'use_cvterm' => 'cv',
  983. 'cv_id' => '',
  984. 'use_linker' => 'Yes',
  985. 'use_prop' => 'Yes',
  986. 'type_column' => '',
  987. 'prop_term_name' => '',
  988. 'prop_term_value' => '',
  989. );
  990. if (array_key_exists('base_chado_table', $form_state['values'])
  991. and $form_state['values']['base_chado_table']) {
  992. $default['table'] = $form_state['values']['base_chado_table'];
  993. }
  994. if (array_key_exists('chado_table_has_all', $form_state['values'])
  995. and $form_state['values']['chado_table_has_all']) {
  996. $default['has_all'] = $form_state['values']['chado_table_has_all'];
  997. }
  998. if (array_key_exists('chado_type_use_linker', $form_state['values'])
  999. and $form_state['values']['chado_type_use_linker']) {
  1000. $default['use_linker'] = $form_state['values']['chado_type_use_linker'];
  1001. }
  1002. if (array_key_exists('chado_type_use_prop', $form_state['values'])
  1003. and $form_state['values']['chado_type_use_prop']) {
  1004. $default['use_prop'] = $form_state['values']['chado_type_use_prop'];
  1005. }
  1006. if (array_key_exists('type_column', $form_state['values'])
  1007. and $form_state['values']['type_column']) {
  1008. $default['type_column'] = $form_state['values']['type_column'];
  1009. }
  1010. if (array_key_exists('prop_term_name', $form_state['values'])
  1011. and $form_state['values']['prop_term_name']) {
  1012. $default['prop_term_name'] = $form_state['values']['prop_term_name'];
  1013. // Make sure we have only one property cvterm selected
  1014. $num_selected = 0;
  1015. foreach ($form_state['values'] as $key => $value) {
  1016. $matches = array();
  1017. if (preg_match("/^prop_term-(\d+)$/", $key, $matches) and
  1018. $form_state['values']['prop_term-' . $matches[1]]) {
  1019. $cvterm_id = $matches[1];
  1020. $term = chado_generate_var('cvterm', array('cvterm_id' => $cvterm_id));
  1021. $num_selected++;
  1022. }
  1023. }
  1024. if ($num_selected == 0) {
  1025. form_set_error('', 'Please select at least one property term.');
  1026. }
  1027. else if ($num_selected > 1) {
  1028. form_set_error('prop_term-' . $cvterm_id, 'Please select only one property term from the list below.');
  1029. }
  1030. $form_state['prop_term'] = $term;
  1031. }
  1032. if (array_key_exists('prop_term_value', $form_state['values'])
  1033. and $form_state['values']['prop_term_value']) {
  1034. $default['prop_term_value'] = $form_state['values']['prop_term_value'];
  1035. }
  1036. if (array_key_exists('chado_type_use_cv', $form_state['values'])
  1037. and $form_state['values']['chado_type_use_cv']) {
  1038. $default['use_cvterm'] = $form_state['values']['chado_type_use_cv'];
  1039. }
  1040. if (array_key_exists('chado_type_cv_id', $form_state['values'])
  1041. and $form_state['values']['chado_type_cv_id']) {
  1042. $default['cv_id'] = $form_state['values']['chado_type_cv_id'];
  1043. }
  1044. // Make sure a default table is selected
  1045. if (!$default['table']) {
  1046. form_set_error('base_chado_table', 'Please select a default table.');
  1047. }
  1048. }
  1049. /**
  1050. * Implements hook_field_stoage_bundle_mapping_form_submit().
  1051. *
  1052. * Here we do no action on submit other than set the storage_args
  1053. * variable that is passed by reference.
  1054. */
  1055. function tripal_chado_field_storage_bundle_mapping_form_submit($form,
  1056. &$form_state, $term, &$storage_args) {
  1057. // Get the form values
  1058. $default = array(
  1059. 'table' => '',
  1060. 'has_all' => 'No',
  1061. 'use_cvterm' => '',
  1062. 'cv_id' => '',
  1063. 'use_linker' => 'No',
  1064. 'use_prop' => 'No',
  1065. 'type_column' => '',
  1066. 'prop_term_name' => '',
  1067. 'prop_term_value' => '',
  1068. );
  1069. if (array_key_exists('base_chado_table', $form_state['values'])
  1070. and $form_state['values']['base_chado_table']) {
  1071. $default['table'] = $form_state['values']['base_chado_table'];
  1072. }
  1073. if (array_key_exists('chado_table_has_all', $form_state['values'])
  1074. and $form_state['values']['chado_table_has_all']) {
  1075. $default['has_all'] = $form_state['values']['chado_table_has_all'];
  1076. }
  1077. if (array_key_exists('chado_type_use_linker', $form_state['values'])
  1078. and $form_state['values']['chado_type_use_linker']) {
  1079. $default['use_linker'] = $form_state['values']['chado_type_use_linker'];
  1080. }
  1081. if (array_key_exists('chado_type_use_prop', $form_state['values'])
  1082. and $form_state['values']['chado_type_use_prop']) {
  1083. $default['use_prop'] = $form_state['values']['chado_type_use_prop'];
  1084. }
  1085. if (array_key_exists('type_column', $form_state['values'])
  1086. and $form_state['values']['type_column']) {
  1087. $default['type_column'] = $form_state['values']['type_column'];
  1088. }
  1089. if (array_key_exists('prop_term_name', $form_state['values'])
  1090. and $form_state['values']['prop_term_name']) {
  1091. $default['prop_term_name'] = $form_state['values']['prop_term_name'];
  1092. }
  1093. if (array_key_exists('prop_term_value', $form_state['values'])
  1094. and $form_state['values']['prop_term_value']) {
  1095. $default['prop_term_value'] = $form_state['values']['prop_term_value'];
  1096. }
  1097. if (array_key_exists('chado_type_use_cv', $form_state['values'])
  1098. and $form_state['values']['chado_type_use_cv']) {
  1099. $default['use_cvterm'] = $form_state['values']['chado_type_use_cv'];
  1100. }
  1101. if (array_key_exists('chado_type_cv_id', $form_state['values'])
  1102. and $form_state['values']['chado_type_cv_id']) {
  1103. $default['cv_id'] = $form_state['values']['chado_type_cv_id'];
  1104. }
  1105. // If the user selected to use the cvterm table then we have to
  1106. // handle it specially.
  1107. if ($default['use_cvterm'] == 'cv' and !empty($default['cv_id'])) {
  1108. $storage_args['data_table'] = $default['table'];
  1109. $storage_args['type_id'] = $form_state['values']['selected_cvterm_id'];
  1110. $storage_args['type_value'] = '';
  1111. if ($default['cv_id']) {
  1112. $storage_args['type_value'] = $default['cv_id'];
  1113. }
  1114. $storage_args['type_column'] = '';
  1115. return;
  1116. }
  1117. // If we have a type_column then we know this type uses a column in the
  1118. // base table, so we can set the storage args and return.
  1119. if ($default['type_column']) {
  1120. $storage_args['data_table'] = $default['table'];
  1121. $storage_args['type_column'] = $default['type_column'];
  1122. return;
  1123. }
  1124. // If the user indicated that all the records in a table are of this type.
  1125. if ($default['has_all'] == 'Yes') {
  1126. $storage_args['data_table'] = $default['table'];
  1127. $storage_args['type_id'] = $form_state['values']['selected_cvterm_id'];
  1128. $storage_args['type_linker_table'] = '';
  1129. $storage_args['type_column'] = '';
  1130. $storage_args['type_value'] = '';
  1131. }
  1132. // If the user indicated they wanted to use the prop table then we'll
  1133. // set the storage args and return.
  1134. else if ($default['use_prop'] == 'Yes') {
  1135. $storage_args['data_table'] = $default['table'];
  1136. $storage_args['type_linker_table'] = $default['table'] . 'prop';
  1137. $storage_args['type_column'] = 'type_id';
  1138. $storage_args['type_id'] = $form_state['prop_term']->cvterm_id;
  1139. $storage_args['type_value'] = $default['prop_term_value'];
  1140. }
  1141. // If the user indicated they wanted to use the linker tables then we'll
  1142. // set the storage args and return.
  1143. else if ($default['use_linker'] == 'Yes') {
  1144. $storage_args['data_table'] = $default['table'];
  1145. $storage_args['type_id'] = $form_state['values']['selected_cvterm_id'];
  1146. $storage_args['type_linker_table'] = $default['table'] . '_cvterm';
  1147. $storage_args['type_column'] = 'cvterm_id';
  1148. }
  1149. }