tripal_chado.fields.inc 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857
  1. <?php
  2. /**
  3. * Implements hook_field_info().
  4. *
  5. * This function would normally provide a large info array for all of the
  6. * fields provided by this module. But instead it will call a hook that
  7. * can be implmented within each individual field file. This will allow
  8. * all of the code for a single field to be self contained in a single file.
  9. *
  10. * New fields can be added automatically by including a new file in the
  11. * tripal_chado/includes/fields directory. The file must be named with a
  12. * 'chado_' prefix and end with a '.inc' suffix. After adding the file,
  13. * the cache must be cleared.
  14. *
  15. */
  16. function tripal_chado_field_info() {
  17. $info = array();
  18. // Find all of the files in the tripal_chado/includes/fields directory.
  19. $fields_path = drupal_get_path('module', 'tripal_chado') . '/includes/fields';
  20. $field_files = file_scan_directory($fields_path, '/^chado_.*\.inc$/');
  21. // Iterate through the fields, include the file and run the info function.
  22. foreach ($field_files as $file) {
  23. $field_type = $file->name;
  24. module_load_include('inc', 'tripal_chado', 'includes/fields/' . $field_type);
  25. if (preg_match('/^chado/', $field_type) and class_exists($field_type)) {
  26. $field_obj = new $field_type();
  27. $info[$field_type] = $field_obj->field_info();
  28. }
  29. }
  30. return $info;
  31. }
  32. /**
  33. * Implements hook_field_create_info().
  34. *
  35. * This is a Tripal defined hook that supports integration with the
  36. * TripalEntity field.
  37. */
  38. function tripal_chado_field_create_info($entity_type, $bundle, $term) {
  39. $bundle_name = $bundle->name;
  40. // The details array is used to pass to the TripalEntity->create_info()
  41. // function to provide more details about how the bundle is used by this
  42. // module.
  43. $details = array();
  44. // This array will hold details that map the bundle to tables in Chado.
  45. $bundle_data = array();
  46. // Get the cvterm that corresponds to this TripalTerm object.
  47. $vocab = entity_load('TripalVocab', array($term->vocab_id));
  48. $vocab = reset($vocab);
  49. $match = array(
  50. 'dbxref_id' => array(
  51. 'db_id' => array(
  52. 'name' => $vocab->vocabulary,
  53. ),
  54. 'accession' => $term->accession
  55. ),
  56. );
  57. $cvterm = chado_generate_var('cvterm', $match);
  58. // The organism table does not have a type_id so we won't ever find
  59. // a record for it in the tripal_cv_defaults table.
  60. if ($cvterm->name == 'organism') {
  61. $details = array(
  62. 'chado_cv_id' => $cvterm->cv_id->cv_id,
  63. 'chado_cvterm_id' => $cvterm->cvterm_id,
  64. 'chado_table' => 'organism',
  65. 'chado_type_table' => 'organism',
  66. 'chado_type_column' => '',
  67. );
  68. }
  69. // The analysis table does not have a type_id so we won't ever find
  70. // a record for it in the tripalcv_defaults table.
  71. else if ($cvterm->name == 'analysis') {
  72. $details = array(
  73. 'chado_cv_id' => $cvterm->cv_id->cv_id,
  74. 'chado_cvterm_id' => $cvterm->cvterm_id,
  75. 'chado_table' => 'analysis',
  76. 'chado_type_table' => 'analysis',
  77. 'chado_type_column' => '',
  78. );
  79. }
  80. else if ($cvterm->name == 'project') {
  81. $details = array(
  82. 'chado_cv_id' => $cvterm->cv_id->cv_id,
  83. 'chado_cvterm_id' => $cvterm->cvterm_id,
  84. 'chado_table' => 'project',
  85. 'chado_type_table' => 'project',
  86. 'chado_type_column' => '',
  87. );
  88. }
  89. else {
  90. // TODO: WHAT TO DO IF A VOCABULARY IS USED AS A DEFAULT FOR MULTIPLE
  91. // TABLES.
  92. // Look to see if this vocabulary is used as a default for any table.
  93. $default = db_select('tripal_cv_defaults', 't')
  94. ->fields('t')
  95. ->condition('cv_id', $cvterm->cv_id->cv_id)
  96. ->execute()
  97. ->fetchObject();
  98. if ($default) {
  99. $details = array(
  100. 'chado_cv_id' => $cvterm->cv_id->cv_id,
  101. 'chado_cvterm_id' => $cvterm->cvterm_id,
  102. 'chado_table' => $default->table_name,
  103. 'chado_type_table' => $default->table_name,
  104. 'chado_type_column' => $default->field_name,
  105. );
  106. }
  107. }
  108. // Save the mapping information so that we can reuse it when we need to
  109. // look things up for later (such as the hook_create_instance_info() function.
  110. tripal_set_bundle_variable('chado_cv_id', $bundle->id, $details['chado_cv_id']);
  111. tripal_set_bundle_variable('chado_cvterm_id', $bundle->id, $details['chado_cvterm_id']);
  112. tripal_set_bundle_variable('chado_table', $bundle->id, $details['chado_table']);
  113. tripal_set_bundle_variable('chado_type_table', $bundle->id, $details['chado_type_table']);
  114. tripal_set_bundle_variable('chado_type_column', $bundle->id, $details['chado_type_column']);
  115. $base_fields = tripal_chado_field_create_base('create_info', $entity_type, $bundle, $details);
  116. $custom_fields = tripal_chado_field_create_info_custom($entity_type, $bundle, $details);
  117. return array_merge($base_fields, $custom_fields);
  118. }
  119. /**
  120. * A helper function for the tripal_chado_field_create_info() function.
  121. *
  122. * This function adds in the custom fields info by instantiating the class
  123. * for the custom field, calling the create_info() function and
  124. * returning the info array.
  125. *
  126. * @param $entity_type
  127. * The type of entity (e.g TripalEntity)
  128. * @param $bundle
  129. * The bundle object.
  130. * @param $details
  131. * An array containing the mapping of the bundle to the Chado table.
  132. */
  133. function tripal_chado_field_create_info_custom($entity_type, $bundle, $details) {
  134. $info = array();
  135. // Find all of the files in the tripal_chado/includes/fields directory.
  136. $fields_path = drupal_get_path('module', 'tripal_chado') . '/includes/fields';
  137. $field_files = file_scan_directory($fields_path, '/^chado_.*\.inc$/');
  138. // Iterate through the fields, include the file and run the info function.
  139. foreach ($field_files as $file) {
  140. $field_type = $file->name;
  141. module_load_include('inc', 'tripal_chado', 'includes/fields/' . $field_type);
  142. if (preg_match('/^chado/', $field_type) and class_exists($field_type)) {
  143. $field_obj = new $field_type();
  144. $result = $field_obj->create_info($entity_type, $bundle, $details);
  145. if (is_array($result)) {
  146. $info[$result['field_name']] = $result;
  147. }
  148. }
  149. }
  150. return $info;
  151. }
  152. /**
  153. * Retrieves either the create_info or create_instance_info arrays.
  154. *
  155. * The logic for creating the fields for the base table is so similar for
  156. * both the create_info and create_instance_info arrays they are both
  157. * handled by this function to prevent duplication of code.
  158. *
  159. * @param $step
  160. * Set to 'create_info' to retrun the create_info array or
  161. * 'create_instance_info' to return the create_instance_info array.
  162. * @param $entity_type
  163. * The type of entity (e.g TripalEntity)
  164. * @param $bundle
  165. * The bundle object.
  166. * @param $details
  167. * An array containing the mapping of the bundle to the Chado table.
  168. *
  169. * @return
  170. * An array compabile with the tripal_chado_field_create_info() and
  171. * tripal_chado_field_create_instance_info() functions.
  172. */
  173. function tripal_chado_field_create_base($step, $entity_type, $bundle, $details) {
  174. $table_name = $details['chado_table'];
  175. $type_table = $details['chado_type_table'];
  176. $type_field = $details['chado_type_column'];
  177. // Iterate through the columns of the table and see if fields have been
  178. // created for each one. If not, then create them.
  179. $schema = chado_get_schema($table_name);
  180. $columns = $schema['fields'];
  181. $fields = array();
  182. foreach ($columns as $column_name => $details) {
  183. $field_name = $table_name . '__' . $column_name;
  184. // Skip the primary key field.
  185. if ($column_name == $schema['primary key'][0]) {
  186. continue;
  187. }
  188. // Skip the type field.
  189. if ($table_name == $type_table and $column_name == $type_field) {
  190. continue;
  191. }
  192. // Get the field defaults for this column.
  193. $field_info = array();
  194. if ($step == 'create_info') {
  195. $field_info = tripal_chado_field_create_info_base_defaults($field_name,
  196. $table_name, $schema, $column_name);
  197. }
  198. if ($step == 'create_instance_info') {
  199. $field_info = tripal_chado_field_create_instance_info_base_defaults($bundle->name,
  200. $field_name, $table_name, $schema, $column_name);
  201. }
  202. // TODO: add in a call to drupal_alter to allow other modules to change
  203. // the field settings.
  204. // Add the field to the bundle.
  205. $fields[$field_name] = $field_info;
  206. }
  207. return $fields;
  208. }
  209. /**
  210. * A helper function for the tripal_chado_field_create_info() function.
  211. *
  212. * This function generates the default chado_info array for a column in
  213. * a base table of Chado. All of fields returned by this function use
  214. * default Drupal fields to manage the data in Chado columns. For
  215. * custom handling of columns there are custom TripalEntity extensions that
  216. * are added by the tripal_chado_field_create_info_custom() function. A
  217. * custom field will superceed any default base field of the same name
  218. * provided here.
  219. *
  220. * @param $field_name
  221. * The name for the new field.
  222. * @param $table_name
  223. * The Chado table
  224. * @param $schema
  225. * The Drupal schema array for the Chado table.
  226. * @param $column_name
  227. * The name of the column in the Chado table.
  228. * @return
  229. * An associative array compatible with the tripal_chado_field_create_info()
  230. * function.
  231. */
  232. function tripal_chado_field_create_info_base_defaults($field_name, $table_name,
  233. $schema, $column_name) {
  234. $details = $schema['fields'][$column_name];
  235. // Set some defaults for the field.
  236. $field = array(
  237. 'field_name' => $field_name,
  238. 'type' => '',
  239. 'cardinality' => 1,
  240. 'locked' => FALSE,
  241. 'storage' => array(
  242. 'type' => 'field_chado_storage',
  243. ),
  244. 'settings' => array(
  245. 'chado_table' => $table_name,
  246. 'chado_column' => $column_name,
  247. 'semantic_web' => '',
  248. ),
  249. );
  250. // Alter the field info array depending on the column details.
  251. switch($details['type']) {
  252. case 'char':
  253. $field['type'] = 'text';
  254. $field['settings']['max_length'] = $details['length'];
  255. break;
  256. case 'varchar':
  257. $field['type'] = 'text';
  258. $field['settings']['max_length'] = $details['length'];
  259. break;
  260. case 'text':
  261. $field['type'] = 'text';
  262. $field['settings']['max_length'] = 17179869184;
  263. $field['settings']['text_processing'] = 1;
  264. break;
  265. case 'blob':
  266. // not sure how to support a blob field.
  267. continue;
  268. break;
  269. case 'int':
  270. $field['type'] = 'number_integer';
  271. break;
  272. case 'float':
  273. $field['type'] = 'number_float';
  274. $field['settings']['precision'] = 10;
  275. $field['settings']['scale'] = 2;
  276. $field['settings']['decimal_separator'] = '.';
  277. break;
  278. case 'numeric':
  279. $field['type'] = 'number_decimal';
  280. break;
  281. case 'serial':
  282. // Serial fields are most likely not needed as a field.
  283. break;
  284. case 'boolean':
  285. $field['type'] = 'list_boolean';
  286. $field['settings']['allowed_values'] = array(0 => "No", 1 => "Yes");
  287. break;
  288. case 'datetime':
  289. // Use the Drupal Date and Date API to create the field/widget
  290. $field['type'] = 'datetime';
  291. break;
  292. }
  293. // Set some default semantic web information
  294. if ($column_name == 'uniquename') {
  295. $field['settings']['text_processing'] = 0;
  296. }
  297. //
  298. // PUB TABLE
  299. //
  300. elseif ($table_name == 'pub' and $column_name == 'uniquename') {
  301. $field['type'] = 'text';
  302. $field['settings']['text_processing'] = 0;
  303. }
  304. //
  305. // ANALYSIS TABLE
  306. //
  307. elseif ($table_name == 'analysis' and $column_name == 'sourceuri') {
  308. $field['type'] = 'text';
  309. $field['settings']['text_processing'] = 0;
  310. }
  311. return $field;
  312. }
  313. /**
  314. * Implements hook_field_create_instance_info().
  315. *
  316. * This is a Tripal defined hook that supports integration with the
  317. * TripalEntity field.
  318. */
  319. function tripal_chado_field_create_instance_info($entity_type, $bundle, $term) {
  320. // Get the details about the mapping of this bundle to the Chado table:
  321. $details = array(
  322. 'chado_cv_id' => tripal_get_bundle_variable('chado_cv_id', $bundle->id),
  323. 'chado_cvterm_id' => tripal_get_bundle_variable('chado_cvterm_id', $bundle->id),
  324. 'chado_table' => tripal_get_bundle_variable('chado_table', $bundle->id),
  325. 'chado_type_table' => tripal_get_bundle_variable('chado_type_table', $bundle->id),
  326. 'chado_type_column' => tripal_get_bundle_variable('chado_type_column', $bundle->id),
  327. );
  328. $base_fields = tripal_chado_field_create_base('create_instance_info', $entity_type, $bundle, $details);
  329. $custom_fields = tripal_chado_field_create_instance_info_custom($entity_type, $bundle, $details);
  330. return array_merge($base_fields, $custom_fields);
  331. }
  332. /**
  333. * A helper function for the tripal_chado_field_create_instance_info() function.
  334. *
  335. * This function generates the default chado_instance_info array for a column in
  336. * a base table of Chado. All of fields returned by this function use
  337. * default Drupal fields to manage the data in Chado columns. For
  338. * custom handling of columns there are custom TripalEntity extensions that
  339. * are added by the tripal_chado_field_create_info_custom() function. A
  340. * custom field will superceed any default base field of the same name
  341. * provided here.
  342. *
  343. * @param $bundle_name
  344. * The name of the bundle to which this field will be attached.
  345. * @param $field_name
  346. * The name for the new field.
  347. * @param $table_name
  348. * The Chado table
  349. * @param $schema
  350. * The Drupal schema array for the Chado table.
  351. * @param $column_name
  352. * The name of the column in the Chado table.
  353. * @return
  354. * An associative array compatible with the tripal_chado_field_create_info()
  355. * function.
  356. */
  357. function tripal_chado_field_create_instance_info_base_defaults($bundle_name,
  358. $field_name, $table_name, $schema, $column_name) {
  359. $details = $schema['fields'][$column_name];
  360. $field = array(
  361. 'field_name' => $field_name,
  362. 'entity_type' => 'TripalEntity',
  363. 'bundle' => $bundle_name,
  364. 'label' => ucwords(preg_replace('/_/', ' ', $column_name)),
  365. 'description' => '',
  366. 'required' => FALSE,
  367. 'settings' => array(
  368. 'auto_attach' => TRUE,
  369. ),
  370. 'widget' => array(
  371. 'settings' => array(
  372. 'display_label' => 1,
  373. ),
  374. ),
  375. 'display' => array(
  376. 'default' => array(
  377. 'label' => 'above',
  378. 'settings' => array(),
  379. ),
  380. ),
  381. );
  382. // Determine if the field is required.
  383. if (array_key_exists('not null', $details) and $details['not null'] === TRUE) {
  384. $field_info['required'] = TRUE;
  385. }
  386. // Alter the field info array depending on the column details.
  387. switch($details['type']) {
  388. case 'char':
  389. $field['widget']['type'] = 'text_textfield';
  390. break;
  391. case 'varchar':
  392. $field['widget']['type'] = 'text_textfield';
  393. break;
  394. case 'text':
  395. $field['widget']['type'] = 'text_textarea';
  396. $field['widget']['settings']['format'] = filter_default_format();
  397. break;
  398. case 'blob':
  399. // not sure how to support a blob field.
  400. continue;
  401. break;
  402. case 'int':
  403. $field['widget']['type'] = 'number';
  404. break;
  405. case 'float':
  406. $field['widget']['type'] = 'number';
  407. break;
  408. case 'numeric':
  409. $field['widget']['type'] = 'number';
  410. break;
  411. case 'serial':
  412. // Serial fields are most likely not needed as a field.
  413. break;
  414. case 'boolean':
  415. $field['widget']['type'] = 'options_onoff';
  416. break;
  417. case 'datetime':
  418. $field['widget']['type'] = 'date_select';
  419. $field['widget']['settings']['increment'] = 1;
  420. $field['widget']['settings']['tz_handling'] = 'none';
  421. $field['widget']['settings']['collapsible'] = TRUE;
  422. // TODO: Add settings so that the minutes increment by 1.
  423. // And turn off the timezone, as the Chado field doesn't support it.
  424. break;
  425. }
  426. // Set some default semantic web information
  427. if ($column_name == 'uniquename') {
  428. $field['widget_type'] = 'text_textfield';
  429. }
  430. elseif ($field['label'] == 'Timeaccessioned') {
  431. $field['label'] = 'Time Accessioned';
  432. $field['description'] = 'Please enter the time that this record was first added to the database.';
  433. }
  434. elseif ($field['label'] == 'Timelastmodified') {
  435. $field['label'] = 'Time Last Modified';
  436. $field['description'] = 'Please enter the time that this record was last modified. The default is the current time.';
  437. }
  438. //
  439. // ORGANISM TABLE
  440. //
  441. elseif ($table_name == 'organism' and $column_name == 'comment') {
  442. $field['label'] = 'Description';
  443. }
  444. //
  445. // PUB TABLE
  446. //
  447. elseif ($table_name == 'pub' and $column_name == 'uniquename') {
  448. $field['widget_type'] = 'text_textfield';
  449. }
  450. //
  451. // ANALYSIS TABLE
  452. //
  453. elseif ($table_name == 'analysis' and $column_name == 'program') {
  454. $field['description'] = 'The program name (e.g. blastx, blastp, sim4, genscan. If the analysis was not derived from a software package then provide a very brief description of the pipeline, workflow or method.';
  455. $field['label'] = 'Program, Pipeline, Workflow or Method Name.';
  456. }
  457. elseif ($table_name == 'analysis' and $column_name == 'sourceuri') {
  458. $field['widget_type'] = 'text_textfield';
  459. $field['label'] = 'Source URL';
  460. $field['description'] = 'The URL where the original source data was derived. Ideally, this should link to the page where more information about the source data can be found.';
  461. }
  462. elseif ($table_name == 'analysis' and $column_name == 'sourcename') {
  463. $field['label'] = 'Source Name';
  464. $field['description'] = 'The name of the source data. This could be a file name, data set or a small description for how the data was collected. For long descriptions use the larger description field.';
  465. }
  466. elseif ($table_name == 'analysis' and $column_name == 'sourceversion') {
  467. $field['label'] = 'Source Version';
  468. $field['description'] = 'If hte source data set has a version include it here.';
  469. }
  470. elseif ($table_name == 'analysis' and $column_name == 'algorithm') {
  471. $field['label'] = 'Source Version';
  472. $field['description'] = 'The name of the algorithm used to produce the dataset if different from the program.';
  473. }
  474. elseif ($table_name == 'analysis' and $column_name == 'programversion') {
  475. $field['label'] = 'Program Version';
  476. $field['description'] = 'The version of the program used to perform this analysis. (e.g. TBLASTX 2.0MP-WashU [09-Nov-2000]. Enter "n/a" if no version is available or applicable.';
  477. }
  478. //
  479. // PROJECT TABLE
  480. //
  481. elseif ($table_name == 'project' and $column_name == 'description') {
  482. $field['label'] = 'Short Description';
  483. }
  484. return $field;
  485. }
  486. /**
  487. * A helper function for the tripal_chado_field_create_instance_info() function.
  488. *
  489. * This function adds in the custom fields info by instantiating the class
  490. * for the custom field, calling the create_instance_info() function and
  491. * returning the info array.
  492. *
  493. * @param $entity_type
  494. * The type of entity (e.g TripalEntity)
  495. * @param $bundle
  496. * The bundle object.
  497. * @param $details
  498. * An array containing the mapping of the bundle to the Chado table.
  499. */
  500. function tripal_chado_field_create_instance_info_custom($entity_type, $bundle, $details) {
  501. $info = array();
  502. // Find all of the files in the tripal_chado/includes/fields directory.
  503. $fields_path = drupal_get_path('module', 'tripal_chado') . '/includes/fields';
  504. $field_files = file_scan_directory($fields_path, '/^chado_.*\.inc$/');
  505. // Iterate through the fields, include the file and run the info function.
  506. foreach ($field_files as $file) {
  507. $field_type = $file->name;
  508. module_load_include('inc', 'tripal_chado', 'includes/fields/' . $field_type);
  509. if (preg_match('/^chado/', $field_type) and class_exists($field_type)) {
  510. $field_obj = new $field_type();
  511. $result = $field_obj->create_instance_info($entity_type, $bundle, $details);
  512. if (is_array($result)) {
  513. $info[$result['field_name']] = $result;
  514. }
  515. }
  516. }
  517. return $info;
  518. }
  519. /**
  520. * Implements hook_field_widget_info().
  521. *
  522. * This function would normally provide a large info array for all of the
  523. * widgets provided by this module. But instead it will call a hook that
  524. * can be implmented within each individual field file. This will allow
  525. * all of the code for a single field to be self contained in a single file.
  526. */
  527. function tripal_chado_field_widget_info() {
  528. $widgets = array();
  529. $fields = field_info_fields();
  530. foreach ($fields as $field) {
  531. $field_type = $field['type'];
  532. if ($field['storage']['type'] == 'field_chado_storage') {
  533. module_load_include('inc', 'tripal_chado', 'includes/fields/' . $field_type);
  534. if (preg_match('/^chado/', $field_type) and class_exists($field_type)) {
  535. $field_obj = new $field_type();
  536. $widgets[$field_type . '_widget'] = $field_obj->widget_info();
  537. }
  538. }
  539. }
  540. return $widgets;
  541. }
  542. /**
  543. * Implements hook_field_formatter_info().
  544. *
  545. * This function would normally provide a large info array for all of the
  546. * formatters provided by this module. But instead it will call a hook that
  547. * can be implmented within each individual field file. This will allow
  548. * all of the code for a single field to be self contained in a single file.
  549. */
  550. function tripal_chado_field_formatter_info() {
  551. $formatters = array();
  552. $fields = field_info_fields();
  553. foreach ($fields as $field) {
  554. $field_type = $field['type'];
  555. if ($field['storage']['type'] == 'field_chado_storage') {
  556. module_load_include('inc', 'tripal_chado', 'includes/fields/' . $field_type);
  557. if (preg_match('/^chado/', $field_type) and class_exists($field_type)) {
  558. $field_obj = new $field_type();
  559. $formatters[$field_type . '_formatter'] = $field_obj->formatter_info();
  560. }
  561. }
  562. }
  563. return $formatters;
  564. }
  565. /**
  566. * Implements hook_field_settings_form()
  567. */
  568. function tripal_chado_field_settings_form($field, $instance, $has_data) {
  569. $form = '';
  570. $field_type = $field['type'];
  571. module_load_include('inc', 'tripal_chado', 'includes/fields/' . $field_type);
  572. if (preg_match('/^chado/', $field_type) and class_exists($field_type)) {
  573. $field_obj = new $field_type();
  574. $form = $field_obj->settings_form($field, $instance, $has_data);
  575. }
  576. return $form;
  577. }
  578. /**
  579. * Implements hook_field_formatter_settings_summary().
  580. */
  581. function tripal_chado_field_formatter_settings_summary($field, $instance, $view_mode) {
  582. $summary = '';
  583. $field_type = $field['type'];
  584. module_load_include('inc', 'tripal_chado', 'includes/fields/' . $field_type);
  585. if (preg_match('/^chado/', $field_type) and class_exists($field_type)) {
  586. $field = new $field_type();
  587. $summary = $field->formatter_settings_summary($field, $instance, $view_mode);
  588. }
  589. return $summary;
  590. }
  591. /**
  592. * Implements hook_field_formatter_settings_form().
  593. */
  594. function tripal_chado_field_formatter_settings_form($field, $instance,
  595. $view_mode, $form, &$form_state) {
  596. $element = array();
  597. $field_type = $field['type'];
  598. form_load_include($form_state, 'inc', 'tripal_chado', 'includes/fields/' . $field_type);
  599. module_load_include('inc', 'tripal_chado', 'includes/fields/' . $field_type);
  600. if (preg_match('/^chado/', $field_type) and class_exists($field_type)) {
  601. $field_obj = new $field_type();
  602. $element = $field_obj->formatter_settings_form($field, $instance, $view_mode, $form, $form_state);
  603. }
  604. $function = $field_type . '_formatter_settings_form';
  605. if (function_exists($function)) {
  606. $element = $function($field, $instance, $view_mode, $form, $form_state);
  607. }
  608. return $element;
  609. }
  610. /**
  611. * Implements hook_field_formatter_view().
  612. */
  613. function tripal_chado_field_formatter_view($entity_type, $entity, $field,
  614. $instance, $langcode, $items, $display) {
  615. $element = array();
  616. $field_type = $field['type'];
  617. module_load_include('inc', 'tripal_chado', 'includes/fields/' . $field_type);
  618. if (preg_match('/^chado/', $field_type) and class_exists($field_type)) {
  619. $field_obj = new $field_type();
  620. $field_obj->formatter_view($element, $entity_type, $entity, $field, $instance, $langcode, $items, $display);
  621. }
  622. return $element;
  623. }
  624. /**
  625. * Implements hook_field_widget_form().
  626. */
  627. function tripal_chado_field_widget_form(&$form, &$form_state, $field,
  628. $instance, $langcode, $items, $delta, $element) {
  629. $widget = $element;
  630. $field_name = $instance['field_name'];
  631. $field_type = $field['type'];
  632. form_load_include($form_state, 'inc', 'tripal_chado', 'includes/fields/' . $field_type);
  633. module_load_include('inc', 'tripal_chado', 'includes/fields/' . $field_name);
  634. if (preg_match('/^chado/', $field_type) and class_exists($field_type)) {
  635. $field_obj = new $field_type();
  636. $field_obj->widget_form($widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
  637. }
  638. return $widget;
  639. }
  640. /**
  641. * Implements hook_field_widget_form_alter().
  642. */
  643. function tripal_chado_field_widget_form_alter(&$element, &$form_state, $context) {
  644. if (array_key_exists('#field_name', $element)) {
  645. $field_name = $element['#field_name'];
  646. $matches = array();
  647. if (preg_match('/(.+?)__(.+?)$/', $field_name, $matches)) {
  648. $tablename = $matches[1];
  649. $colname = $matches[2];
  650. $schema = chado_get_schema($tablename);
  651. if (!$schema) {
  652. return;
  653. }
  654. // The timelastmodified field exists in many Chado tables. We want
  655. // the form element to update to the most recent time rather than the time
  656. // in the database.
  657. if ($colname == 'timelastmodified' and $schema['fields'][$colname]['type'] == 'datetime') {
  658. // We want the default value for the field to be the current time.
  659. $element['#default_value']['value'] = format_date(time(), 'custom', "Y-m-d H:i:s", 'UTC');
  660. $element['#date_items']['value'] = $element['#default_value']['value'];
  661. }
  662. // We want the date combo fieldset to be collaspible so we will
  663. // add our own theme_wrapper to replace the one added by the date
  664. // module.
  665. if (array_key_exists($colname, $schema['fields']) and $schema['fields'][$colname]['type'] == 'datetime') {
  666. $element['#theme_wrappers'] = array('tripal_chado_date_combo');
  667. }
  668. }
  669. }
  670. }
  671. /**
  672. * Implements hook_field_validate()
  673. */
  674. function tripal_chado_field_validate($entity_type, $entity, $field, $instance,
  675. $langcode, $items, &$errors) {
  676. $field_type = $field['type'];
  677. if ($field['storage']['type'] == 'field_chado_storage') {
  678. module_load_include('inc', 'tripal_chado', 'includes/fields/' . $field_type);
  679. if (preg_match('/^chado/', $field_type) and class_exists($field_type)) {
  680. $field_obj = new $field_type();
  681. $field_obj->validate($entity_type, $entity, $field, $instance,
  682. $langcode, $items, $errors);
  683. }
  684. }
  685. }
  686. /**
  687. * Implements hook_field_validate()
  688. */
  689. function tripal_chado_field_submit($entity_type, $entity, $field, $instance,
  690. $langcode, &$items, $form, &$form_state) {
  691. $field_type = $field['type'];
  692. if ($field['storage']['type'] == 'field_chado_storage') {
  693. module_load_include('inc', 'tripal_chado', 'includes/fields/' . $field_type);
  694. if (preg_match('/^chado/', $field_type) and class_exists($field_type)) {
  695. $field_obj = new $field_type();
  696. $field_obj->submit($entity_type, $entity, $field, $instance,
  697. $langcode, $items, $form, $form_state);
  698. }
  699. }
  700. }
  701. /**
  702. * Implements hook_form_FORM_ID_alter().
  703. *
  704. * The field_ui_display_overview_form is used for formatting the display
  705. * or layout of fields attached to an entity and shown on the entity view page.
  706. *
  707. * This function removes the cvterm class and property adder field as those are
  708. * really not meant for users to show or manage.
  709. */
  710. function tripal_chado_form_field_ui_display_overview_form_alter(&$form, &$form_state, $form_id) {
  711. // Remove the kvproperty_addr field as it isn't ever displayed. It's just used
  712. // on the add/edit form of an entity for adding new property fields.
  713. $fields_names = element_children($form['fields']);
  714. foreach ($fields_names as $field_name) {
  715. $field_info = field_info_field($field_name);
  716. if ($field_info['type'] == 'kvproperty_adder') {
  717. unset($form['fields'][$field_name]);
  718. }
  719. if ($field_info['type'] == 'cvterm_class_adder') {
  720. unset($form['fields'][$field_name]);
  721. }
  722. }
  723. }
  724. /**
  725. * Implements hook_form_FORM_ID_alter().
  726. *
  727. * The field_ui_field_overview_form is used for ordering and configuring the
  728. * fields attached to an entity.
  729. *
  730. * This function removes the property adder field as that is really not meant
  731. * for users to show or manage.
  732. */
  733. function tripal_chado_form_field_ui_field_overview_form_alter(&$form, &$form_state, $form_id) {
  734. // Remove the kvproperty_addr field as it isn't ever displayed. It's just used
  735. // on the add/edit form of an entity for adding new property fields.
  736. $fields_names = element_children($form['fields']);
  737. foreach ($fields_names as $field_name) {
  738. $field_info = field_info_field($field_name);
  739. if ($field_info['type'] == 'kvproperty_adder') {
  740. unset($form['fields'][$field_name]);
  741. }
  742. if ($field_info['type'] == 'cvterm_class_adder') {
  743. unset($form['fields'][$field_name]);
  744. }
  745. }
  746. }
  747. /**
  748. * Implements hook_field_is_empty().
  749. */
  750. function tripal_chado_field_is_empty($item, $field) {
  751. // If there is no value field then the field is empty.
  752. if (!array_key_exists('value', $item)) {
  753. return TRUE;
  754. }
  755. // Iterate through all of the fields and if at least one has a value
  756. // the field is not empty.
  757. foreach ($item as $form_field_name => $value) {
  758. if (isset($value) and $value != NULL and $value != '') {
  759. return FALSE;
  760. }
  761. }
  762. // Otherwise, the field is empty.
  763. return TRUE;
  764. }