ChadoFieldGetValuesListTest.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. <?php
  2. namespace Tests\tripal_chado\fields;
  3. use StatonLab\TripalTestSuite\DBTransaction;
  4. use StatonLab\TripalTestSuite\TripalTestCase;
  5. /**
  6. * Test ChadoField->getValueList() Method.
  7. */
  8. class ChadoFieldGetValuesListTest extends TripalTestCase {
  9. // Uncomment to auto start and rollback db transactions per test method.
  10. use DBTransaction;
  11. // Stores a list of field instances to be tested including their storage method and instance info.
  12. private $field_list = NULL;
  13. /**
  14. * Test getValueList for fields based on columns in the base table.
  15. *
  16. * @dataProvider getBaseFields
  17. *
  18. * @group fields
  19. * @group getValueList
  20. */
  21. public function testBaseTableColumns($field_name, $bundle_name, $info) {
  22. include_once(drupal_get_path('tripal_chado', 'module') . '/includes/TripalFields/ChadoField.inc');
  23. // Construct the Field instance we want the values for.
  24. // Specifying "ChadoField" here ensures we are only testing our
  25. // implementation of getValueList() and not the custom version for any
  26. // given field.
  27. // YOU SHOULD TEST CUSTOM FIELD IMPLEMENTATIONS SEPARATELY.
  28. $instance = new \ChadoField($info['field_info'], $info['instance_info']);
  29. // Retrieve the values.
  30. // $values will be an array containing the distinct set of values for this field instance.
  31. $values = $instance->getValueList(array('limit' => 5));
  32. // Ensure we have values returned!
  33. $this->assertTrue(
  34. is_array($values),
  35. t(
  36. 'No values returned for @field_name (bundle: @bundle_name, bundle base table: @bundle_base_table, chado table: @chado_table, chado column: @chado_column).',
  37. array(
  38. '@field_name' => $field_name,
  39. '@bundle_name' => $bundle_name,
  40. '@bundle_base_table' => $info['bundle_base_table'],
  41. '@chado_table' => $info['instance_info']['settings']['chado_table'],
  42. '@chado_column' => $info['instance_info']['settings']['chado_column'],
  43. )
  44. )
  45. );
  46. // Ensure there are no more then 5 as specified in the limit above.
  47. $this->assertLessThanOrEqual(5, sizeof($values),
  48. t('Returned too many results for @field_name.', array('@field_name' => $field_name)));
  49. // @todo Ensure a known value is in the list.
  50. // Note: This requires insertion of data using factories. However, there are not yet
  51. // factories for all chado tables and I don't know how to test if there is one for the
  52. // current bundle base table. See issue statonlab/TripalTestSuite#92
  53. }
  54. /**
  55. * DataProvider: a list of fields who store their data in the base table of a bundle.
  56. *
  57. * Each element describes a field instance and consists of:
  58. * - the machine name of the field (e.g. obi__organism).
  59. * - the machine name of the bundle (e.g. bio_data_17).
  60. * - an array of additional information including:
  61. * - instance_info: information about the field instance.
  62. * - field_info: information about the field.
  63. * - bundle: the TripalBundle object.
  64. * - bundle_base_table: if applicable, the chado base table the bundle stores it's data in.
  65. * - base_schema: the Tripal Schema array for the bundle_base_table.
  66. */
  67. public function getBaseFields() {
  68. // Retrieve a list of fields to test.
  69. // Note: this list is cached to improve performance.
  70. $fields = $this->retrieveFieldList();
  71. return $fields['field_chado_storage']['base'];
  72. }
  73. /**
  74. * Test for fields based on columns in the base table that are also foreign keys.
  75. *
  76. * @dataProvider getBaseFkFields
  77. *
  78. * @group fields
  79. * @group getValueList
  80. */
  81. public function testBaseTableForeignKey($field_name, $bundle_name, $info) {
  82. include_once(drupal_get_path('tripal_chado', 'module') . '/includes/TripalFields/ChadoField.inc');
  83. // Construct the Field instance we want the values for.
  84. // Specifying "ChadoField" here ensures we are only testing our
  85. // implementation of getValueList() and not the custom version for any
  86. // given field.
  87. // YOU SHOULD TEST CUSTOM FIELD IMPLEMENTATIONS SEPARATELY.
  88. $instance = new \ChadoField($info['field_info'], $info['instance_info']);
  89. // Retrieve the values using defaults.
  90. // $values will be an array containing the distinct set of values for this field instance.
  91. $values = $instance->getValueList(array('limit' => 5));
  92. // Ensure we have values returned!
  93. $this->assertTrue(
  94. is_array($values),
  95. t(
  96. 'No values returned for @field_name with no label string set (bundle: @bundle_name, bundle base table: @bundle_base_table, chado table: @chado_table, chado column: @chado_column).',
  97. array(
  98. '@field_name' => $field_name,
  99. '@bundle_name' => $bundle_name,
  100. '@bundle_base_table' => $info['bundle_base_table'],
  101. '@chado_table' => $info['instance_info']['settings']['chado_table'],
  102. '@chado_column' => $info['instance_info']['settings']['chado_column'],
  103. )
  104. )
  105. );
  106. // Ensure there are no more then 5 as specified in the limit above.
  107. $this->assertLessThanOrEqual(5, sizeof($values),
  108. t('Returned too many results for @field_name.', array('@field_name' => $field_name)));
  109. // @todo Ensure it works with a label string set.
  110. // @todo Ensure a known value is in the list.
  111. // Note: This requires insertion of data using factories. However, there are not yet
  112. // factories for all chado tables and I don't know how to test if there is one for the
  113. // current bundle base table. See issue statonlab/TripalTestSuite#92
  114. }
  115. /**
  116. * DataProvider: a list of fields who store their data in the base table of a bundle.
  117. *
  118. * Each element describes a field instance and consists of:
  119. * - the machine name of the field (e.g. obi__organism).
  120. * - the machine name of the bundle (e.g. bio_data_17).
  121. * - an array of additional information including:
  122. * - instance_info: information about the field instance.
  123. * - field_info: information about the field.
  124. * - bundle: the TripalBundle object.
  125. * - bundle_base_table: if applicable, the chado base table the bundle stores it's data in.
  126. * - base_schema: the Tripal Schema array for the bundle_base_table.
  127. */
  128. public function getBaseFkFields() {
  129. // Retrieve a list of fields to test.
  130. // Note: this list is cached to improve performance.
  131. $fields = $this->retrieveFieldList();
  132. return $fields['field_chado_storage']['foreign key'];
  133. }
  134. /**
  135. * Test for fields based on tables besides the base one for the bundle.
  136. * CURRENTLY RETRIEVING VALUES FOR THESE TABLES IS NOT SUPPORTED.
  137. *
  138. * @dataProvider getNonBaseFields
  139. *
  140. * @group fields
  141. * @group getValueList
  142. */
  143. public function testNonBaseTable($field_name, $bundle_name, $info) {
  144. include_once(drupal_get_path('tripal_chado', 'module') . '/includes/TripalFields/ChadoField.inc');
  145. // Construct the Field instance we want the values for.
  146. // Specifying "ChadoField" here ensures we are only testing our
  147. // implementation of getValueList() and not the custom version for any
  148. // given field.
  149. // YOU SHOULD TEST CUSTOM FIELD IMPLEMENTATIONS SEPARATELY.
  150. $instance = new \ChadoField($info['field_info'], $info['instance_info']);
  151. // Supress tripal errors
  152. putenv("TRIPAL_SUPPRESS_ERRORS=TRUE");
  153. ob_start();
  154. try {
  155. // Retrieve the values.
  156. // $values will be an array containing the distinct set of values for this field instance.
  157. $values = $instance->getValueList(array('limit' => 5));
  158. // @todo Check that we got the correct warning message.
  159. // Currently we can't check this because we need to supress the error in order to keep it from printing
  160. // but once we do, we can't access it ;-P
  161. } catch (Exception $e) {
  162. $this->fail("Although we don't support values lists for $field_name, it still shouldn't produce an exception!");
  163. }
  164. // Clean the buffer and unset tripal errors suppression
  165. ob_end_clean();
  166. putenv("TRIPAL_SUPPRESS_ERRORS");
  167. $this->assertFalse($values, "We don't support retrieving values for $field_name since it doesn't store data in the base table.");
  168. }
  169. /**
  170. * DataProvider: a list of fields who store their data in the base table of a bundle.
  171. *
  172. * Each element describes a field instance and consists of:
  173. * - the machine name of the field (e.g. obi__organism).
  174. * - the machine name of the bundle (e.g. bio_data_17).
  175. * - an array of additional information including:
  176. * - instance_info: information about the field instance.
  177. * - field_info: information about the field.
  178. * - bundle: the TripalBundle object.
  179. * - bundle_base_table: if applicable, the chado base table the bundle stores it's data in.
  180. * - base_schema: the Tripal Schema array for the bundle_base_table.
  181. */
  182. public function getNonBaseFields() {
  183. // Retrieve a list of fields to test.
  184. // Note: this list is cached to improve performance.
  185. $fields = $this->retrieveFieldList();
  186. return $fields['field_chado_storage']['referring'];
  187. }
  188. /**
  189. * Returns a list of Fields sorted by their backend, etc. for use in tests.
  190. */
  191. private function retrieveFieldList() {
  192. if ($this->field_list === NULL) {
  193. $this->field_list = array();
  194. // field_info_instances() retrieves a list of all the field instances in the current site,
  195. // indexed by the bundle it is attached to.
  196. // @todo use fake bundles here to make these tests less dependant upon the current site.
  197. $bundles = field_info_instances('TripalEntity');
  198. foreach($bundles as $bundle_name => $fields) {
  199. // Load the bundle object to later determine the chado table.
  200. $bundle = tripal_load_bundle_entity(array('name'=> $bundle_name));
  201. // For each field instance...
  202. foreach ($fields as $field_name => $instance_info) {
  203. $bundle_base_table = $base_schema = NULL;
  204. // Load the field info.
  205. $field_info = field_info_field($field_name);
  206. // Determine the storage backend.
  207. $storage = $field_info['storage']['type'];
  208. // If this field stores it's data in chado...
  209. // Determine the relationship between this field and the bundle base table.
  210. $rel = NULL;
  211. if ($storage == 'field_chado_storage') {
  212. // We need to know the table this field stores it's data in.
  213. $bundle_base_table = $bundle->data_table;
  214. // and the schema for that table.
  215. $base_schema = chado_get_schema($bundle_base_table);
  216. // and the table this field stores it's data in.
  217. $field_table = $instance_info['settings']['chado_table'];
  218. $field_column = $instance_info['settings']['chado_column'];
  219. // By default we simply assume there is some relationship.
  220. $rel = 'referring';
  221. // If the field and bundle store their data in the same table
  222. // then it's either a "base" or "foreign key" relationship
  223. // based on the schema.
  224. if ($bundle_base_table == $field_table) {
  225. // We assume it's not a foreign key...
  226. $rel = 'base';
  227. // and then check the schema to see if we're wrong :-)
  228. foreach ($base_schema['foreign keys'] as $schema_info) {
  229. if (isset($schema_info['columns'][ $field_column ])) { $rel = 'foreign key'; }
  230. }
  231. }
  232. }
  233. // Store all the info about bundle, field, instance, schema for use in the test.
  234. $info = array(
  235. 'field_name' => $field_name,
  236. 'bundle_name' => $bundle_name,
  237. 'bundle' => $bundle,
  238. 'bundle_base_table' => $bundle_base_table,
  239. 'base_schema' => $base_schema,
  240. 'field_info' => $field_info,
  241. 'instance_info' => $instance_info,
  242. );
  243. // Create a unique key.
  244. $key = $bundle_name . '--' . $field_name;
  245. // If this bundle uses chado and we know the fields relationship to the base
  246. // chado table, then we want to index the field list by that relationship.
  247. if ($rel) {
  248. $this->field_list[$storage][$rel][$key] = array(
  249. $field_name,
  250. $bundle_name,
  251. $info
  252. );
  253. }
  254. else {
  255. $this->field_list[$storage][$key] = array(
  256. $field_name,
  257. $bundle_name,
  258. $info
  259. );
  260. }
  261. }
  262. }
  263. }
  264. return $this->field_list;
  265. }
  266. }