tripal.fields.inc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. <?php
  2. /**
  3. * Implements hook_field_info().
  4. *
  5. * We want the Tripal module to handle all TripalFields. This will allow
  6. * other modules to be more easily disabled/enabled because Drupal won't
  7. * let a module be disabled if it supports fields that are actively attached
  8. * to bundles. Therefore any module that provides a new TripalField will be
  9. * discovered and listed for Drupal by this function.
  10. */
  11. function tripal_field_info() {
  12. // $info = array();
  13. // $field_types = tripal_get_field_types();
  14. // foreach ($field_types as $field_type) {
  15. // $info[$field_type] = $field_type::globalInfo();
  16. // }
  17. // return $info;
  18. return array(
  19. 'tripal_key_value' => array(
  20. 'label' => 'Tripal complex field',
  21. 'description' => 'A field specific to data managed by Tripal. ',
  22. 'settings' => array(
  23. 'tripal_term' => '',
  24. ),
  25. 'instance_settings' => array(),
  26. 'default_widget' => 'tripal_generic_key_value_widget',
  27. 'default_formatter' => 'tripal_generic_key_value_formatter',
  28. 'storage' => array(
  29. 'type' => 'tripal_no_storage',
  30. 'module' => 'tripal',
  31. 'active' => TRUE
  32. ),
  33. ),
  34. );
  35. }
  36. /**
  37. * Implements hook_info_alter().
  38. */
  39. function tripal_field_info_alter(&$info) {
  40. // Make sure all fields have a 'tripal_term' setting so we can map
  41. // all fields to a vocabulary term for the semantic web.
  42. foreach ($info as $field_name => $details) {
  43. if(array_key_exists('settings', $details)) {
  44. if (!array_key_exists('tripal_term', $details['settings'])) {
  45. $info[$field_name]['settings']['tripal_term'] = '';
  46. }
  47. }
  48. else {
  49. $info[$field_name]['settings']['tripal_term'] = '';
  50. }
  51. }
  52. }
  53. /**
  54. * Implements hook_field_widget_info();
  55. */
  56. function tripal_field_widget_info() {
  57. // $info = array();
  58. // $field_types = tripal_get_field_types();
  59. // foreach ($field_types as $field_type) {
  60. // $info += $field_type::widgetInfo();
  61. // }
  62. // return $info;
  63. return array(
  64. 'tripal_generic_key_value_widget' => array(
  65. 'label' => 'Generic key/value',
  66. 'field types' => array('tripal_key_value')
  67. ),
  68. );
  69. }
  70. /**
  71. * Implements hook_field_formatter_info().
  72. */
  73. function tripal_field_formatter_info() {
  74. // $info = array();
  75. // $field_types = tripal_get_field_types();
  76. // foreach ($field_types as $field_type) {
  77. // $info += $field_type::formatterInfo();
  78. // }
  79. // return $info;
  80. return array(
  81. 'tripal_generic_key_value_formatter' => array(
  82. 'label' => 'Values',
  83. 'field types' => array('tripal_key_value'),
  84. 'settings' => array(),
  85. ),
  86. );
  87. }
  88. /**
  89. *
  90. */
  91. function tripal_create_tripalfields($entity_type, $bundle) {
  92. $field_name = 'content_type';
  93. $info = array();
  94. $info[$field_name] = array(
  95. 'field_name' => $field_name,
  96. 'type' => 'content_type',
  97. 'cardinality' => 1,
  98. 'locked' => FALSE,
  99. 'storage' => array(
  100. 'type' => 'tripal_no_storage'
  101. ),
  102. 'settings' => array(
  103. 'semantic_web' => 'rdfs:type',
  104. ),
  105. );
  106. return $info;
  107. }
  108. /**
  109. *
  110. * @param unknown $entity_type
  111. * @param unknown $bundle
  112. */
  113. function tripal_create_tripalfield_instance($entity_type, $bundle) {
  114. $field_name = 'content_type';
  115. $info = array();
  116. $info[$field_name] = array(
  117. 'field_name' => $field_name,
  118. 'entity_type' => 'TripalEntity',
  119. 'bundle' => $bundle->name,
  120. 'label' => 'Resource Type',
  121. 'description' => '',
  122. 'required' => FALSE,
  123. 'settings' => array(
  124. 'auto_attach' => TRUE,
  125. ),
  126. 'widget' => array(
  127. 'type' => 'tripal_content_type_widget',
  128. 'settings' => array(
  129. 'display_label' => 1,
  130. ),
  131. ),
  132. 'display' => array(
  133. 'default' => array(
  134. 'label' => 'inline',
  135. 'type' => 'tripal_content_type_formatter',
  136. 'settings' => array(),
  137. ),
  138. ),
  139. );
  140. return $info;
  141. }
  142. /**
  143. * Implements hook_field_formatter_view().
  144. */
  145. function tripal_field_formatter_view($entity_type, $entity, $field,
  146. $instance, $langcode, $items, $display) {
  147. // $element = array();
  148. // $field_type = $field['type'];
  149. // $is_loaded = tripal_load_include_field_type($field_type);
  150. // if ($is_loaded) {
  151. // $tfield = new $field_type($field, $instance);
  152. // $tfield->formatterView($element, $entity_type, $entity, $langcode, $items, $display);
  153. // }
  154. // return $element;
  155. }
  156. /**
  157. * Simple provides a message indicating that the field cannot be deleted.
  158. *
  159. * This function is used in the tripal_menu_alter() function. We alter the
  160. * menu created for managing fields to use this call back which
  161. * prints a message that the field cannot be deleted.
  162. */
  163. function tripal_field_no_delete() {
  164. drupal_set_message('This field cannot be removed.', 'warning');
  165. return '';
  166. }
  167. /**
  168. *
  169. * Implements hook_form_FORM_ID_alter().
  170. *
  171. * The field_ui_field_overview_form_ is used for adding and reordering the
  172. * fields attached to a bundle. It also includes edit and delete links and
  173. * links for editing field types and widgets.
  174. *
  175. * This alter function is used to add a new 'Supported By' column to
  176. * the table to let the user know where fields are storing their data.
  177. */
  178. function tripal_form_field_ui_field_overview_form_alter(&$form, &$form_state, $form_id) {
  179. //dpm($form);
  180. // Add the 'Storage Location' to the table header.
  181. $form['fields']['#header'][] = 'Term';
  182. $form['fields']['#header'][] = 'Supported By * ';
  183. // TODO: remove widgets that aren't appropriate for this entity, if the
  184. // type is 'tripal_key_value'.
  185. // Why is this sort not working!!??
  186. $options = $form['fields']['_add_new_field']['widget_type']['#options']['Tripal complex field'];
  187. asort($options);
  188. $form['fields']['_add_new_field']['widget_type']['#options']['Tripal complex field'] = $options;
  189. // Add the storage location as the final column for each field.
  190. $storage_info = module_invoke_all('field_storage_info');
  191. foreach (element_children($form['fields']) as $field_name) {
  192. $field = field_info_field($field_name);
  193. // For rows in the tables that aren't fields, just add an empty value
  194. // for the storage column.
  195. if (!$field) {
  196. $form['fields'][$field_name][] = array(
  197. '#markup' => '',
  198. );
  199. $form['fields'][$field_name][] = array(
  200. '#markup' => '',
  201. );
  202. continue;
  203. }
  204. $term = $field['settings']['tripal_term'] ? $field['settings']['tripal_term'] : 'N/A';
  205. $form['fields'][$field_name][] = array(
  206. '#markup' => $term,
  207. );
  208. $storage_type = $field['storage']['type'];
  209. $storage_label = array_key_exists('label', $storage_info[$storage_type]) ? $storage_info[$storage_type]['label'] : '';
  210. if ($storage_type == 'field_sql_storage') {
  211. $storage_label = 'Drupal';
  212. }
  213. if (array_key_exists('logo_url', $storage_info[$storage_type])) {
  214. $logo_url = $storage_info[$storage_type]['logo_url'];
  215. $form['fields'][$field_name][] = array(
  216. '#markup' => '<img class="form-field-ui-field-overview-storage-logo" src="' . $logo_url . '">',
  217. );
  218. }
  219. else {
  220. $form['fields'][$field_name][] = array(
  221. '#markup' => $storage_label,
  222. );
  223. }
  224. }
  225. $form['note'] = array(
  226. '#markup' => '* Fields attached to this content type can use various
  227. storage backends. Please be sure when you add new fields that the
  228. storage backend is appropriate. For example, if you use Chado, and you
  229. want all biological content to be stored in Chado, be sure that the
  230. respective fields are "supported by" Chado.',
  231. );
  232. }
  233. /**
  234. * Implements hook_module_implements_alter()
  235. *
  236. * We want our edits to the field_ui_field_overview_form form to occur after
  237. * all modules have implemented their changes.
  238. */
  239. function tripal_module_implements_alter(&$implementations, $hook) {
  240. if ($hook == 'form_alter') {
  241. $group = $implementations['tripal'];
  242. unset($implementations['tripal']);
  243. $implementations['tripal'] = $group;
  244. }
  245. }
  246. /**
  247. * Implements hook_field_settings_form()
  248. */
  249. function tripal_field_settings_form($field, $instance, $has_data) {
  250. // $form = array();
  251. // $field_type = $field['type'];
  252. // //$is_loaded = tripal_load_include_field_type($field_type);
  253. // tripal_load_include_field_type($field_type);
  254. // if (class_exists($field_type)) {
  255. // $tfield = new $field_type($field, $instance);
  256. // $form = $tfield->globalSettingsForm($field, $instance, $has_data);
  257. // }
  258. // return $form;
  259. }
  260. /**
  261. * Allows for altering of a field's instance setting form.
  262. *
  263. * This appears to be a Drupal hook but is actually a custom function created
  264. * by this module. It is called by the tripal_form_alter() function of this
  265. * module.
  266. *
  267. * @param $form
  268. * The form array. Alterations to the form can be made within this array.
  269. * @param $form_state
  270. * The form state array.
  271. */
  272. function tripal_field_instance_settings_form_alter(&$form, $form_state) {
  273. $field = $form['#field'];
  274. $instance = $form['#instance'];
  275. $form['tripal_additions'] = array(
  276. '#type' => 'fieldset',
  277. '#title' => 'Tripal Settings',
  278. );
  279. $form['tripal_additions']['semantic_web'] = array(
  280. '#type' => 'textfield',
  281. '#title' => 'Vocabulary Term'
  282. );
  283. $form['tripal_additions']['storage'] = array(
  284. '#type' => 'textfield',
  285. '#title' => 'Storage Backend'
  286. );
  287. }
  288. /**
  289. * Implements hook_instance_settings_form()
  290. */
  291. function tripal_field_instance_settings_form($field, $instance) {
  292. // $form = array();
  293. // $field_type = $field['type'];
  294. // tripal_load_include_field_type($field_type);
  295. // if (class_exists($field_type)) {
  296. // $tfield = new $field_type($field, $instance);
  297. // $form = $tfield->instanceSettingsForm();
  298. // }
  299. // return $form;
  300. }
  301. /**
  302. *
  303. */
  304. function tripal_field_instance_settings_form_validate($form, &$form_state) {
  305. // $field = $form['#field'];
  306. // $instance = $form['#instance'];
  307. // $field_type = $field['type'];
  308. // tripal_load_include_field_type($field_type);
  309. // if (class_exists($field_type)) {
  310. // $tfield = new $field_type($field, $instance);
  311. // $form = $tfield->instanceSettingsFormValidate($form, $form_state);
  312. // }
  313. }
  314. /**
  315. *
  316. */
  317. function tripal_field_widget_form_validate($form, &$form_state) {
  318. // $entity = $form['#entity'];
  319. // $entity_type = $form['#entity_type'];
  320. // $langcode = $form['#language'];
  321. // $delta = $form['#delta'];
  322. // $field = $form['#field'];
  323. // $field_type = $field['type'];
  324. // tripal_load_include_field_type($field_type);
  325. // if (class_exists($field_type)) {
  326. // $instance = $form['#instance'];
  327. // $tfield = new $field_type($field, $instance);
  328. // $form = $tfield->widgetFormValidate($form, $form_state, $entity_type, $entity, $langcode, $delta);
  329. // }
  330. }
  331. /**
  332. * Implements hook_field_settings_form_validate().
  333. *
  334. * This is not an actual Drpual hook, but rather a Tripal created hook
  335. * to alow the TripalField objects to have a globalSettingsFormValidate()
  336. * member function.
  337. */
  338. function tripal_field_settings_form_validate($form, &$form_state) {
  339. // $field = $form['#field'];
  340. // $instance = $form['#instance'];
  341. // $field_type = $field['type'];
  342. // tripal_load_include_field_type($field_type);
  343. // if (class_exists($field_type)) {
  344. // $tfield = new $field_type($field, $instance);
  345. // $form = $tfield->globalSettingsFormValidate($field, $instance, $form, $form_state);
  346. // }
  347. }
  348. /**
  349. * Implements hook_field_formatter_settings_summary().
  350. */
  351. function tripal_field_formatter_settings_summary($field, $instance, $view_mode) {
  352. // $summary = '';
  353. // $field_type = $field['type'];
  354. // tripal_load_include_field_type($field_type);
  355. // if (class_exists($field_type)) {
  356. // $tfield = new $field_type($field, $instance);
  357. // $form = $tfield->formatterSettingsSummary($view_mode);
  358. // }
  359. // return $summary;
  360. }
  361. /**
  362. * Implements hook_field_formatter_settings_form().
  363. */
  364. function tripal_formatter_settings_form($field, $instance,
  365. $view_mode, $form, &$form_state) {
  366. // $form = array();
  367. // $field_type = $field['type'];
  368. // tripal_load_include_field_type($field_type);
  369. // if (class_exists($field_type)) {
  370. // $tfield = new $field_type($field, $instance);
  371. // $form = $tfield->formatterSettingsForm($view_mode, $form, $form_state);
  372. // }
  373. // return $form;
  374. }
  375. /**
  376. * Implements hook_field_widget_form().
  377. */
  378. function tripal_field_widget_form(&$form, &$form_state, $field,
  379. $instance, $langcode, $items, $delta, $element) {
  380. // $widget = $element;
  381. // $field_type = $field['type'];
  382. // tripal_load_include_field_type($field_type);
  383. // if (class_exists($field_type)) {
  384. // $tfield = new $field_type($field, $instance);
  385. // $tfield->widgetForm($widget, $form, $form_state, $langcode, $items, $delta, $element);
  386. // }
  387. // return $widget;
  388. }
  389. /**
  390. * Implements hook_field_widget_form_alter().
  391. */
  392. function tripal_field_widget_form_alter(&$element, &$form_state, $context) {
  393. if (array_key_exists('#field_name', $element)) {
  394. $field_name = $element['#field_name'];
  395. $matches = array();
  396. if (preg_match('/(.+?)__(.+?)$/', $field_name, $matches)) {
  397. $tablename = $matches[1];
  398. $colname = $matches[2];
  399. $schema = chado_get_schema($tablename);
  400. if (!$schema) {
  401. return;
  402. }
  403. // The timelastmodified field exists in many Chado tables. We want
  404. // the form element to update to the most recent time rather than the time
  405. // in the database.
  406. if ($colname == 'timelastmodified' and $schema['fields'][$colname]['type'] == 'datetime') {
  407. // We want the default value for the field to be the current time.
  408. $element['#default_value']['value'] = format_date(time(), 'custom', "Y-m-d H:i:s", 'UTC');
  409. $element['#date_items']['value'] = $element['#default_value']['value'];
  410. }
  411. // We want the date combo fieldset to be collaspible so we will
  412. // add our own theme_wrapper to replace the one added by the date
  413. // module.
  414. if (array_key_exists($colname, $schema['fields']) and $schema['fields'][$colname]['type'] == 'datetime') {
  415. $element['#theme_wrappers'] = array('tripal_chado_date_combo');
  416. }
  417. }
  418. }
  419. }
  420. /**
  421. * Implements hook_field_validate()
  422. */
  423. function tripal_field_validate($entity_type, $entity, $field, $instance,
  424. $langcode, $items, &$errors) {
  425. // $field_type = $field['type'];
  426. // $is_loaded = tripal_load_include_field_type($field_type);
  427. // if ($is_loaded) {
  428. // $tfield = new $field_type($field, $instance);
  429. // $tfield->validate($entity_type, $entity, $langcode,
  430. // $items, $errors);
  431. // }
  432. }
  433. /**
  434. * Implements hook_form_FORM_ID_alter().
  435. *
  436. * The field_ui_display_overview_form is used for formatting the display
  437. * or layout of fields attached to an entity and shown on the entity view page.
  438. *
  439. * This function removes the cvterm class and property adder field as those are
  440. * really not meant for users to show or manage.
  441. */
  442. function tripal_form_field_ui_display_overview_form_alter(&$form, &$form_state, $form_id) {
  443. // Remove the kvproperty_addr field as it isn't ever displayed. It's just used
  444. // on the add/edit form of an entity for adding new property fields.
  445. $fields_names = element_children($form['fields']);
  446. foreach ($fields_names as $field_name) {
  447. $field_info = field_info_field($field_name);
  448. if ($field_info['type'] == 'kvproperty_adder') {
  449. unset($form['fields'][$field_name]);
  450. }
  451. if ($field_info['type'] == 'cvterm_class_adder') {
  452. unset($form['fields'][$field_name]);
  453. }
  454. }
  455. }
  456. /**
  457. * Implements hook_field_is_empty().
  458. */
  459. function tripal_field_is_empty($item, $field) {
  460. // If there is no value field then the field is empty.
  461. if (!array_key_exists('value', $item)) {
  462. return TRUE;
  463. }
  464. // Iterate through all of the fields and if at least one has a value
  465. // the field is not empty.
  466. foreach ($item as $form_field_name => $value) {
  467. if (isset($value) and $value != NULL and $value != '') {
  468. return FALSE;
  469. }
  470. }
  471. // Otherwise, the field is empty.
  472. return TRUE;
  473. }