tripal.module 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056
  1. <?php
  2. /**
  3. * @file
  4. * The Tripal Core module
  5. */
  6. // Import the full Tripal API into scope.
  7. tripal_import_api();
  8. require_once "includes/TripalVocab.inc";
  9. require_once "includes/TripalVocabController.inc";
  10. require_once "includes/TripalVocabViewsController.inc";
  11. require_once "includes/TripalTerm.inc";
  12. require_once "includes/TripalTermController.inc";
  13. require_once "includes/TripalTermViewsController.inc";
  14. require_once "includes/TripalEntity.inc";
  15. require_once "includes/TripalEntityController.inc";
  16. require_once "includes/TripalEntityUIController.inc";
  17. require_once "includes/TripalEntityViewsController.inc";
  18. require_once "includes/TripalBundle.inc";
  19. require_once "includes/TripalBundleController.inc";
  20. require_once "includes/TripalBundleUIController.inc";
  21. /**
  22. * @defgroup tripal Tripal Core Module
  23. * @ingroup tripal_modules
  24. * @{
  25. * Functionality useful for all other Tripal modules including the Tripal jobs, files,
  26. * materialized views and custom table functions.
  27. * @}
  28. */
  29. /**
  30. * Implements hook_views_api().
  31. */
  32. function tripal_views_api() {
  33. return array(
  34. 'api' => 3,
  35. );
  36. }
  37. /**
  38. * Implements hook_init().
  39. * Used to set the search_path, create default content and set default variables.
  40. *
  41. * @ingroup tripal
  42. */
  43. function tripal_init() {
  44. global $base_url;
  45. // add some variables for all javasript to use for building URLs
  46. $clean_urls = variable_get('clean_url', 0);
  47. drupal_add_js(
  48. "var baseurl = '$base_url';" .
  49. "var isClean = $clean_urls;",
  50. 'inline', 'header');
  51. // make sure the date time settings are the way Tripal will insert them
  52. // otherwise PostgreSQL version that may have a different datestyle setting
  53. // will fail when inserting or updating a date column in a table.
  54. db_query("SET DATESTYLE TO :style", array(':style' => 'MDY'));
  55. }
  56. /**
  57. * Implements hook_menu().
  58. * Defines all menu items needed by Tripal Core
  59. *
  60. * @ingroup tripal
  61. */
  62. function tripal_menu() {
  63. $items = array();
  64. // Tripal setting groups
  65. $items['admin/tripal'] = array(
  66. 'title' => 'Tripal',
  67. 'description' => t("Manage the behavior or Tripal and its various modules."),
  68. 'weight' => -8,
  69. 'page callback' => 'system_admin_menu_block_page',
  70. 'access arguments' => array('administer tripal'),
  71. 'file' => 'system.admin.inc',
  72. 'file path' => drupal_get_path('module', 'system'),
  73. );
  74. $items['admin/tripal/tripal_jobs'] = array(
  75. 'title' => 'Jobs',
  76. 'description' => t('Provides tools for managing jobs submitted to Tripal. In some
  77. cases, long-running tasks are too slow to complete within a single
  78. browser session. The Tripal jobs system allows long-running tasks
  79. to be submitted to a queue that can be executed manually by the
  80. site admin or automatically using a module such as the ') .
  81. l('Tripal Daemon', 'https://www.drupal.org/project/tripal_daemon', array('attributes' => array('target' => '_blank'))) .
  82. ' extension module.',
  83. 'page callback' => 'tripal_jobs_admin_view',
  84. 'access arguments' => array('administer tripal'),
  85. 'type' => MENU_NORMAL_ITEM,
  86. 'weight' => 0,
  87. 'file' => 'includes/tripal.jobs.inc',
  88. 'file path' => drupal_get_path('module', 'tripal'),
  89. );
  90. $items['admin/tripal/storage'] = array(
  91. 'title' => 'Storage Backend',
  92. 'description' => t("Tripal is designed to access biological
  93. data in any data storage back-end. A storage back-end must have a
  94. module that can be installed that interfaces with Tripal. By default
  95. the base Tripal package provides The Tripal Chado module for storing
  96. data in the GMOD Chado database schema. All available storage backends
  97. and their administrative tools are found here."),
  98. 'weight' => 8,
  99. 'access arguments' => array('administer tripal'),
  100. );
  101. $items['admin/tripal/terms'] = array(
  102. 'title' => 'Vocabularies',
  103. 'description' => t("Vocabulary terms are essential to creating content
  104. in Tripal. This allows data to be shared more easily with others
  105. using technologies such as the semantic web and web services.
  106. Before creating content you must have loaded vocabularies and their
  107. terms."),
  108. 'weight' => 8,
  109. 'access arguments' => array('administer tripal'),
  110. );
  111. $items['admin/tripal/terms/import'] = array(
  112. 'title' => 'Import Vocabulary',
  113. 'description' => t("Import vocabularies and terms in OBO format."),
  114. 'access arguments' => array('administer tripal'),
  115. 'page callback' => 'drupal_get_form',
  116. 'page arguments' => array('tripal_vocabulary_import_form'),
  117. 'file' => 'includes/tripal.admin.inc',
  118. 'file path' => drupal_get_path('module', 'tripal'),
  119. 'type' => MENU_NORMAL_ITEM,
  120. );
  121. // Menu items for facilitating import of extension modules.
  122. $items['admin/tripal/extension'] = array(
  123. 'title' => 'Extensions',
  124. 'description' => t('Look for extensions to add new functionality to this
  125. site. Tripal can be extended with new functionality developed
  126. by other Tripal site developers. These include modules with new or
  127. different functionality, bulk loading templates, or materialized
  128. views. Anyone can create new extensions and share those for
  129. others to use. Once shared they will appear in this list.'),
  130. 'access arguments' => array('administer tripal'),
  131. 'page callback' => 'drupal_get_form',
  132. 'page arguments' => array('tripal_extensions_form'),
  133. 'type' => MENU_NORMAL_ITEM,
  134. 'file' => 'includes/tripal.extensions.inc',
  135. 'file path' => drupal_get_path('module', 'tripal'),
  136. 'weight' => 100
  137. );
  138. $items['admin/tripal/extension/import'] = array(
  139. 'title' => 'Import Extensions',
  140. 'description' => 'Provides a list of the available extensions that are registered at the tripal.info site. From this page you can easily import or install extensions to your site.',
  141. 'page callback' => 'drupal_get_form',
  142. 'page arguments' => array('tripal_extensions_form'),
  143. 'access arguments' => array('administer tripal'),
  144. 'type' => MENU_NORMAL_ITEM,
  145. 'file' => 'includes/tripal.extensions.inc',
  146. 'file path' => drupal_get_path('module', 'tripal'),
  147. 'weight' => -100,
  148. );
  149. /*
  150. $items['admin/tripal/setup/customize'] = array(
  151. 'title' => 'Customize Tripal',
  152. 'description' => t('Information on how to customize tripal'),
  153. 'page callback' => 'theme',
  154. 'page arguments' => array('tripal_customize'),
  155. 'access arguments' => array('administer tripal'),
  156. 'weight' => 10
  157. );
  158. */
  159. // Jobs Management
  160. $items['admin/tripal/tripal_jobs/help'] = array(
  161. 'title' => 'Help',
  162. 'description' => t('Help for the tripal job management system'),
  163. 'page callback' => 'theme',
  164. 'page arguments' => array('tripal_job_help'),
  165. 'access arguments' => array('administer tripal'),
  166. 'type' => MENU_LOCAL_TASK,
  167. 'weight' => 10
  168. );
  169. $items['admin/tripal/tripal_jobs/cancel/%'] = array(
  170. 'title' => 'Jobs',
  171. 'description' => t('Cancel a pending job'),
  172. 'page callback' => 'tripal_cancel_job',
  173. 'page arguments' => array(4),
  174. 'access arguments' => array('administer tripal'),
  175. 'type' => MENU_CALLBACK,
  176. );
  177. $items['admin/tripal/tripal_jobs/rerun/%'] = array(
  178. 'title' => 'Jobs',
  179. 'description' => t('Re-run an existing job.'),
  180. 'page callback' => 'tripal_rerun_job',
  181. 'page arguments' => array(4),
  182. 'access arguments' => array('administer tripal'),
  183. 'type' => MENU_CALLBACK,
  184. );
  185. $items['admin/tripal/tripal_jobs/view/%'] = array(
  186. 'title' => 'Jobs Details',
  187. 'description' => t('View job details.'),
  188. 'page callback' => 'tripal_jobs_view',
  189. 'page arguments' => array(4),
  190. 'access arguments' => array('administer tripal'),
  191. 'type' => MENU_CALLBACK,
  192. );
  193. $items['admin/tripal/tripal_jobs/views/jobs/enable'] = array(
  194. 'title' => 'Enable Jobs Administrative View',
  195. 'page callback' => 'tripal_enable_view',
  196. 'page arguments' => array('tripal_admin_jobs', 'admin/tripal/tripal_jobs'),
  197. 'access arguments' => array('administer tripal'),
  198. 'type' => MENU_CALLBACK,
  199. );
  200. return $items;
  201. }
  202. /**
  203. * Implements hook_permission().
  204. */
  205. function tripal_permission() {
  206. return array(
  207. 'administer tripal' => array(
  208. 'title' => t('Administer Tripal'),
  209. 'description' => t('Allow the user to access administrative pages of Tripal.')
  210. ),
  211. 'view dev helps' => array(
  212. 'title' => t('View Developer Hints'),
  213. 'description' => t('Tripal will provide blue shaded boxes that provide
  214. instructions for how to customize or setup specific pages on a
  215. site. This permission should be enabled for developers. But can
  216. be disabled once developers are accustomed to these hints.'),
  217. 'restrict access' => TRUE,
  218. ),
  219. 'administer tripal data types' => array(
  220. 'title' => t('Administer Tripal data types'),
  221. 'description' => t('Create and delete fields for Tripal data types, and set their permissions.'),
  222. ),
  223. 'administer tripal data' => array(
  224. 'title' => t('Administer Tripal data'),
  225. 'description' => t('Edit and delete all tripal data'),
  226. ),
  227. 'administer controlled vocabularies' => array(
  228. 'title' => t('Administer controlled vocabularies (CVs).'),
  229. 'description' => t('Allow a user to add, edit and delete controlled vocabularies as well as add and edit terms.')
  230. ),
  231. );
  232. }
  233. /**
  234. * Checks access permissions for a given entity.
  235. */
  236. function tripal_entity_access($entity) {
  237. // TODO: need to implement this function.
  238. return TRUE;
  239. }
  240. /**
  241. * Implements hook_theme().
  242. * Registers template files/functions used by this module.
  243. *
  244. * @ingroup tripal
  245. */
  246. function tripal_theme($existing, $type, $theme, $path) {
  247. return array(
  248. 'tripal_customize' => array(
  249. 'arguments' => array('job_id' => NULL),
  250. 'template' => 'tripal_customize',
  251. 'path' => "$path/theme/templates"
  252. ),
  253. 'theme_file_upload_combo' => array(
  254. 'render element' => 'element',
  255. ),
  256. 'theme_sequence_combo' => array(
  257. 'render element' => 'element',
  258. ),
  259. 'tripal_jobs_help' => array(
  260. 'template' => 'tripal_jobs_help',
  261. 'variables' => array(NULL),
  262. 'path' => "$path/theme/templates"
  263. ),
  264. 'tripal_customtables_help' => array(
  265. 'template' => 'tripal_customtables_help',
  266. 'variables' => array(NULL),
  267. 'path' => "$path/theme/templates"
  268. ),
  269. // Admin messages theme
  270. 'tripal_admin_message' => array(
  271. 'function' => 'theme_tripal_admin_message',
  272. 'variables' => array('message' => NULL),
  273. ),
  274. 'tripal_entity' => array(
  275. 'render element' => 'elements',
  276. 'template' => 'tripal_entity',
  277. 'path' => "$path/theme/templates"
  278. ),
  279. 'tripal_add_list' => array(
  280. 'variables' => array('content' => NULL),
  281. ),
  282. );
  283. }
  284. /**
  285. * Implements hook_coder_ignore().
  286. * Defines the path to the file (tripal.coder_ignores.txt) where ignore rules for coder are stored
  287. */
  288. function tripal_coder_ignore() {
  289. return array(
  290. 'path' => drupal_get_path('module', 'tripal'),
  291. 'line prefix' => drupal_get_path('module', 'tripal'),
  292. );
  293. }
  294. /**
  295. * Implements hook_libraries_info().
  296. */
  297. function tripal_libraries_info() {
  298. $libraries = array();
  299. $libraries['d3'] = array(
  300. 'name' => 'D3.js',
  301. 'vendor url' => 'http://d3js.org/',
  302. 'download url' => 'https://github.com/mbostock/d3',
  303. 'version arguments' => array(
  304. 'file' => 'd3.js',
  305. 'pattern' => '/\s*version: "(\d+\.\d+\.\d+)"/',
  306. ),
  307. 'files' => array(
  308. 'js' => array(
  309. 'd3.min.js',
  310. ),
  311. ),
  312. );
  313. return $libraries;
  314. }
  315. /**
  316. * Implements hook_admin_paths().
  317. * Define administrative paths.
  318. */
  319. function tripal_admin_paths() {
  320. if (variable_get('node_admin_theme')) {
  321. $paths = array(
  322. 'bio-data/*/edit' => TRUE,
  323. 'bio-data/*/delete' => TRUE,
  324. 'bio-data/add' => TRUE,
  325. 'bio-data/add/*' => TRUE,
  326. );
  327. return $paths;
  328. }
  329. }
  330. /**
  331. * Implements hook_menu_local_tasks_alter().
  332. *
  333. * Used to add action links to pages.
  334. */
  335. function tripal_menu_local_tasks_alter(&$data, $router_item, $root_path) {
  336. // Add an "Add Tripal Content" action link to the Admin >> Content >>
  337. // Biological Content page.
  338. if ($root_path == 'admin/content/bio-data') {
  339. $item = menu_get_item('bio-data/add');
  340. if ($item['access']) {
  341. $data['actions']['output'][] = array(
  342. '#theme' => 'menu_local_action',
  343. '#link' => $item,
  344. );
  345. }
  346. }
  347. }
  348. /**
  349. * Implements hook_shortcut_default_set().
  350. * Modify the shortcut menu to include Biological content links.
  351. *
  352. * @param object $account
  353. * The user account whose default shortcut set will be returned. If not provided, the
  354. * function will return the currently logged-in user's default shortcut set.
  355. *
  356. * @return
  357. * An object representing the default shortcut set.
  358. */
  359. function tripal_shortcut_default_set($account) {
  360. $sets = shortcut_sets();
  361. $found = FALSE;
  362. foreach ($sets as $set) {
  363. if ($set->title == 'TripalDefault') {
  364. $found = TRUE;
  365. }
  366. }
  367. if (!$found) {
  368. $t = get_t();
  369. // Create an initial default shortcut set.
  370. $shortcut_set = new stdClass();
  371. $shortcut_set->title = $t('TripalDefault');
  372. $shortcut_set->links = array(
  373. array(
  374. 'link_path' => 'node/add',
  375. 'link_title' => $t('Add content'),
  376. 'weight' => -35,
  377. ),
  378. array(
  379. 'link_path' => 'bio-data/add',
  380. 'link_title' => 'Add Tripal Content',
  381. 'weight' => -30,
  382. ),
  383. array(
  384. 'link_path' => 'admin/content',
  385. 'link_title' => $t('Find content'),
  386. 'weight' => -25,
  387. ),
  388. array(
  389. 'link_path' => 'admin/content/bio-data',
  390. 'link_title' => 'Find Tripal Content',
  391. 'weight' => -20,
  392. ),
  393. );
  394. shortcut_set_save($shortcut_set);
  395. }
  396. $sets = shortcut_sets();
  397. foreach ($sets as $set) {
  398. if ($set->title == 'TripalDefault') {
  399. return $set->set_name;
  400. }
  401. }
  402. }
  403. // http://www.bluespark.com/blog/drupal-entities-part-3-programming-hello-drupal-entity
  404. // http://dikini.net/31.08.2010/entities_bundles_fields_and_field_instances
  405. /**
  406. * Implement hook_entity_info().
  407. */
  408. function tripal_entity_info() {
  409. $entities = array();
  410. //return $entities;
  411. //
  412. // The TripalVocab entity is meant to house vocabularies. It is these
  413. // vocabs that are used by the TripalTerm entities. The storage backend
  414. // is responsible for setting the values of this entity.
  415. //
  416. $entities['TripalVocab'] = array(
  417. // A human readable label to identify our entity.
  418. 'label' => 'Controlled Vocabulary',
  419. 'plural label' => 'Controlled Vocabularies',
  420. // The entity class and controller class extend the classes provided by the
  421. // Entity API.
  422. 'entity class' => 'TripalVocab',
  423. 'controller class' => 'TripalVocabController',
  424. // Adds Views integration for this entity.
  425. 'views controller class' => 'TripalVocabViewsController',
  426. // The table for this entity defined in hook_schema()
  427. 'base table' => 'tripal_vocab',
  428. // If fieldable == FALSE, we can't attach fields.
  429. 'fieldable' => TRUE,
  430. // entity_keys tells the controller what database fields are used for key
  431. // functions. It is not required if we don't have bundles or revisions.
  432. // Here we do not support a revision, so that entity key is omitted.
  433. 'entity keys' => array (
  434. 'id' => 'id',
  435. ),
  436. // Callback function for access to this entity.
  437. 'access callback' => 'tripal_entity_access',
  438. // FALSE disables caching. Caching functionality is handled by Drupal core.
  439. 'static cache' => FALSE,
  440. // This entity doesn't support bundles.
  441. 'bundles' => array (),
  442. 'view modes' => array (
  443. 'full' => array (
  444. 'label' => t ('Full content'),
  445. 'custom settings' => FALSE
  446. ),
  447. 'teaser' => array (
  448. 'label' => t ('Teaser'),
  449. 'custom settings' => TRUE
  450. ),
  451. ),
  452. );
  453. //
  454. // The TripalTerm entity is meant to house vocabulary terms. It is these
  455. // terms that are used by the TripalEntity entities. The storage backend
  456. // is responsible for setting the values of this entity.
  457. //
  458. $entities['TripalTerm'] = array(
  459. // A human readable label to identify our entity.
  460. 'label' => 'Controlled Vocabulary Term',
  461. 'plural label' => 'Controlled Vocabulary Terms',
  462. // The entity class and controller class extend the classes provided by the
  463. // Entity API.
  464. 'entity class' => 'TripalTerm',
  465. 'controller class' => 'TripalTermController',
  466. // Adds Views integration for this entity.
  467. 'views controller class' => 'TripalTermViewsController',
  468. // The table for this entity defined in hook_schema()
  469. 'base table' => 'tripal_term',
  470. // If fieldable == FALSE, we can't attach fields.
  471. 'fieldable' => TRUE,
  472. // entity_keys tells the controller what database fields are used for key
  473. // functions. It is not required if we don't have bundles or revisions.
  474. // Here we do not support a revision, so that entity key is omitted.
  475. 'entity keys' => array (
  476. 'id' => 'id',
  477. ),
  478. // Callback function for access to this entity.
  479. 'access callback' => 'tripal_entity_access',
  480. // FALSE disables caching. Caching functionality is handled by Drupal core.
  481. 'static cache' => FALSE,
  482. // This entity doesn't support bundles.
  483. 'bundles' => array (),
  484. 'view modes' => array (
  485. 'full' => array (
  486. 'label' => t ('Full content'),
  487. 'custom settings' => FALSE
  488. ),
  489. 'teaser' => array (
  490. 'label' => t ('Teaser'),
  491. 'custom settings' => TRUE
  492. ),
  493. ),
  494. );
  495. //
  496. // The TripalEntity is used for all data. It links data from a storage
  497. // back-end to a TripalTerm entity.
  498. //
  499. $entities['TripalEntity'] = array (
  500. // A human readable label to identify our entity.
  501. 'label' => 'Tripal Content',
  502. 'plural label' => 'Tripal Content',
  503. // The entity class and controller class extend the classes provided by the
  504. // Entity API.
  505. 'entity class' => 'TripalEntity',
  506. 'controller class' => 'TripalEntityController',
  507. // Adds Views integration for this entity.
  508. 'views controller class' => 'TripalEntityViewsController',
  509. // The table for this entity defined in hook_schema()
  510. 'base table' => 'tripal_entity',
  511. // Returns the uri elements of an entity.
  512. 'uri callback' => 'tripal_vocbulary_term_uri',
  513. // IF fieldable == FALSE, we can't attach fields.
  514. 'fieldable' => TRUE,
  515. // entity_keys tells the controller what database fields are used for key
  516. // functions. It is not required if we don't have bundles or revisions.
  517. // Here we do not support a revision, so that entity key is omitted.
  518. 'entity keys' => array (
  519. 'id' => 'id',
  520. 'bundle' => 'bundle'
  521. ),
  522. 'bundle keys' => array (
  523. 'bundle' => 'name'
  524. ),
  525. // Callback function for access to this entity.
  526. 'access callback' => 'tripal_entity_access',
  527. // FALSE disables caching. Caching functionality is handled by Drupal core.
  528. 'static cache' => FALSE,
  529. // Bundles are added dynamically below.
  530. 'bundles' => array (),
  531. 'label callback' => 'tripal_entity_label',
  532. // The information below is used by the TripalEntityUIController
  533. // (which extends the EntityDefaultUIController). The admin_ui
  534. // key here is mean to appear on the 'Find Content' page of the
  535. // administrative menu.
  536. 'admin ui' => array (
  537. 'path' => 'admin/content/bio-data',
  538. 'controller class' => 'TripalEntityUIController',
  539. 'menu wildcard' => '%TripalEntity',
  540. 'file' => 'includes/TripalEntityUIController.inc'
  541. ),
  542. 'view modes' => array (
  543. 'full' => array (
  544. 'label' => t ('Full content'),
  545. 'custom settings' => FALSE
  546. ),
  547. 'teaser' => array (
  548. 'label' => t ('Teaser'),
  549. 'custom settings' => TRUE
  550. )
  551. )
  552. );
  553. //
  554. // The TripalBundle entity is used manage the bundle types. The 'bundle of'
  555. // attribute links this to the TripalEntity and allows the UI provided
  556. // by the entity module to work for each TripalEntity bundle.
  557. //
  558. $entities['TripalBundle'] = array (
  559. 'label' => 'Tripal Content Type',
  560. 'entity class' => 'TripalBundle',
  561. 'controller class' => 'TripalBundleController',
  562. 'base table' => 'tripal_bundle',
  563. 'fieldable' => FALSE,
  564. 'bundle of' => 'TripalEntity',
  565. 'exportable' => FALSE,
  566. 'entity keys' => array (
  567. 'id' => 'id',
  568. 'name' => 'name',
  569. 'label' => 'label'
  570. ),
  571. 'access callback' => 'tripal_bundle_access',
  572. 'module' => 'tripal',
  573. // Enable the entity API's admin UI.
  574. 'admin ui' => array (
  575. 'path' => 'admin/structure/bio-data',
  576. 'controller class' => 'TripalBundleUIController',
  577. 'file' => 'includes/TripalBundleUIController.inc',
  578. 'menu wildcard' => '%TripalBundle',
  579. )
  580. );
  581. return $entities;
  582. }
  583. /**
  584. * Implements hook_entities_info_alter().
  585. *
  586. * Add in the bundles (entity types) to the TripalEntity entity.
  587. */
  588. function tripal_entity_info_alter(&$entity_info){
  589. if (array_key_exists('TripalEntity', $entity_info)) {
  590. // Dynamically add in the bundles. Bundles are alternative groups of fields
  591. // or configuration associated with an entity type .We want to dynamically
  592. // add the bundles to the entity.
  593. $bundles = db_select('tripal_bundle', 'tb')
  594. ->fields('tb')
  595. ->execute();
  596. while ($bundle = $bundles->fetchObject()) {
  597. $bundle_name = $bundle->name;
  598. $term_id = $bundle->term_id;
  599. $term = entity_load('TripalTerm', array('id' => $term_id));
  600. $term = reset($term);
  601. $label = preg_replace('/_/', ' ', ucwords($term->name));
  602. $entity_info['TripalEntity']['bundles'][$bundle_name] = array (
  603. 'label' => $label,
  604. 'admin' => array (
  605. 'path' => 'admin/structure/bio-data/manage/%TripalBundle',
  606. 'real path' => 'admin/structure/bio-data/manage/' . $bundle_name,
  607. 'bundle argument' => 4,
  608. 'access arguments' => array (
  609. 'administer tripal data types'
  610. )
  611. )
  612. );
  613. }
  614. }
  615. }
  616. /**
  617. * Menu argument loader; Load a tripal data type by string.
  618. *
  619. * This function is not meant to be used as an API function. It is only meant
  620. * for use in the menu to resolve the %tripal_bundle wildcard.
  621. *
  622. * @param $type
  623. * The machine-readable name of a tripal data type to load.
  624. * @return
  625. * A tripal data type array or FALSE if $type does not exist.
  626. */
  627. function TripalBundle_load($bundle_type, $reset = FALSE) {
  628. // Get the type of entity by the ID.
  629. $bundle = db_select('tripal_bundle', 'tdt')
  630. ->fields('tdt')
  631. ->condition('name', $bundle_type)
  632. ->execute()
  633. ->fetchObject();
  634. if ($bundle) {
  635. $entity = entity_load('TripalBundle', array($bundle->id), array(), $reset);
  636. return reset($entity);
  637. }
  638. return FALSE;
  639. }
  640. /**
  641. * Allows the menu system to use a wildcard to fetch the entity.
  642. *
  643. * Make sure that the wildcard you choose in the tripal_entity entity
  644. * definition fits the function name here.
  645. *
  646. * This function is not meant to be used as an API function. It is only meant
  647. * for use in the menu to resolve the %tripal_entity wildcard.
  648. *
  649. * @param $id
  650. * Integer specifying the tripal_entity id.
  651. * @param $reset
  652. * A boolean indicating that the internal cache should be reset.
  653. * @return
  654. * A fully-loaded $tripal_entity object or FALSE if it cannot be loaded.
  655. *
  656. * @see tripal_entity_load_multiple()
  657. */
  658. function TripalEntity_load($id, $reset = FALSE) {
  659. $entity = entity_load('TripalEntity', array($id), array(), $reset);
  660. return reset($entity);
  661. }
  662. /**
  663. *
  664. * Implements hook_form_FORM_ID_alter().
  665. *
  666. * The field_ui_field_edit_form is used for customizing the settings of
  667. * a field attached to an entity.
  668. *
  669. * This alter function disables some of the form widgets when the storage
  670. * backend indicates they are not appropriate.
  671. */
  672. function tripal_form_field_ui_field_edit_form_alter(&$form, &$form_state, $form_id) {
  673. // For entity fields added by Tripal Entities we don't want the
  674. // the end-user to change the cardinality and the required fields
  675. // such that record can't be saved in Chado.
  676. // TODO: this shouldn't be hardcoded here. These settings
  677. // should be part of the field and handled by the tripal_entity module.
  678. if ($form['#instance']['entity_type'] == 'TripalEntity') {
  679. $form['field']['cardinality']['#access'] = FALSE;
  680. $form['instance']['required']['#access'] = FALSE;
  681. }
  682. // TODO: don't the the maximum length be larger than the field size.
  683. }
  684. /**
  685. *
  686. * Implements hook_form_FORM_ID_alter().
  687. *
  688. * The field_ui_field_overview_form_ is used for adding and reordering the
  689. * fields attached to a bundle. It also includes edit and delete links and
  690. * links for editing field types and widgets.
  691. *
  692. * This alter function is used to add a new 'Supported By' column to
  693. * the table to let the user know where fields are storing their data.
  694. */
  695. function tripal_form_field_ui_field_overview_form_alter(&$form, &$form_state, $form_id) {
  696. // Add the 'Storage Location' to the table header.
  697. $form['fields']['#header'][] = 'Supported By * ';
  698. // Add the storage location as the final column for each field.
  699. $storage_info = module_invoke_all('field_storage_info');
  700. foreach (element_children($form['fields']) as $field_name) {
  701. $field = field_info_field($field_name);
  702. // For rows in the tables that aren't fields, just add an empty value
  703. // for the storage column.
  704. if (!$field) {
  705. $form['fields'][$field_name][] = array(
  706. '#markup' => '',
  707. );
  708. continue;
  709. }
  710. $storage_type = $field['storage']['type'];
  711. $storage_label = array_key_exists('label', $storage_info[$storage_type]) ? $storage_info[$storage_type]['label'] : '';
  712. if ($storage_type == 'field_sql_storage') {
  713. $storage_label = 'Drupal';
  714. }
  715. if (array_key_exists('logo_url', $storage_info[$storage_type])) {
  716. $logo_url = $storage_info[$storage_type]['logo_url'];
  717. $form['fields'][$field_name][] = array(
  718. '#markup' => '<img class="form-field-ui-field-overview-storage-logo" src="' . $logo_url . '">',
  719. );
  720. }
  721. else {
  722. $form['fields'][$field_name][] = array(
  723. '#markup' => $storage_label,
  724. );
  725. }
  726. }
  727. $form['note'] = array(
  728. '#markup' => '* Fields attached to this content type can use various
  729. storage backends. Please be sure when you add new fields that the
  730. storage backend is appropriate. For example, if you use Chado, and you
  731. want all biological content to be stored in Chado, be sure that the
  732. respective fields are "supported by" Chado.',
  733. );
  734. }
  735. /**
  736. * Implements hook_menu_alter().
  737. */
  738. function tripal_menu_alter(&$items) {
  739. // We don't want to allow deletion of fields added by the storage backend.
  740. // TODO: this shouldn't be hardcoded here. These settings
  741. // should be part of the field and handled by the tripal_entity module.
  742. $items['admin/structure/bio-data/manage/%TripalBundle/fields/%field_ui_menu/delete']['page callback'] = 'tripal_field_no_delete';
  743. $items['admin/structure/bio-data/manage/%TripalBundle/fields/%field_ui_menu/delete']['page arguments'] = array();
  744. }
  745. /**
  746. * Simple provides a message indicating that the field cannot be deleted.
  747. */
  748. function tripal_field_no_delete() {
  749. drupal_set_message('This field cannot be removed.', 'warning');
  750. return '';
  751. }
  752. /**
  753. * Imports all of the Tripal API into scope.
  754. *
  755. * Typically this function call is not necessary as all of the API is
  756. * automaticaly included by the tripal module. However this function can
  757. * be useful in the .install files during a site upgrade when the tripal
  758. * module is not enabld.
  759. *
  760. * Example usage:
  761. * @code
  762. * module_load_include('module', 'tripal', 'tripal');
  763. * tripal_import_api();
  764. * @endcode
  765. *
  766. */
  767. function tripal_import_api() {
  768. module_load_include('inc', 'tripal', 'api/tripal.d3js.api');
  769. module_load_include('inc', 'tripal', 'api/tripal.entities.api');
  770. module_load_include('inc', 'tripal', 'api/tripal.files.api');
  771. module_load_include('inc', 'tripal', 'api/tripal.jobs.api');
  772. module_load_include('inc', 'tripal', 'api/tripal.notice.api');
  773. module_load_include('inc', 'tripal', 'api/tripal.variables.api');
  774. }
  775. /**
  776. * Implements hook_field_storage_info().
  777. *
  778. * The Tripal module does not provide a storage back-end. But it does provide
  779. * a placeholder when no storage backend is needed but a field
  780. * is still desired. The 'tripal_no_storage' backend is used for the
  781. * content_type field which adds a type field to every entity.
  782. */
  783. function tripal_field_storage_info() {
  784. return array(
  785. 'tripal_no_storage' => array(
  786. 'label' => t('Tripal'),
  787. 'description' => t('The NULL storage is a placeholder for field values
  788. that are not stored in any storage backend (e.g. entity types).'),
  789. 'settings' => array(),
  790. ),
  791. );
  792. }
  793. /**
  794. * Implements hook_field_info().
  795. */
  796. function tripal_field_info() {
  797. $fields = array(
  798. 'content_type' => array(
  799. 'label' => t('Record Type'),
  800. 'description' => t('The content type.'),
  801. 'default_widget' => 'tripal_content_type_widget',
  802. 'default_formatter' => 'tripal_content_type_formatter',
  803. 'settings' => array(),
  804. 'storage' => array(
  805. 'type' => 'tripal_no_storage',
  806. 'module' => 'tripal',
  807. 'active' => TRUE
  808. ),
  809. ),
  810. );
  811. return $fields;
  812. }
  813. /**
  814. * Implements hook_field_widget_info();
  815. */
  816. function tripal_field_widget_info() {
  817. return array(
  818. 'tripal_content_type_widget' => array(
  819. 'label' => t('Record Type'),
  820. 'field types' => array('content_type')
  821. ),
  822. );
  823. }
  824. /**
  825. * Implements hook_field_formatter_info().
  826. */
  827. function tripal_field_formatter_info() {
  828. return array(
  829. 'tripal_content_type_formatter' => array(
  830. 'label' => t('Record Type'),
  831. 'field types' => array('content_type')
  832. ),
  833. );
  834. }
  835. /**
  836. * Implements hook_field_widget_form().
  837. */
  838. function tripal_field_widget_form(&$form, &$form_state, $field,
  839. $instance, $langcode, $items, $delta, $element) {
  840. $widget = $element;
  841. switch ($instance['widget']['type']) {
  842. case 'tripal_content_type_widget':
  843. // There is no widget for this type.
  844. break;
  845. }
  846. }
  847. /**
  848. * Implements hook_field_formatter_view().
  849. */
  850. function tripal_field_formatter_view($entity_type, $entity, $field,
  851. $instance, $langcode, $items, $display) {
  852. $element = array();
  853. switch ($display['type']) {
  854. case 'tripal_content_type_formatter':
  855. module_load_include('inc', 'tripal', 'includes/fields/content_type');
  856. tripal_content_type_formatter($element, $entity_type, $entity, $field,
  857. $instance, $langcode, $items, $display);
  858. break;
  859. }
  860. return $element;
  861. }
  862. /**
  863. * Implemenation of hook_add_bundle_fields().
  864. *
  865. * In this function we add the type field.
  866. */
  867. function tripal_add_bundle_fields($entity_type, $bundle, $term) {
  868. $field_name = 'content_type';
  869. $bundle_name = $bundle->name;
  870. // Create the field array.
  871. $field_info = array(
  872. 'field_type' => 'content_type',
  873. 'widget_type' => 'tripal_content_type_widget',
  874. 'widget_settings' => array('display_label' => 1),
  875. 'description' => '',
  876. 'label' => 'Record Type',
  877. 'is_required' => 0,
  878. 'storage' => 'tripal_no_storage',
  879. 'field_settings' => array(
  880. 'semantic_web' => array(
  881. // The type is the term from a vocabulary that desribes this field..
  882. 'type' => '',
  883. // The namepsace for the vocabulary (e.g. 'foaf').
  884. 'ns' => '',
  885. // The URL for the namespace. It must be that the type can be
  886. // appended to the URL.
  887. 'nsurl' => '',
  888. ),
  889. ),
  890. );
  891. tripal_add_bundle_field($field_name, $field_info, $entity_type, $bundle_name);
  892. }
  893. /**
  894. * Implements hook_field_storage_query().
  895. *
  896. * Used by EntityFieldQuery to find the entities having certain entity
  897. * and field conditions and sort them in the given field order.
  898. *
  899. * NOTE: This function needs to exist or errors are triggered but so far it doesn't
  900. * appear to actually need to do anything...
  901. */
  902. function tripal_field_storage_query($query) { }
  903. /**
  904. * Implements hook_field_storage_load().
  905. *
  906. * Responsible for loading the fields from the Chado database and adding
  907. * their values to the entity.
  908. */
  909. function tripal_field_storage_load($entity_type, $entities, $age,
  910. $fields, $options) {
  911. $load_current = $age == FIELD_LOAD_CURRENT;
  912. global $language;
  913. $langcode = $language->language;
  914. foreach ($entities as $id => $entity) {
  915. // Iterate through the entity's fields so we can get the column names
  916. // that need to be selected from each of the tables represented.
  917. $tables = array();
  918. foreach ($fields as $field_id => $ids) {
  919. // By the time this hook runs, the relevant field definitions have been
  920. // populated and cached in FieldInfo, so calling field_info_field_by_id()
  921. // on each field individually is more efficient than loading all fields in
  922. // memory upfront with field_info_field_by_ids().
  923. $field = field_info_field_by_id($field_id);
  924. $field_name = $field['field_name'];
  925. $field_type = $field['type'];
  926. $field_module = $field['module'];
  927. // Allow the creating module to alter the value if desired. The
  928. // module should do this if the field has any other form elements
  929. // that need populationg besides the default value.
  930. $load_function = $field_module . '_' . $field_type . '_field_load';
  931. module_load_include('inc', $field_module, 'includes/fields/' . $field_type);
  932. if (function_exists($load_function)) {
  933. $load_function($field, $entity);
  934. }
  935. } // end: foreach ($fields as $field_id => $ids) {
  936. } // end: foreach ($entities as $id => $entity) {
  937. }
  938. /**
  939. * Implements hook_field_is_empty().
  940. */
  941. function tripal_field_is_empty($item, $field) {
  942. // If there is no value field then the field is empty.
  943. if (!array_key_exists('value', $item)) {
  944. return TRUE;
  945. }
  946. // Iterate through all of the fields and if at least one has a value
  947. // the field is not empty.
  948. foreach ($item as $form_field_name => $value) {
  949. if (isset($value) and $value != NULL and $value != '') {
  950. return FALSE;
  951. }
  952. }
  953. // Otherwise, the field is empty.
  954. return TRUE;
  955. }