tripal_core.chado_general.api.inc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  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) and $props) {
  263. $props = array($props);
  264. }
  265. if (count($props) > 0) {
  266. // The property is already assigned, so, see if we should update it.
  267. if ($update_if_present) {
  268. return chado_update_property($record, $property);
  269. }
  270. else {
  271. if (!$force_rank) {
  272. // iterate through the properties returned and check to see if the
  273. // property with this value already exists if not, get the largest rank
  274. // and insert the same property but with this new value
  275. foreach ($props as $prop) {
  276. if ($prop->rank > $rank) {
  277. $rank = $prop->rank;
  278. }
  279. if (strcmp($prop->value, $value) == 0) {
  280. return TRUE;
  281. }
  282. }
  283. // now add 1 to the rank
  284. $rank++;
  285. }
  286. else {
  287. tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_insert_property: " .
  288. "The property is already assigned to the record with the following " .
  289. "rank. And, because the 'force_rank' option is used, the property " .
  290. "cannot be added: %property.",
  291. array('%property' => print_r($property, true)));
  292. return FALSE;
  293. }
  294. }
  295. }
  296. // Build the values array for checking if the CVterm exists and for
  297. // inserting the term as a property.
  298. $values = array();
  299. if ($cv_id) {
  300. $values['cv_id'] = $cv_id;
  301. }
  302. if ($cv_name) {
  303. $values['cv_id'] = array(
  304. 'name' => $cv_name,
  305. );
  306. }
  307. if ($type_name) {
  308. $values['name'] = $type_name;
  309. }
  310. if ($type_id) {
  311. $values['cvterm_id'] = $type_id;
  312. }
  313. // Make sure the CV term exists;
  314. $options = array();
  315. $term = chado_select_record('cvterm', array('cvterm_id'), $values, $options);
  316. if (!$term or count($term) == 0) {
  317. tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_insert_property: " .
  318. "Cannot find the term described by: %property.",
  319. array('%property' => print_r($property, TRUE)));
  320. return FALSE;
  321. }
  322. if (count($term) > 1) {
  323. tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_insert_property: " .
  324. "Multiple terms found. Cannot add the property. Property was described " .
  325. "by: %property.",
  326. array('%property' => print_r($property, TRUE))); return FALSE;
  327. }
  328. // Get the foreign key for this property table
  329. $table_desc = chado_get_schema($base_table . 'prop');
  330. $fkcol = key($table_desc['foreign keys'][$base_table]['columns']);
  331. // Add the property to the record.
  332. $values = array(
  333. $fkcol => $base_id,
  334. 'type_id' => $values,
  335. 'value' => $value,
  336. 'rank' => $rank,
  337. );
  338. $result = chado_insert_record($base_table . 'prop', $values);
  339. return $result;
  340. }
  341. /**
  342. * Update a property for a given base table record and property name.
  343. *
  344. * @param $record
  345. * An associative array used to identify the record to which the property
  346. * should be updated. The following keys must be used:
  347. * -table: The base table for which the property should be updated.
  348. * Thus to update a property for a feature the base_table=feature.
  349. * -id: The primary key value of the base table. The property will be
  350. * associated with the record that matches this id.
  351. * -prop_id: The primary key in the [table]prop table. If this value
  352. * is supplied then the 'table' and 'id' keys are not needed.
  353. * @param $property
  354. * An associative array used to specify the property to be updated. It can
  355. * contain the following keys. The keys must be specified to uniquely identify
  356. * the term to be applied. If the options identify more than one CV term
  357. * then an error will occur.
  358. * -type_name: The cvterm name to be selected.
  359. * -type_id: The cvterm_id of the term to be selected.
  360. * -cv_id: The cv_id of the CV that contains the term.
  361. * -cv_name: The name of the CV that contains the term.
  362. * -value: The specific value for the property.
  363. * -rank: The specific rank for the property.
  364. * @param $options
  365. * An associative array containing the following keys:
  366. * -insert_if_missing: A boolean indicating whether a record should be
  367. * inserted if one doesn't exist to update.
  368. *
  369. *
  370. * @return
  371. * Return TRUE on Update/Insert and FALSE otherwise
  372. *
  373. * @ingroup tripal_chado_api
  374. */
  375. function chado_update_property($record, $property, $options = array()) {
  376. $base_table = array_key_exists('table', $record) ? $record['table'] : '';
  377. $base_id = array_key_exists('id', $record) ? $record['id'] : '';
  378. $prop_id = array_key_exists('prop_id', $record) ? $record['prop_id'] : '';
  379. $type_name = array_key_exists('type_name', $property) ? $property['type_name'] : '';
  380. $type_id = array_key_exists('type_id', $property) ? $property['type_id'] : '';
  381. $cv_name = array_key_exists('cv_name', $property) ? $property['cv_name'] : '';
  382. $cv_id = array_key_exists('cv_id', $property) ? $property['cv_id'] : '';
  383. $value = array_key_exists('value', $property) ? $property['value'] : '';
  384. $rank = array_key_exists('rank', $property) ? $property['rank'] : 0;
  385. $insert_if_missing = array_key_exists('insert_if_missing', $options) ? $options['insert_if_missing'] : FALSE;
  386. // first see if the property is missing (we can't update a missing property
  387. $prop = chado_get_property($record, $property);
  388. if (count($prop) == 0) {
  389. if ($insert_if_missing) {
  390. return chado_insert_property($record, $property);
  391. }
  392. else {
  393. return FALSE;
  394. }
  395. }
  396. // Build the values array for checking if the CVterm exists.
  397. $type = array();
  398. if ($cv_id) {
  399. $type['cv_id'] = $cv_id;
  400. }
  401. if ($cv_name) {
  402. $type['cv_id'] = array(
  403. 'name' => $cv_name,
  404. );
  405. }
  406. if ($type_name) {
  407. $type['name'] = $type_name;
  408. }
  409. if ($type_id) {
  410. $type['cvterm_id'] = $type_id;
  411. }
  412. // Make sure the CV term exists;
  413. $options = array();
  414. $term = chado_select_record('cvterm', array('cvterm_id'), $type, $options);
  415. if (!$term or count($term) == 0) {
  416. tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_update_property: " .
  417. "Cannot find the term described by: %property.",
  418. array('%property' => print_r($property, TRUE)));
  419. return FALSE;
  420. }
  421. if (count($term) > 1) {
  422. tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_update_property: " .
  423. "Multiple terms found. Cannot add the property. Property was described " .
  424. "by: %property.",
  425. array('%property' => print_r($property, TRUE)));
  426. return FALSE;
  427. }
  428. // Get the foreign key for this property table
  429. $table_desc = chado_get_schema($base_table . 'prop');
  430. $fkcol = key($table_desc['foreign keys'][$base_table]['columns']);
  431. // construct the array that will match the exact record to update
  432. $match = array(
  433. $fkcol => $base_id,
  434. 'type_id' => $type,
  435. );
  436. // If we have the unique property_id, make sure to use it in the match to
  437. // ensure we get the exact record. Doesn't rely on there only being one
  438. // property of that type.
  439. if ($prop_id) {
  440. $property_pkey = $table_desc['primary key'][0];
  441. $match = array(
  442. $property_pkey => $prop_id,
  443. );
  444. }
  445. // Construct the array of values to be updated.
  446. $values = array();
  447. $values['value'] = $value;
  448. if ($rank) {
  449. $values['rank'] = $rank;
  450. }
  451. // If we have the unique property_id then we can also update the type
  452. // thus add it to the values to be updated
  453. if ($prop_id) {
  454. $values['type_id'] = $type;
  455. }
  456. return chado_update_record($base_table . 'prop', $match, $values);
  457. }
  458. /**
  459. * Deletes a property for a given base table record using the property name
  460. *
  461. * @param $record
  462. * An associative array used to identify the record to which the property
  463. * should be deleted. The following keys must be used:
  464. * -table: The base table for which the property should be deleted.
  465. * Thus to update a property for a feature the base_table=feature.
  466. * -id: The primary key value of the base table. The property will be
  467. * deleted from the record that matches this id.
  468. * -prop_id: The primary key in the [table]prop table to be deleted. If
  469. * this value is supplied then the 'table' and 'id' keys are not needed.
  470. * @param $property
  471. * An associative array used to specify the property to be updated. It can
  472. * contain the following keys. The keys must be specified to uniquely identify
  473. * the term to be applied. If the options identify more than one CV term
  474. * then an error will occur.
  475. * -type_name: The cvterm name to be selected.
  476. * -type_id: The cvterm_id of the term to be selected.
  477. * -cv_id: The cv_id of the CV that contains the term.
  478. * -cv_name: The name of the CV that contains the term.
  479. * -value: The specific value for the property.
  480. * -rank: The specific rank for the property.
  481. *
  482. * @return
  483. * Return TRUE on successful deletion and FALSE otherwise
  484. *
  485. * @ingroup tripal_chado_api
  486. */
  487. function chado_delete_property($record, $property) {
  488. $base_table = array_key_exists('table', $record) ? $record['table'] : '';
  489. $base_id = array_key_exists('id', $record) ? $record['id'] : '';
  490. $prop_id = array_key_exists('prop_id', $record) ? $record['prop_id'] : '';
  491. $type_name = array_key_exists('type_name', $property) ? $property['type_name'] : '';
  492. $type_id = array_key_exists('type_id', $property) ? $property['type_id'] : '';
  493. $cv_name = array_key_exists('cv_name', $property) ? $property['cv_name'] : '';
  494. $cv_id = array_key_exists('cv_id', $property) ? $property['cv_id'] : '';
  495. $value = array_key_exists('value', $property) ? $property['value'] : '';
  496. $rank = array_key_exists('rank', $property) ? $property['rank'] : 0;
  497. // Build the values array for checking if the CVterm exists
  498. $type = array();
  499. if ($cv_id) {
  500. $type['cv_id'] = $cv_id;
  501. }
  502. if ($cv_name) {
  503. $type['cv_id'] = array(
  504. 'name' => $cv_name,
  505. );
  506. }
  507. if ($type_name) {
  508. $type['name'] = $type_name;
  509. }
  510. if ($type_id) {
  511. $type['cvterm_id'] = $type_id;
  512. }
  513. // Make sure the CV term exists;
  514. $options = array();
  515. $term = chado_select_record('cvterm', array('cvterm_id'), $type, $options);
  516. if (!$term or count($term) == 0) {
  517. tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_delete_property: " .
  518. "Cannot find the term described by: %property.",
  519. array('%property' => print_r($property, TRUE)));
  520. return FALSE;
  521. }
  522. if (count($term) > 1) {
  523. tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_delete_property: " .
  524. "Multiple terms found. Cannot add the property. Property was described " .
  525. "by: %property.",
  526. array('%property' => print_r($property, TRUE))); return FALSE;
  527. }
  528. // get the foreign key for this property table
  529. $table_desc = chado_get_schema($base_table . 'prop');
  530. $fkcol = key($table_desc['foreign keys'][$base_table]['columns']);
  531. // If we have the unique property_id, make sure to use it in the match to ensure
  532. // we get the exact record. Doesn't rely on there only being one property of that type
  533. if ($prop_id) {
  534. $property_pkey = $table_desc['primary key'][0];
  535. $match = array(
  536. $property_pkey => $prop_id
  537. );
  538. }
  539. // construct the array that will match the exact record to update
  540. else {
  541. $match = array(
  542. $fkcol => $record_id,
  543. 'type_id' => $type,
  544. );
  545. }
  546. return chado_delete_record($base_table . 'prop', $match);
  547. }
  548. /**
  549. * Get all records in the base table assigned one or more properties.
  550. *
  551. * The property or properties of interest are specified using the $property
  552. * argument.
  553. *
  554. * @param $record
  555. * An associative array used to identify the table and subset of records to
  556. * to be searched:
  557. * -table: The base table for which the property should be updated.
  558. * Thus to update a property for a feature the base_table=feature.
  559. * -base_records: An array in the format accepted by the chado_select_record
  560. * for specifying a subset of records in the base table.
  561. * @param $property
  562. * An associative array used to specify the property to be selected for. It
  563. * can contain the following keys. The keys must be specified to uniquely
  564. * identify the term to be searched. If the options identify more than one
  565. * CV term then an error will occur.
  566. * -type_name: The cvterm name to be selected.
  567. * -type_id: The cvterm_id of the term to be selected.
  568. * -cv_id: The cv_id of the CV that contains the term.
  569. * -cv_name: The name of the CV that contains the term.
  570. * -value: The specific value for the property.
  571. * -rank: The specific rank for the property.
  572. * @param $options
  573. * An array of options supported by chado_generate_var(). These keys
  574. * are used for generating the cvterm objects returned by this function.
  575. *
  576. * @return
  577. * An array of chado variables with the given property
  578. *
  579. * @ingroup tripal_chado_api
  580. */
  581. function chado_get_record_with_property($record, $property, $options = array()) {
  582. $base_table = array_key_exists('table', $record) ? $record['table'] : '';
  583. $base_records= array_key_exists('base_records', $record) ? $record['base_records'] : array();
  584. $type_name = array_key_exists('type_name', $property) ? $property['type_name'] : '';
  585. $type_id = array_key_exists('type_id', $property) ? $property['type_id'] : '';
  586. $cv_name = array_key_exists('cv_name', $property) ? $property['cv_name'] : '';
  587. $cv_id = array_key_exists('cv_id', $property) ? $property['cv_id'] : '';
  588. $value = array_key_exists('value', $property) ? $property['value'] : '';
  589. $rank = array_key_exists('rank', $property) ? $property['rank'] : '';
  590. $property_table = $base_table . 'prop';
  591. $foreignkey_name = $base_table . '_id';
  592. // Build the values array for checking if the CVterm exists and for
  593. // inserting the term as a property.
  594. $type = array();
  595. if ($cv_id) {
  596. $type['cv_id'] = $cv_id;
  597. }
  598. if ($cv_name) {
  599. $type['cv_id'] = array(
  600. 'name' => $cv_name,
  601. );
  602. }
  603. if ($type_name) {
  604. $type['name'] = $type_name;
  605. }
  606. if ($type_id) {
  607. $type['cvterm_id'] = $type_id;
  608. }
  609. // Make sure the CV term exists;
  610. $term = chado_select_record('cvterm', array('cvterm_id'), $type);
  611. if (!$term or count($term) == 0) {
  612. tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_update_property: " .
  613. "Cannot find the term described by: %property.",
  614. array('%property' => print_r($property, TRUE)));
  615. return FALSE;
  616. }
  617. if (count($term) > 1) {
  618. tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_update_property: " .
  619. "Multiple terms found. Cannot add the property. Property was described " .
  620. "by: %property.",
  621. array('%property' => print_r($property, TRUE))); return FALSE;
  622. }
  623. // Build the array for identifying the property.
  624. $values = array();
  625. $values['type_id'] = $type;
  626. if ($rank) {
  627. $values['rank'] = $rank;
  628. }
  629. if ($value) {
  630. $values['value'] = $value;
  631. }
  632. // Add the base records details to the values array.
  633. if (!empty($base_records)) {
  634. $values[$foreignkey_name] = $base_records;
  635. }
  636. // Now select the ids of the base table that have the properties we want that match.
  637. $select = chado_select_record($property_table, array($foreignkey_name), $values);
  638. // For each of these ids, pull out the full base records
  639. $records = array();
  640. foreach ($select as $s) {
  641. $id = $s->{$foreignkey_name};
  642. $values = array($foreignkey_name => $id);
  643. $records[$id] = chado_generate_var($base_table, $values, $options);
  644. }
  645. return $records;
  646. }