tripal_entities.module 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. <?php
  2. // http://www.bluespark.com/blog/drupal-entities-part-3-programming-hello-drupal-entity
  3. // http://dikini.net/31.08.2010/entities_bundles_fields_and_field_instances
  4. /**
  5. * Implement hook_entity_info().
  6. */
  7. function tripal_entities_entity_info() {
  8. $entities = array();
  9. $entities['chado_data'] = array(
  10. 'label' => t('Vocabulary Term'),
  11. 'uri callback' => 'tripal_entities_vocbulary_term_uri',
  12. 'plural label' => t('Vocabulary Terms'),
  13. 'entity class' => 'TrpVocabularyTerm',
  14. 'controller class' => 'TrpVocabularyTermController',
  15. 'fieldable' => TRUE,
  16. 'entity keys' => array(
  17. 'id' => 'entity_id',
  18. 'bundle' => 'bundle',
  19. ),
  20. // Bundles are defined by the model types below
  21. 'bundles' => array(),
  22. );
  23. // We want to dynamically add the bundles (or term types) to the entity.
  24. $values = array(
  25. 'cv_id' => array(
  26. 'name' => 'sequence'
  27. ),
  28. 'name' => 'gene'
  29. );
  30. $cvterm = chado_generate_var('cvterm', $values);
  31. $bundle_id = 'trp_' . $cvterm->dbxref_id->db_id->name . '_' . $cvterm->dbxref_id->accession;
  32. $label = preg_replace('/_/', ' ', ucwords($cvterm->name));
  33. $entities['trp_vocabulary_term']['bundles'][$bundle_id] = array(
  34. 'label' => $label,
  35. );
  36. return $entities;
  37. }
  38. function tripal_entities_load($entity_id = NULL, $reset = FALSE){
  39. $ids = (isset ($entity_id) ? array($entity_id) : array());
  40. $chado_data = tripal_entities_load_multiple($entity_ids, $reset);
  41. return $chado_data ? reset ($chado_data) : FALSE;
  42. }
  43. function tripal_entities_load_multiple($entity_ids = array(), $conditions = array(), $reset = FALSE){
  44. return entity_load('chado_data', $entity_ids, $conditions, $reset);
  45. }
  46. function tripal_entities_menu() {
  47. $items['admin/structure/chado_data/manage'] = array(
  48. 'title' => 'Term Admin',
  49. 'description' => 'Manage chado_data structure',
  50. 'page callback' => 'chado_data_info',
  51. 'access arguments' => array('administer chado_datas'),
  52. );
  53. $items['chado_data/%'] = array(
  54. 'title callback' => 'chado_data_page_title',
  55. 'title arguments' => array(1),
  56. 'page callback' => 'chado_data_page_view',
  57. 'page arguments' => array(1),
  58. 'access arguments' => array('view chado_data'),
  59. 'type' => MENU_CALLBACK,
  60. );
  61. $items['data/add'] = array(
  62. 'title' => 'Add new data',
  63. 'page callback' => 'drupal_get_form',
  64. 'page arguments' => array('tripal_entities_add_form'),
  65. 'access arguments' => array('create chado_data'),
  66. );
  67. return $items;
  68. }
  69. function tripal_entities_permission(){
  70. return array(
  71. 'administer chado_datas' => array(
  72. 'title' => t('Administer chado_datas'),
  73. 'restrict access' => TRUE,
  74. ),
  75. 'view postsits' => array(
  76. 'title' => t('View chado_datas'),
  77. )
  78. );
  79. }
  80. function chado_data_info() {
  81. return ('Welcome to the administration page for your CV Terms!');
  82. }
  83. function chado_data_page_title($chado_data){
  84. return $chado_data->entity_id;
  85. }
  86. function chado_data_page_view($chado_data, $view_mode = 'full'){
  87. $chado_data->content = array();
  88. // Build fields content.
  89. field_attach_prepare_view('chado_data', array($chado_data->entity_id => $chado_data), $view_mode);
  90. entity_prepare_view('chado_data', array($chado_data->entity_id => $chado_data));
  91. $chado_data->content += field_attach_view('chado_data', $chado_data, $view_mode);
  92. return $chado_data->content;
  93. }
  94. /**
  95. *
  96. */
  97. function tripal_entities_vocbulary_term_uri($entity) {
  98. return array(
  99. 'path' => 'chado_data/' . $entity->entity_id,
  100. );
  101. }
  102. /**
  103. *
  104. */
  105. function tripal_entities_add_form($form, &$form_state) {
  106. // Set the defaults.
  107. $cv_id = NULL;
  108. $term_name = NULL;
  109. if (array_key_exists('values', $form_state)) {
  110. $cv_id = array_key_exists('cv_id', $form_state['values']) ? $form_state['values']['cv_id'] : NULL;
  111. $term_name = array_key_exists('term_name', $form_state['values']) ? $form_state['values']['term_name'] : NULL;
  112. }
  113. // Let the user select the vocabulary and chado_data but only if they haven't
  114. // already selected a chado_data.
  115. $cvs = tripal_get_cv_select_options();
  116. if (!$term_name) {
  117. $form['cv_id'] = array(
  118. '#type' => 'select',
  119. '#title' => t('Vocabulary'),
  120. '#options' => $cvs,
  121. '#required' => TRUE,
  122. '#description' => t('Select a vocabulary that contains the term for the type of data you want to add.'),
  123. '#default_value' => $cv_id,
  124. '#ajax' => array(
  125. 'callback' => "tripal_entities_add_form_ajax_callback",
  126. 'wrapper' => 'tripal_entities_add_form',
  127. 'effect' => 'fade',
  128. 'method' => 'replace'
  129. )
  130. );
  131. }
  132. // If we have a CV ID then we want to provide an autocomplete field
  133. if ($cv_id and !$term_name) {
  134. $form['cvterm_select']['term_name'] = array(
  135. '#title' => t('Record Type'),
  136. '#type' => 'textfield',
  137. '#description' => t("Enter the name of a term within the selected vocabulary for the record type you want to enter."),
  138. '#required' => TRUE,
  139. '#default_value' => $term_name,
  140. '#autocomplete_path' => "admin/tripal/chado/tripal_cv/cvterm/auto_name/$cv_id",
  141. );
  142. $form['cvterm_select']['select_button'] = array(
  143. '#type' => 'submit',
  144. '#value' => t('Use this term'),
  145. '#name' => 'select_cvterm',
  146. );
  147. }
  148. // Once the CV term is selected then provide the other fields.
  149. if ($term_name) {
  150. // Get the cvterm that matches
  151. $values = array(
  152. 'cv_id' => $cv_id,
  153. 'name' => $term_name
  154. );
  155. $cvterm = tripal_get_cvterm($values);
  156. $form['cv_id'] = array(
  157. '#type' => 'hidden',
  158. '#value' => $cv_id,
  159. );
  160. $form['cvterm_id'] = array(
  161. '#type' => 'hidden',
  162. '#value' => $cvterm->cvterm_id,
  163. );
  164. $form['bundle'] = array(
  165. '#type' => 'hidden',
  166. '#value' => $term_name,
  167. );
  168. $form['cv_name'] = array(
  169. '#type' => 'item',
  170. '#title' => 'Vocabulary',
  171. '#markup' => $cvterm->cv_id->name,
  172. '#weight' => -100,
  173. );
  174. $form['term_name_shown'] = array(
  175. '#type' => 'item',
  176. '#title' => 'Record Type',
  177. '#markup' => $cvterm->name,
  178. '#weight' => -100,
  179. );
  180. /* // Drupal field types and settings:
  181. // https://www.drupal.org/node/1879542
  182. $field = array(
  183. 'field_name' => 'feature__name',
  184. 'type' => 'text',
  185. 'cardinality' => 1,
  186. 'storage' => array(
  187. 'type' => 'tripal_entities_storage'
  188. ),
  189. );
  190. field_create_field($field);
  191. $field_instance = array(
  192. 'field_name' => 'feature__name',
  193. 'label' => 'Name',
  194. 'widget' => array(
  195. 'type' => 'text_textfield'
  196. ),
  197. 'entity_type' => 'chado_data',
  198. 'required' => 'true',
  199. 'settings' => array(
  200. 'max_length' => 255
  201. ),
  202. 'bundle' => $cvterm->name,
  203. );
  204. field_create_instance($field_instance);
  205. $field = array(
  206. 'field_name' => 'feature__uniquename',
  207. 'type' => 'text',
  208. 'cardinality' => 1,
  209. 'storage' => array(
  210. 'type' => 'tripal_entities_storage'
  211. ),
  212. );
  213. field_create_field($field);
  214. $field_instance = array(
  215. 'field_name' => 'feature__uniquename',
  216. 'label' => 'Unique Name',
  217. 'widget' => array(
  218. 'type' => 'text_textfield'
  219. ),
  220. 'entity_type' => 'chado_data',
  221. 'required' => 'true',
  222. 'settings' => array(
  223. 'max_length' => 255
  224. ),
  225. 'bundle' => $cvterm->name,
  226. );
  227. field_create_instance($field_instance);
  228. $field = array(
  229. 'field_name' => 'feature__organism_id',
  230. 'type' => 'organism_id',
  231. 'cardinality' => 1,
  232. 'storage' => array(
  233. 'type' => 'tripal_entities_storage'
  234. ),
  235. );
  236. field_create_field($field);
  237. $field_instance = array(
  238. 'field_name' => 'feature__organism_id',
  239. 'label' => 'Organism',
  240. 'entity_type' => 'chado_data',
  241. 'required' => 'true',
  242. 'settings' => array(),
  243. 'bundle' => $cvterm->name,
  244. );
  245. field_create_instance($field_instance);*/
  246. // Create the object for this entity instance. The entity instance type
  247. // is always the name of the term.
  248. $entity = new stdClass();
  249. $entity->entity_id = NULL;
  250. $entity->bundle = $cvterm->name;
  251. $form['#parents'] = array('attached');
  252. field_attach_form('chado_data', $entity, $form, $form_state);
  253. $form['submit'] = array(
  254. '#type' => 'submit',
  255. '#value' => t('Add a new ' . $cvterm->name),
  256. '#name' => 'add_data',
  257. '#weight' => 1000
  258. );
  259. }
  260. $form['#prefix'] = '<div id="tripal_entities_add_form">';
  261. $form['#suffix'] = '</div>';
  262. return $form;
  263. }
  264. /**
  265. * Implements hook_field_info().
  266. */
  267. function tripal_entities_field_info() {
  268. $fields = array(
  269. 'organism_id' => array(
  270. 'label' => t('Organism'),
  271. 'description' => t('A field for specifying an organism.'),
  272. 'default_widget' => 'tripal_entities_organism_select_widget',
  273. 'default_formatter' => 'tripal_entities_organism_formatter',
  274. 'settings' => array(),
  275. 'storage' => array(
  276. 'type' => 'tripal_entities_storage',
  277. 'module' => 'tripal_entities',
  278. 'active' => TRUE
  279. ),
  280. ),
  281. );
  282. return $fields;
  283. }
  284. /**
  285. * Implements hook_field_widget_info().
  286. */
  287. function tripal_entities_field_widget_info() {
  288. return array(
  289. 'tripal_entities_organism_select_widget' => array(
  290. 'label' => t('Organism Select'),
  291. 'field types' => array('organism_id')
  292. ),
  293. );
  294. }
  295. /**
  296. * Implements hook_field_formatter_info().
  297. */
  298. function tripal_entities_field_formatter_info() {
  299. return array(
  300. 'tripal_entities_organism_formatter' => array(
  301. 'label' => t('Organism'),
  302. 'field types' => array('organism_id')
  303. ),
  304. );
  305. }
  306. /**
  307. * Implements hook_field_widget_form().
  308. */
  309. function tripal_entities_field_widget_form(&$form, &$form_state, $field,
  310. $instance, $langcode, $items, $delta, $element) {
  311. $widget = $element;
  312. $widget['#delta'] = $delta;
  313. switch ($instance['widget']['type']) {
  314. case 'tripal_entities_organism_select_widget':
  315. $options = tripal_get_organism_select_options();
  316. $widget += array(
  317. '#type' => 'select',
  318. '#title' => $element['#title'],
  319. '#description' => $element['#description'],
  320. '#options' => $options,
  321. '#default_value' => '',
  322. '#required' => $element['#required'],
  323. '#weight' => isset($element['#weight']) ? $element['#weight'] : 0,
  324. '#delta' => $delta,
  325. '#element_validate' => array('tripal_entities_organism_select_widget_validate'),
  326. );
  327. $element['value'] = $widget;
  328. break;
  329. }
  330. return $element;
  331. }
  332. /**
  333. * Callback function for validating the tripal_entities_organism_select_widget.
  334. */
  335. function tripal_entities_organism_select_widget_validate($element, &$form_state) {
  336. $field_name = $element['#field_name'];
  337. // Make sure we have a valid organism
  338. foreach ($form_state['values'][$field_name] as $langcode => $items) {
  339. foreach ($items as $delta => $value) {
  340. $organism_id = chado_select_record('organism', array('organism_id'),
  341. array('organism_id' => $value['value']), array('has_record' => TRUE));
  342. if (!$organism_id) {
  343. form_error($element, t("Please specify an organism that already exists in the database."));
  344. }
  345. }
  346. }
  347. }
  348. /**
  349. * Implements hook_field_is_empty().
  350. */
  351. function tripal_entities_field_is_empty($item, $field) {
  352. if (empty($item['tripal_entities_organism_select_widget'])) {
  353. return TRUE;
  354. }
  355. }
  356. /**
  357. * Implements hook_field_storage_info().
  358. */
  359. function tripal_entities_field_storage_info() {
  360. return array(
  361. 'tripal_entities_storage' => array(
  362. 'label' => t('Chado storage'),
  363. 'description' => t('Stores fields in the local Chado database.'),
  364. 'settings' => array(),
  365. ),
  366. );
  367. }
  368. /**
  369. * Implements hook_field_storage_write().
  370. */
  371. function tripal_entities_field_storage_write($entity_type, $entity, $op, $fields) {
  372. // Get the IDs for this entity.
  373. list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
  374. // Find out which table should receive the insert.
  375. $tablename = 'feature';
  376. $type_field = 'type_id';
  377. $schema = chado_get_schema($tablename);
  378. $pkey_field = $schema['primary key'][0];
  379. // Construct the values array that will be used to insert into the table.
  380. $values = array();
  381. foreach ($fields as $field_id) {
  382. $field = field_info_field_by_id($field_id);
  383. $field_name = $field['field_name'];
  384. $matches = array();
  385. if (preg_match('/^' . $tablename . '__(.*)/', $field_name, $matches)) {
  386. $chado_field = $matches[1];
  387. // Currently, we only support one language, but for for the sake of
  388. // thoroughness we'll iterate through all possible languages.
  389. $all_languages = field_available_languages($entity_type, $field);
  390. $field_languages = array_intersect($all_languages, array_keys((array) $entity->$field_name));
  391. foreach ($field_languages as $langcode) {
  392. $items = (array) $entity->{$field_name}[$langcode];
  393. // The number of items is related to the cardinatily of the field.
  394. foreach ($items as $delta => $item) {
  395. $values[$chado_field] = $item['value'];
  396. }
  397. }
  398. }
  399. }
  400. // Add in the type_id field.
  401. $values[$type_field] = $entity->cvterm_id;
  402. switch ($op) {
  403. case FIELD_STORAGE_INSERT:
  404. $record = chado_insert_record($tablename, $values);
  405. if (!$record) {
  406. drupal_set_message('Could not insert record.', 'error');
  407. }
  408. $entity->record_id = $record[$pkey_field];
  409. break;
  410. case FIELD_STORAGE_UPDATE:
  411. $match[$pkey_field] = $entity->record_id;
  412. chado_update_record($tablename, $match, $values);
  413. break;
  414. }
  415. }
  416. /**
  417. * Implements hook_field_storage_load().
  418. *
  419. * Responsible for loading the fields from the Chado database and adding
  420. * their values to the entity.
  421. */
  422. function tripal_entities_field_storage_load($entity_type, $entities, $age, $fields, $options) {
  423. }
  424. /**
  425. * An Ajax callback for the tripal_entities_add_form.
  426. */
  427. function tripal_entities_add_form_ajax_callback($form, $form_state) {
  428. // return the form so Drupal can update the content on the page
  429. return $form;
  430. }
  431. /**
  432. * Implements hook_validate() for the tripal_entities_add_form.
  433. */
  434. function tripal_entities_add_form_validate($form, &$form_state) {
  435. if ($form_state['clicked_button']['#name'] == 'add_data') {
  436. $chado_data = (object) $form_state['values'];
  437. field_attach_form_validate('chado_data', $chado_data, $form, $form_state);
  438. }
  439. }
  440. /**
  441. * Implements hook_submit() for the tripal_entities_add_form.
  442. *
  443. */
  444. function tripal_entities_add_form_submit($form, &$form_state) {
  445. if ($form_state['clicked_button']['#name'] == 'select_cvterm') {
  446. // don't do anything, we just need to know what the term name is.
  447. $form_state['rebuild'] = TRUE;
  448. }
  449. else {
  450. // Build and entity instance object.
  451. $entity = (object) $form_state['values'];
  452. // This is an update if the entity_id is in the form_state.
  453. if (array_key_exists('entity_id', $form_state['values'])) {
  454. $entity->entity_id = $form_state['values']['entity_id'];
  455. field_attach_update('chado_data', $entity);
  456. }
  457. else {
  458. field_attach_insert('chado_data', $entity);
  459. }
  460. // Now save the entity
  461. $entity = entity_get_controller('chado_data')->save($entity);
  462. // $form_state['redirect'] = "chado_data/$chado_data->entity_id";
  463. }
  464. }
  465. /**
  466. * Implements hook_theme().
  467. */
  468. function tripal_entities_theme($existing, $type, $theme, $path) {
  469. return array(
  470. );
  471. }
  472. /**
  473. *
  474. *
  475. */
  476. class TrpVocabularyTermController extends DrupalDefaultEntityController {
  477. public function save($entity) {
  478. global $user;
  479. $tablename = 'feature';
  480. $type_field = 'type_id';
  481. $schema = chado_get_schema($tablename);
  482. $pkey_field = $schema['primary key'][0];
  483. $record = array(
  484. 'cvterm_id' => $entity->cvterm_id,
  485. 'tablename' => $tablename,
  486. 'record_id' => $entity->record_id,
  487. 'title' => 'title',
  488. 'uid' => $user->uid,
  489. 'created' => time(),
  490. 'changed' => time(),
  491. );
  492. $success = drupal_write_record('tripal_entity', $record);
  493. return $entity;
  494. }
  495. }