tripal.fields.api.inc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. <?php
  2. /**
  3. * Executes a TripalFieldQuery using the provided conditions.
  4. *
  5. * This hook is called to find the entities having certain field
  6. * conditions and sort them in the given field order.
  7. *
  8. * @param $conditions
  9. * An array of filter representing the conditions to be applied to the query.
  10. * Each filter is an associative array whose keys include the following:
  11. * - field: an array representing the field identical to the output of the
  12. * field_info_field() function.
  13. * - filter: the name of the field on which the filter should be applied.
  14. * - value: the value of the filter.
  15. * - operator: the operation to apply: '=', '<>', '>', '>=', '<', '<=',
  16. * 'STARTS_WITH', 'CONTAINS': These operators expect $value to be a
  17. * literal of the same type as the column. 'IN', 'NOT IN': These operators
  18. * expect $value to be an array of literals of the same type as the column.
  19. * @param $orderBy
  20. * An array of sorting instructions. Each sort is an associative array with
  21. * the following keys:
  22. * - field: an array representing the field identical to the output of the
  23. * field_info_field() function.
  24. * - orderBy: the name of the field on which the filter should be applied.
  25. * - direction: either the string 'ASC' (for ascending sort) or 'DESC' (for
  26. * descending).
  27. */
  28. function hook_field_storage_tquery($conditions, $orderBy) {
  29. // See the tripal_chado_field_storage_tquery() function for an example.
  30. }
  31. function hook_bundle_fields_info($entity_type, $bundle) {
  32. }
  33. function hook_bundle_instances_info($entity_type, $bundle) {
  34. }
  35. function hook_bundle_fields_info_alter(&$info, $bundle, $term) {
  36. }
  37. function hook_bundle_instances_info_alter(&$info, $bundle, $term) {
  38. }
  39. /**
  40. * Retrieves a list of TripalField types.
  41. *
  42. * The TripalField classes can be added by a site developer and should be
  43. * placed in the [module]/includes/TripalFields directory. Tripal will support
  44. * any field as long as it is in this directory and extends the TripalField
  45. * class. To support dynamic inclusion of new fields this function
  46. * will look for TripalField class files and return a type for
  47. * each one.
  48. *
  49. * @return
  50. * A list of TripalField names.
  51. */
  52. function tripal_get_field_types() {
  53. $types = array();
  54. $modules = module_list(TRUE);
  55. foreach ($modules as $module) {
  56. // Only run this for modules that are enabled.
  57. if (!module_exists($module)) {
  58. continue;
  59. }
  60. // Find all of the files in the tripal_chado/includes/TripalFields/ directory.
  61. $fields_path = drupal_get_path('module', $module) . '/includes/TripalFields';
  62. $field_files = file_scan_directory($fields_path, '/.*\.inc$/');
  63. // Iterate through the fields, include the file and run the info function.
  64. foreach ($field_files as $file) {
  65. // Ignore the formatter and widget classes for now.
  66. if (preg_match('/_formatter|_widget/', $file->name)) {
  67. continue;
  68. }
  69. $field_type = $file->name;
  70. module_load_include('inc', $module, 'includes/TripalFields/' . $field_type . '/' . $field_type);
  71. if (class_exists($field_type) and is_subclass_of($field_type, 'TripalField')) {
  72. $types[] = $field_type;
  73. }
  74. }
  75. }
  76. // If the libraries module is enabled then we want to look for a TripalFields
  77. // library folder and see if our field exist there.
  78. if (module_exists('libraries')) {
  79. $library_path = libraries_get_path('TripalFields');
  80. $fields_path = realpath(".") . '/' . $library_path;
  81. $field_files = file_scan_directory($fields_path, '/.*\.inc$/');
  82. foreach ($field_files as $file) {
  83. // Ignore the formatter and widget classes for now.
  84. if (preg_match('/_formatter|_widget/', $file->name)) {
  85. continue;
  86. }
  87. $field_type = $file->name;
  88. $file_path = realpath(".") . '/' . $library_path .'/' . $field_type . '/' . $field_type . '.inc';
  89. if (file_exists($file_path)) {
  90. require_once($file_path);
  91. if (class_exists($field_type) and is_subclass_of($field_type, 'TripalField')) {
  92. $types[] = $field_type;
  93. }
  94. }
  95. }
  96. }
  97. return $types;
  98. }
  99. /**
  100. * Retrieves a list of TripalFieldWidgets.
  101. *
  102. * The TripalFieldWidget classes can be added by a site developer and should be
  103. * placed in the [module]/includes/TripalFields directory. Tripal will support
  104. * any widget as long as it is in this directory and extends the
  105. * TripalFieldWidget class.
  106. *
  107. * @return
  108. * A list of TripalFieldWidget names.
  109. */
  110. function tripal_get_field_widgets() {
  111. $widgets = array();
  112. $modules = module_list(TRUE);
  113. foreach ($modules as $module) {
  114. // Only run this for modules that are enabled.
  115. if (!module_exists($module)) {
  116. continue;
  117. }
  118. // Find all of the files in the tripal_chado/includes/fields directory.
  119. $fields_path = drupal_get_path('module', $module) . '/includes/TripalFields';
  120. $field_files = file_scan_directory($fields_path, '/.*_widget\.inc$/');
  121. // Iterate through the fields, include the file and run the info function.
  122. foreach ($field_files as $file) {
  123. $widget_type = $file->name;
  124. $field_type = preg_replace('/(^.*)_widget/', '$1', $widget_type);
  125. module_load_include('inc', $module, 'includes/TripalFields/' . $field_type . '/' . $widget_type);
  126. if (class_exists($widget_type) and is_subclass_of($widget_type, 'TripalFieldWidget')) {
  127. $widgets[] = $widget_type;
  128. }
  129. }
  130. }
  131. // If the libraries module is enabled then we want to look for a TripalFields
  132. // library folder and see if our field exist there.
  133. if (module_exists('libraries')) {
  134. $library_path = libraries_get_path('TripalFields');
  135. $fields_path = realpath(".") . '/' . $library_path;
  136. $field_files = file_scan_directory($fields_path, '/.*_widget\.inc$/');
  137. foreach ($field_files as $file) {
  138. $widget_type = $file->name;
  139. $field_type = preg_replace('/(^.*)_widget/', '$1', $widget_type);
  140. $file_path = realpath(".") . '/' . $library_path .'/' . $field_type . '/' . $widget_type . '.inc';
  141. if (file_exists($file_path)) {
  142. require_once($file_path);
  143. if (class_exists($widget_type) and is_subclass_of($widget_type, 'TripalFieldWidget')) {
  144. $widgets[] = $widget_type;
  145. }
  146. }
  147. }
  148. }
  149. return $widgets;
  150. }
  151. /**
  152. * Retrieves a list of field formatters compatible with a given field.
  153. * @param unknown $field
  154. */
  155. function tripal_get_field_field_formatters($field) {
  156. $field_name = $field['field_name'];
  157. $field_type = $field['type'];
  158. $field_module = $field['module'];
  159. $downloaders = array();
  160. // All fields should support the Tab and CSV downloaders.
  161. tripal_load_include_downloader_class('TripalTabDownloader');
  162. $downloaders['TripalTabDownloader'] = TripalTabDownloader::$label;
  163. tripal_load_include_downloader_class('TripalCSVDownloader');
  164. $downloaders['TripalCSVDownloader'] = TripalCSVDownloader::$label;
  165. if (tripal_load_include_field_class($field_type)) {
  166. $settings = $field_type::$default_instance_settings;
  167. if (array_key_exists('download_formatters', $settings)) {
  168. foreach ($settings['download_formatters'] as $class_name) {
  169. if (!array_key_exists($class_name, $downloaders)) {
  170. tripal_load_include_downloader_class($class_name);
  171. $downloaders[$class_name] = $class_name::$label;
  172. }
  173. }
  174. }
  175. }
  176. return $downloaders;
  177. }
  178. /**
  179. * Retrieves a list of all the TripalFieldFormatters available on this site.
  180. *
  181. * The TripalFieldFormatter classes can be added by a site developer and should
  182. * be placed in the [module]/includes/TripalFields directory. Tripal will
  183. * support any widget as long as it is in this directory and extends the
  184. * TripalFieldFormatter class.
  185. *
  186. * @return
  187. * A list of TripalFieldFormatter names.
  188. */
  189. function tripal_get_field_formatters() {
  190. $formatters = array();
  191. $modules = module_list(TRUE);
  192. foreach ($modules as $module) {
  193. // Only run this for modules that are enabled.
  194. if (!module_exists($module)) {
  195. continue;
  196. }
  197. // Find all of the files in the tripal_chado/includes/fields directory.
  198. $fields_path = drupal_get_path('module', $module) . '/includes/TripalFields';
  199. $field_files = file_scan_directory($fields_path, '/.*_formatter\.inc$/');
  200. // Iterate through the fields, include the file and run the info function.
  201. foreach ($field_files as $file) {
  202. $formatter_type = $file->name;
  203. $field_type = preg_replace('/(^.*)_formatter/', '$1', $formatter_type);
  204. module_load_include('inc', $module, 'includes/TripalFields/' . $field_type . '/' . $formatter_type);
  205. if (class_exists($formatter_type) and is_subclass_of($formatter_type, 'TripalFieldFormatter')) {
  206. $formatters[] = $formatter_type;
  207. }
  208. }
  209. }
  210. // If the libraries module is enabled then we want to look for a TripalFields
  211. // library folder and see if our field exist there.
  212. if (module_exists('libraries')) {
  213. $library_path = libraries_get_path('TripalFields');
  214. $fields_path = realpath(".") . '/' . $library_path;
  215. $field_files = file_scan_directory($fields_path, '/.*_formatter\.inc$/');
  216. foreach ($field_files as $file) {
  217. $formatter_type = $file->name;
  218. $field_type = preg_replace('/(^.*)_formatter/', '$1', $formatter_type);
  219. $file_path = realpath(".") . '/' . $library_path .'/' . $field_type . '/' . $formatter_type . '.inc';
  220. if (file_exists($file_path)) {
  221. require_once($file_path);
  222. if (class_exists($formatter_type) and is_subclass_of($formatter_type, 'TripalFieldFormatter')) {
  223. $formatters[] = $formatter_type;
  224. }
  225. }
  226. }
  227. }
  228. return $formatters;
  229. }
  230. /**
  231. * Loads the TripalField class file into scope.
  232. *
  233. * @param $class
  234. * The class to include. This can be a TripalField, TripalFieldWidget or
  235. * TripalFieldFormatter class name.
  236. *
  237. * @return
  238. * TRUE if the field type class file was found, FALSE otherwise.
  239. */
  240. function tripal_load_include_field_class($class) {
  241. $modules = module_list(TRUE);
  242. foreach ($modules as $module) {
  243. $field_type = preg_replace('/(^.*)_(formatter|widget)/', '$1', $class);
  244. $file_path = realpath(".") . '/' . drupal_get_path('module', $module) . '/includes/TripalFields/' . $field_type . '/' . $class . '.inc';
  245. if (file_exists($file_path)) {
  246. module_load_include('inc', $module, 'includes/TripalFields/' . $field_type . '/' . $class);
  247. if (class_exists($class)) {
  248. return TRUE;
  249. }
  250. }
  251. }
  252. // If the libraries module is enabled then we want to look for a TripalFields
  253. // library folder and see if our field exist there.
  254. if (module_exists('libraries')) {
  255. $library_path = libraries_get_path('TripalFields');
  256. $field_type = preg_replace('/(^.*)_(formatter|widget)/', '$1', $class);
  257. $file_path = realpath(".") . '/' . $library_path .'/' . $field_type . '/' . $class . '.inc';
  258. if (file_exists($file_path)) {
  259. require_once($file_path);
  260. if (class_exists($class)) {
  261. return TRUE;
  262. }
  263. }
  264. }
  265. return FALSE;
  266. }
  267. /**
  268. * Loads the TripalEntityDownloader file into scope.
  269. *
  270. * @param $class
  271. * The name of the class to include.
  272. *
  273. * @return
  274. * TRUE if the downloader class file was found, FALSE otherwise.
  275. */
  276. function tripal_load_include_downloader_class($class) {
  277. $modules = module_list(TRUE);
  278. foreach ($modules as $module) {
  279. $file_path = realpath(".") . '/' . drupal_get_path('module', $module) . '/includes/TripalFieldDownloaders/' . $class . '.inc';
  280. if (file_exists($file_path)) {
  281. module_load_include('inc', $module, 'includes/TripalFieldDownloaders/' . $class);
  282. if (class_exists($class)) {
  283. return TRUE;
  284. }
  285. }
  286. }
  287. // If the libraries module is enabled then we want to look for a
  288. // TripalFieldDownloader library folder and see if our field exist there.
  289. if (module_exists('libraries')) {
  290. $library_path = libraries_get_path('TripalFieldDownloaders');
  291. $file_path = realpath(".") . '/' . $library_path .'/' . $class . '.inc';
  292. if (file_exists($file_path)) {
  293. require_once($file_path);
  294. if (class_exists($class)) {
  295. return TRUE;
  296. }
  297. }
  298. }
  299. return FALSE;
  300. }
  301. /**
  302. * More easily get the value of a single item from a field's items array.
  303. *
  304. * A Drupal field attached to an entity may have multiple items (i.e. it has
  305. * a cardinality > 1). Each of these items will always have a 'value' key that
  306. * contains the data for that field. However, fields can also have other keys
  307. * with their own values. You can easily retreive the value of these keys
  308. * using this function. What makes this function useful is that you can
  309. * provide a default value to use if the key has no value. This is useful
  310. * when developing a TripalField::widgetForm function and you need to
  311. * retreive default values and you don't want to have to always check if the
  312. * value is set.
  313. *
  314. * @param $items
  315. * The fields $items array. Compatbile with that returned by field_get_items.
  316. * @param $delta
  317. * The index of the item.
  318. * @parm $key
  319. * The name of the key within the item.
  320. * @param $default
  321. * A default value to return if the key is not set. By default the empty
  322. * string is returned.
  323. *
  324. * @return
  325. * The value assigned to the item's key; FALSE if the key doesn't exist or
  326. * the $default argument if no value is associated with the key.
  327. */
  328. function tripal_get_field_item_keyval($items, $delta, $key, $default='') {
  329. if (!array_key_exists($delta, $items)) {
  330. return FALSE;
  331. }
  332. if (!array_key_exists($key, $items[$delta])) {
  333. return FALSE;
  334. }
  335. if (!$items[$delta][$key]) {
  336. return $default;
  337. }
  338. return $items[$delta][$key];
  339. }
  340. /**
  341. * Formats an element of a TripalField for use by Drupal Views.
  342. *
  343. * Sometimes the value of TripalField can be more than just a single scalar. In
  344. * this case the value is an array of key value pairs where each key is a
  345. * controlled vocabulary term. In order to support fields, filtering and
  346. * sorting by these sub elements using Drupal Views, the TripalField
  347. * implementation must provide some help to Views by describing these elements,
  348. * and then implementing a query() function to support them. However, the
  349. * naming of sub elements must follow a set convention. This function
  350. * guarantees proper naming for sub elements.
  351. *
  352. * @param $field_name
  353. * The name of the field to which the element belongs.
  354. * @param $term
  355. * The term object as returned by tripal_get_term_details();
  356. */
  357. function tripal_format_views_field_element($field_name, $term) {
  358. $element_name = $term['vocabulary']['short_name'] . '__' . $term['accession'];
  359. return $field_name . '.' . $element_name;
  360. }