tripal_core.chado_general.api.inc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711
  1. <?php
  2. /**
  3. * @file
  4. * Provides an application programming interface (API) to manage data withing the Chado database.
  5. */
  6. require_once 'tripal_core.schema_v1.2.api.inc';
  7. require_once 'tripal_core.schema_v1.11.api.inc';
  8. /**
  9. * @defgroup tripal_chado_api Chado API
  10. * @ingroup tripal_core_api
  11. * @{
  12. * Provides an application programming interface (API) to manage data withing the Chado database.
  13. *
  14. * This includes functions for selecting, inserting, updating and deleting records
  15. * in Chado tables. The functions will ensure proper integrity contraints are met
  16. * for inserts and updates.
  17. *
  18. * Also, a set of functions is provided for creating template variables. First,
  19. * is the chado_generate_var which is used to select one ore more
  20. * records from a table and return an array with foreign key relationships fully
  21. * populated. For example, if selecting a feature, the organism_id and type_id
  22. * would be present in the returned array as a nested array with their respective
  23. * foreign keys also nested. The only fields that are not included are text
  24. * fields (which may be very large) or many-to-many foreign key relationships.
  25. * However, these fields and relationships can be expanded using the
  26. * chado_expand_var.
  27. *
  28. * When a row from a chado table is selected using these two functions, it provides
  29. * a way for users who want to cutomize Drupal template files to access all data
  30. * associate with a specific record.
  31. *
  32. * Finally, the property tables in Chado generally follow the same format. Therefore
  33. * there is a set of functions for inserting, updating and deleting properties for
  34. * any table. This provides quick lookup of properties (provided the CV term is
  35. * known).
  36. *
  37. * @}
  38. *
  39. */
  40. /**
  41. * Set the Tripal Database
  42. *
  43. * The chado_set_active function is used to prevent namespace collisions
  44. * when chado and drupal are installed in the same database but in different
  45. * schemas. It is also used for backwards compatibility with older versions
  46. * of tripal or in cases where chado is located outside of the Drupal database.
  47. * or when using Drupal functions such as db_table_exists()
  48. *
  49. * @ingroup tripal_chado_api
  50. */
  51. function chado_set_active($dbname = 'default') {
  52. global $databases, $active_db;
  53. if ($dbname ) {
  54. if ($dbname == 'chado') {
  55. db_query('set search_path to chado,public');
  56. return 'default';
  57. }
  58. else {
  59. db_query('set search_path to public');
  60. return 'chado';
  61. }
  62. }
  63. // if the 'chado' database is in the $db_url variable then chado is
  64. // not in the same Drupal database, so we don't need to set any
  65. // search_path and can just change the database
  66. elseif (array_key_exists($dbname, $databases)) {
  67. return db_set_active($dbname);
  68. }
  69. }
  70. /**
  71. * Get max rank for a given set of criteria
  72. * This function was developed with the many property tables in chado in mind but will
  73. * work for any table with a rank
  74. *
  75. * @params tablename: the name of the chado table you want to select the max rank from
  76. * this table must contain a rank column of type integer
  77. * @params where_options: array(
  78. * <column_name> => array(
  79. * 'type' => <type of column: INT/STRING>,
  80. * 'value' => <the value you want to filter on>,
  81. * 'exact' => <if TRUE use =; if FALSE use ~>,
  82. * )
  83. * )
  84. * where options should include the id and type for that table to correctly
  85. * group a set of records together where the only difference are the value and rank
  86. * @return the maximum rank
  87. *
  88. * @ingroup tripal_chado_api
  89. */
  90. function chado_get_table_max_rank($tablename, $where_options) {
  91. $where_clauses = array();
  92. $where_args = array();
  93. //generate the where clause from supplied options
  94. // the key is the column name
  95. $i = 0;
  96. $sql = "
  97. SELECT max(rank) as max_rank, count(rank) as count
  98. FROM {".$tablename."}
  99. WHERE
  100. ";
  101. foreach ($where_options as $key => $value) {
  102. $where_clauses[] = "$key = :$key";
  103. $where_args[":$key"] = $value;
  104. }
  105. $sql .= implode($where_clauses, ' AND ');
  106. $result = chado_query($sql, $where_args)->fetchObject();
  107. if ($result->count > 0) {
  108. return $result->max_rank;
  109. }
  110. else {
  111. return -1;
  112. }
  113. }
  114. /**
  115. * Retrieve a property for a given base table record.
  116. *
  117. * @param $record
  118. * An array used to identify the record to which the property is associated.
  119. * The following keys must be used:
  120. * -table: The base table for which the property should be updated.
  121. * Thus to update a property for a feature the base_table=feature.
  122. * -id: The primary key value of the base table. The property will be
  123. * associated with the record that matches this id.
  124. * -prop_id: The primary key in the [table]prop table. If this value
  125. * is supplied then the 'table' and 'id' keys are not needed.
  126. * @param $property
  127. * An associative array used to specify the property to be selected. It can
  128. * contain the following keys. The keys must be specified to uniquely identify
  129. * the term to be applied. If the options identify more than one CV term
  130. * then an error will occur.
  131. * -type_name: The cvterm name to be selected.
  132. * -type_id: The cvterm_id of the term to be selected.
  133. * -cv_id: The cv_id of the CV that contains the term.
  134. * -cv_name: The name of the CV that contains the term.
  135. * -value: The specific value for the property.
  136. * -rank: The specific rank for the property.
  137. * @return
  138. * An array in the same format as that generated by the function
  139. * chado_generate_var(). If only one record is returned it
  140. * is a single object. If more than one record is returned then it is an array
  141. * of objects
  142. *
  143. * @ingroup tripal_chado_api
  144. */
  145. function chado_get_property($record, $property) {
  146. $base_table = array_key_exists('table', $record) ? $record['table'] : '';
  147. $base_id = array_key_exists('id', $record) ? $record['id'] : '';
  148. $prop_id = array_key_exists('prop_id', $record) ? $record['prop_id'] : '';
  149. $type_name = array_key_exists('type_name', $property) ? $property['type_name'] : '';
  150. $type_id = array_key_exists('type_id', $property) ? $property['type_id'] : '';
  151. $cv_name = array_key_exists('cv_name', $property) ? $property['cv_name'] : '';
  152. $cv_id = array_key_exists('cv_id', $property) ? $property['cv_id'] : '';
  153. $value = array_key_exists('value', $property) ? $property['value'] : '';
  154. $rank = array_key_exists('rank', $property) ? $property['rank'] : 0;
  155. // Build the values array for checking if the CVterm exists and for
  156. // retrieving the term as a property.
  157. $type = array();
  158. if ($cv_id) {
  159. $type['cv_id'] = $cv_id;
  160. }
  161. if ($cv_name) {
  162. $type['cv_id'] = array(
  163. 'name' => $cv_name,
  164. );
  165. }
  166. if ($type_name) {
  167. $type['name'] = $type_name;
  168. }
  169. if ($type_id) {
  170. $type['cvterm_id'] = $type_id;
  171. }
  172. // Make sure the CV term exists;
  173. $options = array();
  174. $term = chado_select_record('cvterm', array('cvterm_id'), $type, $options);
  175. if (!$term or count($term) == 0) {
  176. tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_get_property: " .
  177. "Cannot find the term described by: %property.",
  178. array('%property' => print_r($property, TRUE)));
  179. return FALSE;
  180. }
  181. if (count($term) > 1) {
  182. tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_get_property: " .
  183. "Multiple terms found. Cannot add the property. Property was described " .
  184. "by: %property.",
  185. array('%property' => print_r($property, TRUE))); return FALSE;
  186. }
  187. // get the foreign key for this property table
  188. $table_desc = chado_get_schema($base_table . 'prop');
  189. $fkcol = key($table_desc['foreign keys'][$base_table]['columns']);
  190. // construct the array of values to be selected
  191. $values = array(
  192. $fkcol => $base_id,
  193. 'type_id' => $type,
  194. );
  195. // if we have the unique property_id make sure to add that to the values
  196. if ($prop_id) {
  197. $property_pkey = $table_desc['primary key'][0];
  198. $values[$property_pkey] = $prop_id;
  199. }
  200. $results = chado_generate_var($base_table . 'prop', $values);
  201. if ($results) {
  202. $results = chado_expand_var($results, 'field', $base_table . 'prop.value');
  203. }
  204. return $results;
  205. }
  206. /**
  207. * Insert a property for a given base table.
  208. *
  209. * By default if the property already exists a new property is added with the
  210. * next available rank. If the option 'update_if_present' is specified then
  211. * the record will be updated if it exists rather than adding a new property.
  212. *
  213. * @param $record
  214. * An associative array used to identify the record to which the property
  215. * should be assigned. The following keys must be used:
  216. * -table: The base table for which the property should be inserted.
  217. * Thus to insert a property for a feature the base_table=feature and
  218. * property is inserted into featureprop
  219. * -id: The primary key value of the base table. The property will be
  220. * associated with the record that matches this id.
  221. * @param $property
  222. * An associative array used to specify the property to be added. It can
  223. * contain the following keys. The keys must be specified to uniquely identify
  224. * the term to be applied. If the options identify more than one CV term
  225. * then an error will occur.
  226. * -type_name: The cvterm name to be selected.
  227. * -type_id: The cvterm_id of the term to be selected.
  228. * -cv_id: The cv_id of the CV that contains the term.
  229. * -cv_name: The name of the CV that contains the term.
  230. * -value: The specific value for the property.
  231. * -rank: The specific rank for the property.
  232. * @param $options
  233. * An associative array containing the following keys:
  234. * -update_if_present: A boolean indicating whether an existing record
  235. * should be updated. If the property already exists and this value is
  236. * not specified or is zero then a new property will be added with the
  237. * next largest rank.
  238. * -force_rank: If the specified rank is already used by another property
  239. * recrod for the same base_id, then set force_rank to TRUE to require
  240. * that only the specified rank can be used. Otherwise, the next
  241. * available rank will be used. If 'update_if_present' is FALSE and
  242. * 'force_rank' is set then an error will occur.
  243. *
  244. * @return
  245. * Return TRUE if successful and FALSE otherwise
  246. *
  247. * @ingroup tripal_chado_api
  248. */
  249. function chado_insert_property($record, $property, $options = array()) {
  250. $base_table = array_key_exists('table', $record) ? $record['table'] : '';
  251. $base_id = array_key_exists('id', $record) ? $record['id'] : '';
  252. $type_name = array_key_exists('type_name', $property) ? $property['type_name'] : '';
  253. $type_id = array_key_exists('type_id', $property) ? $property['type_id'] : '';
  254. $cv_name = array_key_exists('cv_name', $property) ? $property['cv_name'] : '';
  255. $cv_id = array_key_exists('cv_id', $property) ? $property['cv_id'] : '';
  256. $value = array_key_exists('value', $property) ? $property['value'] : '';
  257. $rank = array_key_exists('rank', $property) ? $property['rank'] : 0;
  258. $update_if_present = array_key_exists('update_if_present', $options) ? $options['update_if_present'] : FALSE;
  259. $force_rank = array_key_exists('force_rank', $options) ? $options['force_rank'] : FALSE;
  260. // First see if the property is already assigned to the record. I
  261. $props = chado_get_property($record, $property);
  262. if (!is_array($props)) {
  263. if ($props) {
  264. $props = array($props);
  265. }
  266. else {
  267. $props = array();
  268. }
  269. }
  270. if (count($props) > 0) {
  271. // The property is already assigned, so, see if we should update it.
  272. if ($update_if_present) {
  273. return chado_update_property($record, $property);
  274. }
  275. else {
  276. if (!$force_rank) {
  277. // iterate through the properties returned and check to see if the
  278. // property with this value already exists if not, get the largest rank
  279. // and insert the same property but with this new value
  280. foreach ($props as $prop) {
  281. if ($prop->rank > $rank) {
  282. $rank = $prop->rank;
  283. }
  284. if (strcmp($prop->value, $value) == 0) {
  285. return TRUE;
  286. }
  287. }
  288. // now add 1 to the rank
  289. $rank++;
  290. }
  291. else {
  292. tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_insert_property: " .
  293. "The property is already assigned to the record with the following " .
  294. "rank. And, because the 'force_rank' option is used, the property " .
  295. "cannot be added: %property.",
  296. array('%property' => print_r($property, true)));
  297. return FALSE;
  298. }
  299. }
  300. }
  301. // Build the values array for checking if the CVterm exists and for
  302. // inserting the term as a property.
  303. $values = array();
  304. if ($cv_id) {
  305. $values['cv_id'] = $cv_id;
  306. }
  307. if ($cv_name) {
  308. $values['cv_id'] = array(
  309. 'name' => $cv_name,
  310. );
  311. }
  312. if ($type_name) {
  313. $values['name'] = $type_name;
  314. }
  315. if ($type_id) {
  316. $values['cvterm_id'] = $type_id;
  317. }
  318. // Make sure the CV term exists;
  319. $options = array();
  320. $term = chado_select_record('cvterm', array('cvterm_id'), $values, $options);
  321. if (!$term or count($term) == 0) {
  322. tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_insert_property: " .
  323. "Cannot find the term described by: %property.",
  324. array('%property' => print_r($property, TRUE)));
  325. return FALSE;
  326. }
  327. if (count($term) > 1) {
  328. tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_insert_property: " .
  329. "Multiple terms found. Cannot add the property. Property was described " .
  330. "by: %property.",
  331. array('%property' => print_r($property, TRUE))); return FALSE;
  332. }
  333. // Get the foreign key for this property table
  334. $table_desc = chado_get_schema($base_table . 'prop');
  335. $fkcol = key($table_desc['foreign keys'][$base_table]['columns']);
  336. // Add the property to the record.
  337. $values = array(
  338. $fkcol => $base_id,
  339. 'type_id' => $values,
  340. 'value' => $value,
  341. 'rank' => $rank,
  342. );
  343. $result = chado_insert_record($base_table . 'prop', $values);
  344. return $result;
  345. }
  346. /**
  347. * Update a property for a given base table record and property name.
  348. *
  349. * @param $record
  350. * An associative array used to identify the record to which the property
  351. * should be updated. The following keys must be used:
  352. * -table: The base table for which the property should be updated.
  353. * Thus to update a property for a feature the base_table=feature.
  354. * -id: The primary key value of the base table. The property will be
  355. * associated with the record that matches this id.
  356. * -prop_id: The primary key in the [table]prop table. If this value
  357. * is supplied then the 'table' and 'id' keys are not needed.
  358. * @param $property
  359. * An associative array used to specify the property to be updated. It can
  360. * contain the following keys. The keys must be specified to uniquely identify
  361. * the term to be applied. If the options identify more than one CV term
  362. * then an error will occur.
  363. * -type_name: The cvterm name to be selected.
  364. * -type_id: The cvterm_id of the term to be selected.
  365. * -cv_id: The cv_id of the CV that contains the term.
  366. * -cv_name: The name of the CV that contains the term.
  367. * -value: The specific value for the property.
  368. * -rank: The specific rank for the property.
  369. * @param $options
  370. * An associative array containing the following keys:
  371. * -insert_if_missing: A boolean indicating whether a record should be
  372. * inserted if one doesn't exist to update.
  373. *
  374. *
  375. * @return
  376. * Return TRUE on Update/Insert and FALSE otherwise
  377. *
  378. * @ingroup tripal_chado_api
  379. */
  380. function chado_update_property($record, $property, $options = array()) {
  381. $base_table = array_key_exists('table', $record) ? $record['table'] : '';
  382. $base_id = array_key_exists('id', $record) ? $record['id'] : '';
  383. $prop_id = array_key_exists('prop_id', $record) ? $record['prop_id'] : '';
  384. $type_name = array_key_exists('type_name', $property) ? $property['type_name'] : '';
  385. $type_id = array_key_exists('type_id', $property) ? $property['type_id'] : '';
  386. $cv_name = array_key_exists('cv_name', $property) ? $property['cv_name'] : '';
  387. $cv_id = array_key_exists('cv_id', $property) ? $property['cv_id'] : '';
  388. $value = array_key_exists('value', $property) ? $property['value'] : '';
  389. $rank = array_key_exists('rank', $property) ? $property['rank'] : 0;
  390. $insert_if_missing = array_key_exists('insert_if_missing', $options) ? $options['insert_if_missing'] : FALSE;
  391. // first see if the property is missing (we can't update a missing property
  392. $prop = chado_get_property($record, $property);
  393. if (count($prop) == 0) {
  394. if ($insert_if_missing) {
  395. return chado_insert_property($record, $property);
  396. }
  397. else {
  398. return FALSE;
  399. }
  400. }
  401. // Build the values array for checking if the CVterm exists.
  402. $type = array();
  403. if ($cv_id) {
  404. $type['cv_id'] = $cv_id;
  405. }
  406. if ($cv_name) {
  407. $type['cv_id'] = array(
  408. 'name' => $cv_name,
  409. );
  410. }
  411. if ($type_name) {
  412. $type['name'] = $type_name;
  413. }
  414. if ($type_id) {
  415. $type['cvterm_id'] = $type_id;
  416. }
  417. // Make sure the CV term exists;
  418. $options = array();
  419. $term = chado_select_record('cvterm', array('cvterm_id'), $type, $options);
  420. if (!$term or count($term) == 0) {
  421. tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_update_property: " .
  422. "Cannot find the term described by: %property.",
  423. array('%property' => print_r($property, TRUE)));
  424. return FALSE;
  425. }
  426. if (count($term) > 1) {
  427. tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_update_property: " .
  428. "Multiple terms found. Cannot add the property. Property was described " .
  429. "by: %property.",
  430. array('%property' => print_r($property, TRUE)));
  431. return FALSE;
  432. }
  433. // Get the foreign key for this property table
  434. $table_desc = chado_get_schema($base_table . 'prop');
  435. $fkcol = key($table_desc['foreign keys'][$base_table]['columns']);
  436. // construct the array that will match the exact record to update
  437. $match = array(
  438. $fkcol => $base_id,
  439. 'type_id' => $type,
  440. );
  441. // If we have the unique property_id, make sure to use it in the match to
  442. // ensure we get the exact record. Doesn't rely on there only being one
  443. // property of that type.
  444. if ($prop_id) {
  445. $property_pkey = $table_desc['primary key'][0];
  446. $match = array(
  447. $property_pkey => $prop_id,
  448. );
  449. }
  450. // Construct the array of values to be updated.
  451. $values = array();
  452. $values['value'] = $value;
  453. if ($rank) {
  454. $values['rank'] = $rank;
  455. }
  456. // If we have the unique property_id then we can also update the type
  457. // thus add it to the values to be updated
  458. if ($prop_id) {
  459. $values['type_id'] = $type;
  460. }
  461. return chado_update_record($base_table . 'prop', $match, $values);
  462. }
  463. /**
  464. * Deletes a property for a given base table record using the property name
  465. *
  466. * @param $record
  467. * An associative array used to identify the record to which the property
  468. * should be deleted. The following keys must be used:
  469. * -table: The base table for which the property should be deleted.
  470. * Thus to update a property for a feature the base_table=feature.
  471. * -id: The primary key value of the base table. The property will be
  472. * deleted from the record that matches this id.
  473. * -prop_id: The primary key in the [table]prop table to be deleted. If
  474. * this value is supplied then the 'table' and 'id' keys are not needed.
  475. * @param $property
  476. * An associative array used to specify the property to be updated. It can
  477. * contain the following keys. The keys must be specified to uniquely identify
  478. * the term to be applied. If the options identify more than one CV term
  479. * then an error will occur.
  480. * -type_name: The cvterm name to be selected.
  481. * -type_id: The cvterm_id of the term to be selected.
  482. * -cv_id: The cv_id of the CV that contains the term.
  483. * -cv_name: The name of the CV that contains the term.
  484. * -value: The specific value for the property.
  485. * -rank: The specific rank for the property.
  486. *
  487. * @return
  488. * Return TRUE on successful deletion and FALSE otherwise
  489. *
  490. * @ingroup tripal_chado_api
  491. */
  492. function chado_delete_property($record, $property) {
  493. $base_table = array_key_exists('table', $record) ? $record['table'] : '';
  494. $base_id = array_key_exists('id', $record) ? $record['id'] : '';
  495. $prop_id = array_key_exists('prop_id', $record) ? $record['prop_id'] : '';
  496. $type_name = array_key_exists('type_name', $property) ? $property['type_name'] : '';
  497. $type_id = array_key_exists('type_id', $property) ? $property['type_id'] : '';
  498. $cv_name = array_key_exists('cv_name', $property) ? $property['cv_name'] : '';
  499. $cv_id = array_key_exists('cv_id', $property) ? $property['cv_id'] : '';
  500. $value = array_key_exists('value', $property) ? $property['value'] : '';
  501. $rank = array_key_exists('rank', $property) ? $property['rank'] : 0;
  502. // Build the values array for checking if the CVterm exists
  503. $type = array();
  504. if ($cv_id) {
  505. $type['cv_id'] = $cv_id;
  506. }
  507. if ($cv_name) {
  508. $type['cv_id'] = array(
  509. 'name' => $cv_name,
  510. );
  511. }
  512. if ($type_name) {
  513. $type['name'] = $type_name;
  514. }
  515. if ($type_id) {
  516. $type['cvterm_id'] = $type_id;
  517. }
  518. // Make sure the CV term exists;
  519. $options = array();
  520. $term = chado_select_record('cvterm', array('cvterm_id'), $type, $options);
  521. if (!$term or count($term) == 0) {
  522. tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_delete_property: " .
  523. "Cannot find the term described by: %property.",
  524. array('%property' => print_r($property, TRUE)));
  525. return FALSE;
  526. }
  527. if (count($term) > 1) {
  528. tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_delete_property: " .
  529. "Multiple terms found. Cannot add the property. Property was described " .
  530. "by: %property.",
  531. array('%property' => print_r($property, TRUE))); return FALSE;
  532. }
  533. // get the foreign key for this property table
  534. $table_desc = chado_get_schema($base_table . 'prop');
  535. $fkcol = key($table_desc['foreign keys'][$base_table]['columns']);
  536. // If we have the unique property_id, make sure to use it in the match to ensure
  537. // we get the exact record. Doesn't rely on there only being one property of that type
  538. if ($prop_id) {
  539. $property_pkey = $table_desc['primary key'][0];
  540. $match = array(
  541. $property_pkey => $prop_id
  542. );
  543. }
  544. // construct the array that will match the exact record to update
  545. else {
  546. $match = array(
  547. $fkcol => $record_id,
  548. 'type_id' => $type,
  549. );
  550. }
  551. return chado_delete_record($base_table . 'prop', $match);
  552. }
  553. /**
  554. * Get all records in the base table assigned one or more properties.
  555. *
  556. * The property or properties of interest are specified using the $property
  557. * argument.
  558. *
  559. * @param $record
  560. * An associative array used to identify the table and subset of records to
  561. * to be searched:
  562. * -table: The base table for which the property should be updated.
  563. * Thus to update a property for a feature the base_table=feature.
  564. * -base_records: An array in the format accepted by the chado_select_record
  565. * for specifying a subset of records in the base table.
  566. * @param $property
  567. * An associative array used to specify the property to be selected for. It
  568. * can contain the following keys. The keys must be specified to uniquely
  569. * identify the term to be searched. If the options identify more than one
  570. * CV term then an error will occur.
  571. * -type_name: The cvterm name to be selected.
  572. * -type_id: The cvterm_id of the term to be selected.
  573. * -cv_id: The cv_id of the CV that contains the term.
  574. * -cv_name: The name of the CV that contains the term.
  575. * -value: The specific value for the property.
  576. * -rank: The specific rank for the property.
  577. * @param $options
  578. * An array of options supported by chado_generate_var(). These keys
  579. * are used for generating the cvterm objects returned by this function.
  580. *
  581. * @return
  582. * An array of chado variables with the given property
  583. *
  584. * @ingroup tripal_chado_api
  585. */
  586. function chado_get_record_with_property($record, $property, $options = array()) {
  587. $base_table = array_key_exists('table', $record) ? $record['table'] : '';
  588. $base_records= array_key_exists('base_records', $record) ? $record['base_records'] : array();
  589. $type_name = array_key_exists('type_name', $property) ? $property['type_name'] : '';
  590. $type_id = array_key_exists('type_id', $property) ? $property['type_id'] : '';
  591. $cv_name = array_key_exists('cv_name', $property) ? $property['cv_name'] : '';
  592. $cv_id = array_key_exists('cv_id', $property) ? $property['cv_id'] : '';
  593. $value = array_key_exists('value', $property) ? $property['value'] : '';
  594. $rank = array_key_exists('rank', $property) ? $property['rank'] : '';
  595. $property_table = $base_table . 'prop';
  596. $foreignkey_name = $base_table . '_id';
  597. // Build the values array for checking if the CVterm exists and for
  598. // inserting the term as a property.
  599. $type = array();
  600. if ($cv_id) {
  601. $type['cv_id'] = $cv_id;
  602. }
  603. if ($cv_name) {
  604. $type['cv_id'] = array(
  605. 'name' => $cv_name,
  606. );
  607. }
  608. if ($type_name) {
  609. $type['name'] = $type_name;
  610. }
  611. if ($type_id) {
  612. $type['cvterm_id'] = $type_id;
  613. }
  614. // Make sure the CV term exists;
  615. $term = chado_select_record('cvterm', array('cvterm_id'), $type);
  616. if (!$term or count($term) == 0) {
  617. tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_update_property: " .
  618. "Cannot find the term described by: %property.",
  619. array('%property' => print_r($property, TRUE)));
  620. return FALSE;
  621. }
  622. if (count($term) > 1) {
  623. tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_update_property: " .
  624. "Multiple terms found. Cannot add the property. Property was described " .
  625. "by: %property.",
  626. array('%property' => print_r($property, TRUE))); return FALSE;
  627. }
  628. // Build the array for identifying the property.
  629. $values = array();
  630. $values['type_id'] = $type;
  631. if ($rank) {
  632. $values['rank'] = $rank;
  633. }
  634. if ($value) {
  635. $values['value'] = $value;
  636. }
  637. // Add the base records details to the values array.
  638. if (!empty($base_records)) {
  639. $values[$foreignkey_name] = $base_records;
  640. }
  641. // Now select the ids of the base table that have the properties we want that match.
  642. $select = chado_select_record($property_table, array($foreignkey_name), $values);
  643. // For each of these ids, pull out the full base records
  644. $records = array();
  645. foreach ($select as $s) {
  646. $id = $s->{$foreignkey_name};
  647. $values = array($foreignkey_name => $id);
  648. $records[$id] = chado_generate_var($base_table, $values, $options);
  649. }
  650. return $records;
  651. }