tripal_entities.module 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586
  1. <?php
  2. require_once "api/tripal_entities.api.inc";
  3. require_once "includes/tripal_entities.chado_entity.inc";
  4. require_once "includes/tripal_entities.entity_form.inc";
  5. require_once "includes/tripal_entities.tables.inc";
  6. require_once "includes/TripalEntity.inc";
  7. require_once "includes/TripalEntityController.inc";
  8. require_once "includes/TripalEntityUIController.inc";
  9. require_once "includes/TripalBundle.inc";
  10. require_once "includes/TripalBundleController.inc";
  11. require_once "includes/TripalBundleUIController.inc";
  12. /**
  13. * Implements hook_views_api().
  14. */
  15. function tripal_entities_views_api() {
  16. return array(
  17. 'api' => 3,
  18. );
  19. }
  20. /**
  21. * Implements hook_menu().
  22. */
  23. function tripal_entities_menu() {
  24. $items = array();
  25. // The administative settings menu.
  26. $items['admin/tripal/bio_data'] = array(
  27. 'title' => 'Biological Data',
  28. 'description' => 'Tools for publishing, configurating and managing biological data.',
  29. 'page callback' => 'tripal_entities_admin_view',
  30. 'access arguments' => array('administer tripal data types'),
  31. 'file' => 'includes/tripal_entities.admin.inc',
  32. 'type' => MENU_NORMAL_ITEM,
  33. );
  34. // The default tab.
  35. $items['admin/tripal/bio_data/default'] = array(
  36. 'title' => 'Biological Data',
  37. 'type' => MENU_DEFAULT_LOCAL_TASK,
  38. 'weight' => 1,
  39. );
  40. $items['admin/tripal/bio_data/publish'] = array(
  41. 'title' => 'Publish',
  42. 'description' => 'Publish Data',
  43. 'page callback' => 'tripal_entities_publish',
  44. 'access arguments' => array('administer tripal data types'),
  45. 'file' => 'includes/tripal_entities.admin.inc',
  46. 'type' => MENU_LOCAL_TASK,
  47. 'weight' => 2
  48. );
  49. $items['admin/tripal/bio_data/publish/%'] = array(
  50. 'title' => 'Publish',
  51. 'description' => 'Publish Data',
  52. 'page callback' => 'tripal_entities_publish',
  53. 'page arguments' => array(4),
  54. 'access arguments' => array('administer tripal data types'),
  55. 'file' => 'includes/tripal_entities.admin.inc',
  56. 'type' => MENU_CALLBACK,
  57. );
  58. $items['admin/tripal/bio_data/access'] = array(
  59. 'title' => 'Access',
  60. 'description' => 'Set default access permissions for collections of data.',
  61. 'page callback' => 'drupal_get_form',
  62. 'page arguments' => array('tripal_entities_admin_access_form'),
  63. 'access arguments' => array('administer tripal data types'),
  64. 'file' => 'includes/tripal_entities.admin.inc',
  65. 'type' => MENU_LOCAL_TASK,
  66. 'weight' => 3
  67. );
  68. return $items;
  69. }
  70. /**
  71. * Implements hook_permission().
  72. */
  73. function tripal_entities_permission() {
  74. // We set up permisssions to manage entity types, manage all entities and the
  75. // permissions for each individual entity
  76. $permissions = array(
  77. 'administer tripal data types' => array(
  78. 'title' => t('Administer Tripal data types'),
  79. 'description' => t('Create and delete fields for Tripal data types, and set their permissions.'),
  80. ),
  81. 'administer tripal data' => array(
  82. 'title' => t('Administer Tripal data'),
  83. 'description' => t('Edit and delete all tripal data'),
  84. ),
  85. );
  86. return $permissions;
  87. }
  88. /**
  89. * Implements hook_theme().
  90. */
  91. function tripal_entities_theme($existing, $type, $theme, $path) {
  92. return array(
  93. 'tripal_entity' => array(
  94. 'render element' => 'elements',
  95. 'template' => 'tripal_entity',
  96. 'path' => "$path/theme/templates"
  97. ),
  98. 'tripal_entities_date_combo' => array(
  99. 'render element' => 'element',
  100. 'file' => 'includes/tripal_entities.chado_entity.inc',
  101. ),
  102. );
  103. }
  104. /**
  105. * https://api.drupal.org/api/drupal/modules!rdf!rdf.module/group/rdf/7
  106. */
  107. function tripal_entities_rdf_mapping() {
  108. return array();
  109. /* return array(
  110. 'type' => 'tripal_entity',
  111. 'bundle' => 'gene',
  112. 'mapping' => array(
  113. 'rdftype' => array('sioc:Item', 'foaf:Document'),
  114. 'title' => array(
  115. 'predicates' => array('dc:title'),
  116. ),
  117. 'uid' => array(
  118. 'predicates' => array('sioc:has_creator'),
  119. 'type' => 'rel',
  120. ),
  121. 'name' => array(
  122. 'predicates' => array('foaf:name'),
  123. ),
  124. 'uniquename' => array(
  125. 'predicates' => array('foaf:name'),
  126. ),
  127. 'organism_id' => array(
  128. 'predicates' => array('sioc:has_parent'),
  129. 'type' => 'rel'
  130. )
  131. ),
  132. ); */
  133. }
  134. // http://www.bluespark.com/blog/drupal-entities-part-3-programming-hello-drupal-entity
  135. // http://dikini.net/31.08.2010/entities_bundles_fields_and_field_instances
  136. /**
  137. * Implement hook_entity_info().
  138. */
  139. function tripal_entities_entity_info() {
  140. $entities = array();
  141. // Get a list of published vocabularies from 'tripal_vocabulary
  142. $published_vocs = chado_generate_var('tripal_vocabulary', array('publish' => 1), array('return_array' => 1));
  143. foreach ($published_vocs as $voc) {
  144. $entities[$voc->db_id->name] = array (
  145. // A human readable label to identify our entity.
  146. 'label' => $voc->db_id->name . ' (' . $voc->cv_id->name . ')',
  147. 'plural label' => $voc->db_id->name . ' (' . $voc->cv_id->name . ')',
  148. // The entity class and controller class extend the classes provided by the
  149. // Entity API.
  150. 'entity class' => 'TripalEntity',
  151. 'controller class' => 'TripalEntityController',
  152. // The table for this entity defined in hook_schema()
  153. 'base table' => 'tripal_entity',
  154. // Returns the uri elements of an entity.
  155. 'uri callback' => 'tripal_entities_vocbulary_term_uri',
  156. // IF fieldable == FALSE, we can't attach fields.
  157. 'fieldable' => TRUE,
  158. // entity_keys tells the controller what database fields are used for key
  159. // functions. It is not required if we don't have bundles or revisions.
  160. // Here we do not support a revision, so that entity key is omitted.
  161. 'entity keys' => array (
  162. 'id' => 'id',
  163. 'bundle' => 'bundle'
  164. ),
  165. 'bundle keys' => array (
  166. 'bundle' => 'bundle'
  167. ),
  168. // Callback function for access to this entity.
  169. 'access callback' => 'tripal_entity_access',
  170. // FALSE disables caching. Caching functionality is handled by Drupal core.
  171. 'static cache' => FALSE,
  172. // Bundles are added in the hook_entities_info_alter() function.
  173. 'bundles' => array (),
  174. 'label callback' => 'tripal_entity_label',
  175. // The information below is used by the TripalEntityUIController
  176. // (which extends the EntityDefaultUIController). The admin_ui
  177. // key here is mean to appear on the 'Find Content' page of the
  178. // administrative menu.
  179. 'admin ui' => array (
  180. 'path' => 'admin/content/bio_data',
  181. 'controller class' => 'TripalEntityUIController',
  182. 'menu wildcard' => '%tripal_entity',
  183. 'file' => 'includes/TripalEntityUIController.inc'
  184. ),
  185. 'view modes' => array (
  186. 'full' => array (
  187. 'label' => t ( 'Full content' ),
  188. 'custom settings' => FALSE
  189. ),
  190. 'teaser' => array (
  191. 'label' => t ( 'Teaser' ),
  192. 'custom settings' => TRUE
  193. )
  194. )
  195. );
  196. // The entity that holds information about the entity types.
  197. $entities [$voc->db_id->name . '_bundle'] = array (
  198. 'label' => $voc->db_id->name . ' (' . $voc->cv_id->name . ') Data Type',
  199. 'entity class' => 'TripalBundle',
  200. 'controller class' => 'TripalBundleController',
  201. 'base table' => 'tripal_bundle',
  202. 'fieldable' => FALSE,
  203. 'exportable' => FALSE,
  204. 'entity keys' => array (
  205. 'id' => 'id',
  206. 'name' => 'bundle',
  207. 'label' => 'label'
  208. ),
  209. 'access callback' => 'tripal_bundle_access',
  210. 'module' => 'tripal_entities',
  211. // Enable the entity API's admin UI.
  212. 'admin ui' => array (
  213. 'path' => 'admin/structure/bio_data/' . $voc->db_id->name,
  214. 'controller class' => 'TripalBundleUIController',
  215. 'file' => 'includes/TripalBundleUIController.inc',
  216. 'menu wildcard' => '%tripal_bundle',
  217. )
  218. );
  219. }
  220. return $entities;
  221. }
  222. /**
  223. * Implements hook_entity_info_alter().
  224. *
  225. * We are adding the info about the tripal data types via a hook to avoid a
  226. * recursion issue as loading the model types requires the entity info as well.
  227. *
  228. */
  229. function tripal_entities_entity_info_alter(&$entity_info) {
  230. // Get a list of published terms from 'tripal_term
  231. $published_terms = chado_generate_var('tripal_term', array('publish' => 1), array('return_array' => 1));
  232. foreach ($published_terms as $term) {
  233. // Bundles are alternative groups of fields or configuration
  234. // associated with a base entity type.
  235. // We want to dynamically add the bundles (or term types) to the entity.
  236. $cvterm = $term->cvterm_id;
  237. $entity_type = $cvterm->dbxref_id->db_id->name;
  238. $accession = $cvterm->dbxref_id->accession;
  239. $bundle_id = $entity_type . '_' . $accession;
  240. $label = preg_replace('/_/', ' ', ucwords($cvterm->name));
  241. $entity_info[$entity_type]['bundles'][$bundle_id] = array (
  242. 'label' => $label,
  243. 'admin' => array (
  244. 'path' => 'admin/structure/bio_data/' . $entity_type . '/manage/%tripal_bundle',
  245. 'real path' => 'admin/structure/bio_data/' . $entity_type . '/manage/' . $bundle_id,
  246. 'bundle argument' => 5,
  247. 'access arguments' => array (
  248. 'administer tripal data types'
  249. )
  250. )
  251. );
  252. }
  253. }
  254. /**
  255. * Get published vocabularies as select options
  256. * @return multitype:NULL
  257. */
  258. function tripal_entities_get_published_vocabularies_as_select_options() {
  259. $published_vocs = chado_generate_var('tripal_vocabulary', array('publish' => 1), array('return_array' => 1));
  260. $options = array();
  261. foreach ($published_vocs as $voc) {
  262. $options [$voc->cv_id->cv_id] = $voc->cv_id->name;
  263. }
  264. return $options;
  265. }
  266. /**
  267. * Get published vocabularies as select options
  268. * @return multitype:NULL
  269. */
  270. function tripal_entities_get_db_names_for_published_vocabularies() {
  271. $published_vocs = chado_generate_var('tripal_vocabulary', array('publish' => 1), array('return_array' => 1));
  272. $db = array();
  273. foreach ($published_vocs as $voc) {
  274. $db [$voc->db_id->db_id] = $voc->db_id->name;
  275. }
  276. return $db;
  277. }
  278. /**
  279. * Get published terms as select options
  280. * @return multitype:NULL
  281. */
  282. function tripal_entities_get_published_terms_as_select_options($cv_id = NULL) {
  283. $where = array('publish' => 1);
  284. $published_terms = chado_generate_var('tripal_term', $where, array('return_array' => 1));
  285. $options = array();
  286. foreach ($published_terms as $term) {
  287. if (!$cv_id) {
  288. $options [$term->cvterm_id->name] = $term->cvterm_id->name;
  289. } else {
  290. if ($term->cvterm_id->cv_id->cv_id == $cv_id) {
  291. $options [$term->cvterm_id->name] = $term->cvterm_id->name;
  292. }
  293. }
  294. }
  295. return $options;
  296. }
  297. /**
  298. * Menu argument loader; Load a tripal data type by string.
  299. *
  300. * @param $type
  301. * The machine-readable name of a tripal data type to load.
  302. * @return
  303. * A tripal data type array or FALSE if $type does not exist.
  304. */
  305. function tripal_bundle_load($bundle_type, $reset = FALSE) {
  306. // Get the type of entity by the ID.
  307. $bundle_types = db_select('tripal_bundle', 'tdt')
  308. ->fields('tdt', array('id', 'type'))
  309. ->condition('bundle', $bundle_type)
  310. ->execute()
  311. ->fetchObject();
  312. // Load the tripal_bundle entity. These entities are always the same
  313. // as an Tripal entity type but with a '_bundle' extension.
  314. $entity = entity_load($bundle_types->type . '_bundle', array($bundle_types->id), array(), $reset);
  315. return reset($entity);
  316. }
  317. /**
  318. * Allows the menu system to use a wildcard to fetch the entity.
  319. *
  320. * Make sure that the wildcard you choose in the tripal_entity entity
  321. * definition fits the function name here.
  322. *
  323. * @param $id
  324. * Integer specifying the tripal_entity id.
  325. * @param $reset
  326. * A boolean indicating that the internal cache should be reset.
  327. * @return
  328. * A fully-loaded $tripal_entity object or FALSE if it cannot be loaded.
  329. *
  330. * @see tripal_entity_load_multiple()
  331. */
  332. function tripal_entity_load($id, $reset = FALSE) {
  333. // Get the type of entity by the ID.
  334. $entity_type = db_select('tripal_entity', 'td')
  335. ->fields('td', array('type'))
  336. ->condition('id', $id)
  337. ->execute()
  338. ->fetchField();
  339. // Load the entity.
  340. if ($entity_type) {
  341. $entity = entity_load($entity_type, array($id), array(), $reset);
  342. return reset($entity);
  343. }
  344. return FALSE;
  345. }
  346. /**
  347. *
  348. * Implements hook_form_FORM_ID_alter().
  349. *
  350. * The field_ui_field_edit_form is used for customizing the settings of
  351. * a field attached to an entity.
  352. */
  353. function tripal_entities_form_field_ui_field_edit_form_alter(&$form, &$form_state, $form_id) {
  354. // For entity fields added by Tripal Entities we don't want the
  355. // the end-user to change the cardinality and the required fields
  356. // such that record can't be saved in Chado.
  357. $dbs = tripal_entities_get_db_names_for_published_vocabularies();
  358. if (in_array($form['#instance']['entity_type'], $dbs)) {
  359. $form['field']['cardinality']['#access'] = FALSE;
  360. $form['instance']['required']['#access'] = FALSE;
  361. }
  362. // TODO: don't the the maximum length be larger than the field size.
  363. }
  364. /**
  365. * Implements hook_form_FORM_ID_alter().
  366. *
  367. * The field_ui_display_overview_form is used for formatting the display
  368. * or layout of fields attached to an entity.
  369. */
  370. function tripal_entities_form_field_ui_display_overview_form_alter(&$form, &$form_state, $form_id) {
  371. $entity_type = $form['#entity_type'];
  372. $bundle_name = $form['#bundle'];
  373. // Get the bundle record.
  374. $bundle = db_select('tripal_bundle', 'tb')
  375. ->fields('tb')
  376. ->condition('bundle', $bundle_name)
  377. ->execute()
  378. ->fetchObject();
  379. if (module_exists('ds')) {
  380. drupal_set_message('Tripal is not compatible with the Display Suite (ds) module. If you would like to use Tripal-style panels for the layout of your pages please disable the Display Suite module.', 'warning');
  381. }
  382. // Add a vertical tab fieldset at the bottom of the
  383. $form['overview_vert_tabs'] = array(
  384. '#type' => 'vertical_tabs'
  385. );
  386. $form['modes']['#group'] = 'overview_vert_tabs';
  387. $form['modes']['#weight'] = 1000;
  388. $form['tripal_entity_layout'] = array(
  389. '#type' => 'fieldset',
  390. '#title' => 'Panels',
  391. '#collapsible' => TRUE,
  392. '#collapsed' => TRUE,
  393. '#group' => 'overview_vert_tabs'
  394. );
  395. $form['tripal_entity_layout']['panel_name'] = array(
  396. '#type' => 'textfield',
  397. '#title' => 'Add a new Panel',
  398. '#description' => t('You may add as many panels to your page layout as
  399. desired. Panels can be used to organize fields into categories....')
  400. );
  401. // Make sure our default panels are in the database.
  402. _tripal_entities_check_default_field_panels();
  403. // Now add each panel as a region.
  404. $form['fields']['#regions'] = array();
  405. $panels = db_select('tripal_panels', 'tp')
  406. ->fields('tp')
  407. ->condition('bundle_id', $bundle->id)
  408. ->orderBy('weight', 'ASC')
  409. ->orderBy('label', 'ASC')
  410. ->execute();
  411. $panel_options = array();
  412. while ($panel = $panels->fetchObject()) {
  413. $settings = unserialize($panel->settings);
  414. $form['fields']['#regions'][$panel->name] = array(
  415. 'title' => t($panel->label),
  416. 'message' => t($settings['message']),
  417. );
  418. $panel_options[$panel->name] = $panel->label;
  419. }
  420. // Set the table headers to add a new 'region' column.
  421. $form['fields']['#header'] = array(
  422. t('Field'),
  423. t('Weight'),
  424. t('Parent'),
  425. t('Label'),
  426. array('data' => t('Format'), 'colspan' => 3),
  427. t('Region'),
  428. );
  429. // Change the region callback for each field to place each field in the
  430. // proper "panel" region. Also, set the default region to be the base region.
  431. $fields = $form['fields'];
  432. foreach (element_children($fields) as $field_name) {
  433. $form['fields'][$field_name]['#region_callback'] = 'tripal_entities_field_ui_row_region';
  434. $form['fields'][$field_name]['region'] = array(
  435. '#type' => 'select',
  436. '#options' => $panel_options,
  437. '#default_value' => 'te_base',
  438. '#attributes' => array(
  439. 'class' => array('te-field-region'),
  440. )
  441. );
  442. }
  443. // Add validate and submit handlers. Rearrange the submit callbacks
  444. // so ours is first.
  445. $form['#validate'][] = 'tripal_entities_field_ui_validate';
  446. $submit = $form['#submit'];
  447. $form['#submit'] = array('tripal_entities_field_ui_submit');
  448. $form['#submit'] = array_merge($form['#submit'], $submit);
  449. }
  450. /**
  451. * A helper function for checking if the default panels are in the database.
  452. */
  453. function _tripal_entities_check_default_field_panels() {
  454. // Make sure we have records for our default regions: te_base and te_hidden.
  455. // First check if the base region is in the database. If not, add it.
  456. $te_base = db_select('tripal_panels', 'tp')
  457. ->fields('tp')
  458. ->condition('name', 'te_base')
  459. ->execute()
  460. ->fetchObject();
  461. if (!$te_base) {
  462. $settings = array(
  463. 'message' => 'Fields that should appear at the top of each page should be placed in the base panel. These fields are always present and help orient the user by at least indicating the necessary information to uniquely identiy the content.',
  464. );
  465. db_insert('tripal_panels')
  466. ->fields(array(
  467. 'bundle_id' => $bundle->id,
  468. 'name' => 'te_base',
  469. 'label' => 'Base Content',
  470. 'settings' => serialize($settings),
  471. 'weight' => -9999999
  472. ))
  473. ->execute();
  474. }
  475. // Next check if the hidden region is in the database. If not, add it.
  476. $te_base = db_select('tripal_panels', 'tp')
  477. ->fields('tp')
  478. ->condition('name', 'te_hidden')
  479. ->execute()
  480. ->fetchObject();
  481. if (!$te_base) {
  482. $settings = array(
  483. 'message' => 'Place field here to hide them from display.',
  484. );
  485. db_insert('tripal_panels')
  486. ->fields(array(
  487. 'bundle_id' => $bundle->id,
  488. 'name' => 'te_hidden',
  489. 'label' => 'Hidden',
  490. 'settings' => serialize($settings),
  491. 'weight' => 9999999
  492. ))
  493. ->execute();
  494. }
  495. }
  496. /**
  497. * Returns the region to which a row on the Field UI page belongs.
  498. *
  499. * @param $row
  500. * The current row that is being rendered in the Field UI page.
  501. */
  502. function tripal_entities_field_ui_row_region($row) {
  503. $default_panel = 'te_base';
  504. $panel = '';
  505. $field_name = $row['#parents'][1];
  506. $field = field_info_field($field_name);
  507. // First get the panel
  508. if (!$panel) {
  509. $panel = $default_panel;
  510. }
  511. // See if there is a record in the tripal_panel_fields for this field.
  512. return $default_panel;
  513. }
  514. /**
  515. * Validates the field UI form to ensure proper panel assignments.
  516. *
  517. * @param $form
  518. * @param $form_state
  519. */
  520. function tripal_entities_field_ui_validate($form, &$form_state) {
  521. }
  522. /**
  523. * Responds to a submit from the field UI form for saving panel assignments.
  524. *
  525. * @param $form
  526. * @param $form_state
  527. */
  528. function tripal_entities_field_ui_submit($form, &$form_state) {
  529. }