TripalField.inc 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736
  1. <?php
  2. class TripalField {
  3. // --------------------------------------------------------------------------
  4. // EDITABLE STATIC CONSTANTS
  5. //
  6. // The following constants SHOULD be set for each descendent class. They are
  7. // used by the static functions to provide information to Drupal about
  8. // the field and it's default widget and formatter.
  9. // --------------------------------------------------------------------------
  10. // The default lable for this field.
  11. public static $default_label = 'Tripal Field';
  12. // The default description for this field.
  13. public static $default_description = 'The generic base class for all Tripal fields. Replace this text as appropriate for the child implementation.';
  14. // Provide a list of global settings. These can be accessed witihn the
  15. // globalSettingsForm. When the globalSettingsForm is submitted then
  16. // Drupal will automatically change these settings for all fields.
  17. // Once instances exist for a field type then these settings cannot be
  18. // changed.
  19. public static $default_settings = array(
  20. 'storage' => 'tripal_no_storage',
  21. // It is expected that all fields set a 'value' in the load() function.
  22. // In many cases, the value may be an associative array of key/value pairs.
  23. // In order for Tripal to provide context for all data, the keys should
  24. // be a controlled vocabulary term (e.g. rdfs:type). Keys in the load()
  25. // function that are supported by the query() function should be
  26. // listed here.
  27. 'searchable_keys' => array(),
  28. );
  29. // Provide a list of instance specific settings. These can be access within
  30. // the instanceSettingsForm. When the instanceSettingsForm is submitted
  31. // then Drupal with automatically change these settings for the instnace.
  32. // It is recommended to put settings at the instance level whenever possible.
  33. // If you override this variable in a child class be sure to replicate the
  34. // term_name, term_vocab, term_accession and term_fixed keys as these are
  35. // required for all TripalFields.
  36. public static $default_instance_settings = array(
  37. // The short name for the vocabulary (e.g. shcema, SO, GO, PATO, etc.).
  38. 'term_vocabulary' => 'schema',
  39. // The name of the term.
  40. 'term_name' => 'Thing',
  41. // The unique ID (i.e. accession) of the term.
  42. 'term_accession' => 'Thing',
  43. // Set to TRUE if the site admin is not allowed to change the term
  44. // type, otherwise the admin can change the term mapped to a field.
  45. 'term_fixed' => FALSE,
  46. // Indicates the download formats for this field. The list must be the
  47. // name of a child class of the TripalFieldDownloader.
  48. 'download_formatters' => array(
  49. 'TripalTabDownloader',
  50. 'TripalCSVDownloader',
  51. ),
  52. );
  53. // The default widget for this field.
  54. public static $default_widget = '';
  55. // The default formatter for this field.
  56. public static $default_formatter = '';
  57. // The module that manages this field.
  58. public static $module = 'tripal';
  59. // A boolean specifying that users should not be allowed to create
  60. // fields and instances of this field type through the UI. Such
  61. // fields can only be created programmatically with field_create_field()
  62. // and field_create_instance().
  63. public static $no_ui = TRUE;
  64. // A boolean specifying that the field will not contain any data. This
  65. // should exclude the field from web serivces or downloads. An example
  66. // could be a quick search field that appears on the page that redirects
  67. // the user but otherwise provides no data.
  68. public static $no_data = FALSE;
  69. // --------------------------------------------------------------------------
  70. // PROTECTED CLASS MEMBERS -- DO NOT OVERRIDE
  71. // --------------------------------------------------------------------------
  72. // An array containing details about the field. The format of this array
  73. // is the same as that returned by field_info_fields()
  74. protected $field;
  75. // An array containing details about an instance of the field. A field does
  76. // not have to have an instance. But if dealing with an instance (such as
  77. // when using the widgetForm, formatterSettingsForm, etc.) it should be set.
  78. protected $instance;
  79. // The term array that provides all the details about the controlled
  80. // vocabulary term that this field maps to.
  81. protected $term;
  82. // --------------------------------------------------------------------------
  83. // CONSTRUCTOR
  84. // --------------------------------------------------------------------------
  85. /**
  86. * Instantiates a new TripalField object.
  87. *
  88. * @param $field
  89. * An array containing the field data as returned by field_info_field().
  90. * @param $instance
  91. * An array containing the instance data as returned by field_instance_info().
  92. */
  93. public function __construct($field, $instance) {
  94. $term = NULL;
  95. $vocabulary = NULL;
  96. $accession = NULL;
  97. $this->field = $field;
  98. $this->instance = $instance;
  99. $class = get_called_class();
  100. // Use the term info defined in the class by default (assuming it's not schema:Thing ;-).
  101. if ($class::$default_instance_settings['term_name'] != 'Thing') {
  102. $vocabulary = $class::$default_instance_settings['term_vocabulary'];
  103. $accession = $class::$default_instance_settings['term_accession'];
  104. }
  105. // Allow the constructor to override the term info.
  106. $vocabulary = isset($this->instance['settings']['term_vocabulary']) ? $this->instance['settings']['term_vocabulary'] : $vocabulary;
  107. $accession = isset($this->instance['settings']['term_accession']) ? $this->instance['settings']['term_accession'] : $accession;
  108. // Assuming we have term info, load the term.
  109. if (!empty($vocabulary) AND !empty($accession)) {
  110. $this->term = tripal_get_term_details($vocabulary, $accession);
  111. }
  112. else {
  113. tripal_report_error('tripal_field', TRIPAL_ERROR, 'Unable to instantiate Field :name due to missing vocabulary and/or accession.',
  114. array(':name' => $class::$default_label));
  115. }
  116. if (!$instance) {
  117. tripal_set_message(t('Missing instance of field "%field"', array('%field' => $field['field_name'])), TRIPAL_ERROR);
  118. }
  119. }
  120. // --------------------------------------------------------------------------
  121. // STATIC INFO FUNCTIONS -- DO NOT OVERRIDE
  122. // --------------------------------------------------------------------------
  123. /**
  124. * Provides default information about this field type
  125. *
  126. * This function corresponds to the hook_field_info() function of
  127. * the Drupal Field API.
  128. *
  129. * @return
  130. * An array whose keys are field type names and whose values are arrays
  131. * describing the field type. The keys are the same as for the
  132. * hook_field_info() function.
  133. */
  134. public static function info() {
  135. $class = get_called_class();
  136. $info = array(
  137. 'label' => $class::$default_label,
  138. 'description' => $class::$default_description,
  139. 'settings' => $class::$default_settings,
  140. 'instance_settings' => $class::$default_instance_settings,
  141. 'default_widget' => $class::$default_widget,
  142. 'default_formatter' => $class::$default_formatter,
  143. 'no_ui' => $class::$no_ui,
  144. );
  145. return $info;
  146. }
  147. // --------------------------------------------------------------------------
  148. // DO NOT OVERRIDE THESE FUNCTIONS
  149. // --------------------------------------------------------------------------
  150. /**
  151. * Retrives the name of this field.
  152. *
  153. * @return
  154. * This field's name.
  155. */
  156. public function getFieldName() {
  157. return $this->field['field_name'];
  158. }
  159. public function getField() {
  160. return $this->field;
  161. }
  162. public function getInstance() {
  163. return $this->instance;
  164. }
  165. /**
  166. * When constructing a pager for use by a field, all pagers must have
  167. * a unique ID
  168. */
  169. protected function getPagerElementID() {
  170. return $this->field['id'];
  171. }
  172. public function getFieldTerm(){
  173. return $this->term;
  174. }
  175. public function getFieldTermID() {
  176. $class = get_called_class();
  177. return $this->instance['settings']['term_vocabulary'] . ':' . $this->instance['settings']['term_accession'];
  178. }
  179. /**
  180. * Describes this field to Tripal web services.
  181. *
  182. * The child class need not implement this function. It has all of the details
  183. * provided for elements by the elementInfo() function are used to generate
  184. * the details needed for Views.
  185. *
  186. * @return
  187. * An associative array with the keys available for searching. The value
  188. * is the term array for the element.
  189. */
  190. public function webServicesData() {
  191. $elements = $this->elementInfo();
  192. $field_term = $this->getFieldTermID();
  193. $field_term_name = strtolower(preg_replace('/[^\w]/', '_', $this->term['name']));
  194. $field_details = $elements[$field_term];
  195. $searchable_keys = array();
  196. $sortable_keys = array();
  197. if (array_key_exists('searchable', $field_details) and $field_details['searchable']) {
  198. $searchable_keys[$field_term_name] = $field_term;
  199. }
  200. if (array_key_exists('sortable', $field_details) and $field_details['sortable']) {
  201. $sortable_keys[$field_term_name] = $field_term;
  202. }
  203. // Now add any entries for child elements.
  204. if (array_key_exists('elements', $field_details)) {
  205. $elements = $field_details['elements'];
  206. foreach ($elements as $element_name => $element_details) {
  207. $this->_addWebServiceElement($searchable_keys, $sortable_keys, $field_term_name, $field_term, $element_name, $element_details);
  208. }
  209. }
  210. return array(
  211. 'searchable' => $searchable_keys,
  212. 'sortable' => $sortable_keys
  213. );
  214. }
  215. /**
  216. *
  217. * @param $searchabe_keys
  218. * @param $field_name
  219. * @param $element_name
  220. * @param $element_details
  221. */
  222. protected function _addWebServiceElement(&$searchable_keys, &$sortable_keys,
  223. $parent_term_name, $parent_term, $element_name, $element_details) {
  224. // Skip the 'entity' element, as we'll never make this searchable or
  225. // viewable. It's meant for linking.
  226. if ($element_name == 'entity') {
  227. return;
  228. }
  229. list($vocabulary, $accession) = explode(':', $element_name);
  230. $term = tripal_get_term_details($vocabulary, $accession);
  231. $field_term = $parent_term . ',' . $term['vocabulary']['short_name'] . ':' . $term['accession'];
  232. $field_term_name = $parent_term_name . '.' . strtolower(preg_replace('/[^\w]/', '_', $term['name']));
  233. // Is the field searchable?
  234. if (array_key_exists('searchable', $element_details) and $element_details['searchable']) {
  235. $searchable_keys[$field_term_name] = $field_term;
  236. }
  237. if (array_key_exists('sortable', $element_details) and $element_details['sortable']) {
  238. $sortable_keys[$field_term_name] = $field_term;
  239. }
  240. // Now add any entries for child elements.
  241. if (array_key_exists('elements', $element_details)) {
  242. $elements = $element_details['elements'];
  243. foreach ($elements as $element_name => $element_details) {
  244. $this->_addWebServiceElement($searchable_keys, $sortable_keys, $field_term_name, $field_term, $element_name, $element_details);
  245. }
  246. }
  247. }
  248. /**
  249. * Describes this field to Views.
  250. *
  251. * The child class need not implement this function has all of the details
  252. * provided for elements by the elementInfo() function are used to generate
  253. * the details needed for Views.
  254. *
  255. * @param $view_base_id
  256. * Views was originally designed to integrate with SQL tables. And
  257. * each field is associated with a table. Because these are TripalFields
  258. * and views is not directly querying the tables it doesn't make sense to
  259. * associate fields with a table, but we must associate the fields with
  260. * the bundle. Each bundle is uniquely identified with the $view_base_id
  261. * that is passed here.
  262. *
  263. * @return
  264. * An associative array describing the data structure. Primary key is the
  265. * name used internally by Views for the bundle that is provided by
  266. * the $view_base_id. The returned array should be compatible with the
  267. * instructions provided by the hook_views_data() function.
  268. */
  269. public function viewsData($view_base_id) {
  270. $data = array();
  271. $field_name = $this->field['field_name'];
  272. $field_term = $this->getFieldTermID();
  273. $elements = $this->elementInfo();
  274. $field_details = $elements[$field_term];
  275. // Get any titles or help text that is overriden.
  276. $title = ucfirst($this->instance['label']);
  277. if (array_key_exists('label', $field_details)) {
  278. $title = $field_details['label'];
  279. }
  280. $help = $this->instance['description'];
  281. if (array_key_exists('help', $field_details)) {
  282. $help = $field_details['help'];
  283. }
  284. // Build the entry for the field.
  285. $data[$view_base_id][$field_name] = array(
  286. 'title' => $title,
  287. 'help' => $help,
  288. 'field' => array(
  289. 'handler' => 'tripal_views_handler_field',
  290. 'click sortable' => TRUE,
  291. ),
  292. );
  293. // Is the field sortable?
  294. if (array_key_exists('sortable', $field_details) and $field_details['sortable']) {
  295. $data[$view_base_id][$field_name]['sort']['handler'] = 'tripal_views_handler_sort';
  296. }
  297. // Is the field searchable?
  298. if (array_key_exists('searchable', $field_details) and $field_details['searchable']) {
  299. $filter_handler = 'tripal_views_handler_filter_string';
  300. if (array_key_exists('type', $field_details) and $field_details['type'] == 'numeric') {
  301. $filter_handler = 'tripal_views_handler_filter_numeric';
  302. }
  303. $data[$view_base_id][$field_name]['filter'] = array(
  304. 'handler' => $filter_handler,
  305. );
  306. }
  307. // Now add any entries for child elements.
  308. if (array_key_exists('elements', $field_details)) {
  309. $elements = $field_details['elements'];
  310. foreach ($elements as $element_name => $element_details) {
  311. $this->_addViewsDataElement($data, $view_base_id, $field_name, $element_name, $element_details);
  312. }
  313. }
  314. return $data;
  315. }
  316. /**
  317. *
  318. * @param unknown $data
  319. * @param unknown $view_base_id
  320. * @param unknown $parent
  321. * @param unknown $element_name
  322. * @param unknown $element_details
  323. */
  324. protected function _addViewsDataElement(&$data, $view_base_id, $parent, $element_name, $element_details) {
  325. // Skip the 'entity' element, as we'll never make this searchable or
  326. // viewable. It's meant for linking.
  327. if ($element_name == 'entity') {
  328. return;
  329. }
  330. if (!preg_match('/:/', $element_name)) {
  331. return;
  332. }
  333. $field_name = $parent . '.' . $element_name;
  334. list($vocabulary, $accession) = explode(':', $element_name);
  335. $term = tripal_get_term_details($vocabulary, $accession);
  336. // Get any titles or help text that is overriden.
  337. $title = ucfirst($term['name']);
  338. if (array_key_exists('label', $element_details)) {
  339. $title = $element_details['label'];
  340. }
  341. $help = $term['definition'];
  342. if (array_key_exists('help', $element_details)) {
  343. $help = $element_details['help'];
  344. }
  345. // Build the entry for the field.
  346. $data[$view_base_id][$field_name] = array(
  347. 'title' => $title,
  348. 'help' => $help,
  349. 'field' => array(
  350. 'handler' => 'tripal_views_handler_field_element',
  351. ),
  352. );
  353. // Is the field sortable?
  354. if (array_key_exists('sortable', $element_details) and $element_details['sortable']) {
  355. $data[$view_base_id][$field_name]['sort']['handler'] = 'tripal_views_handler_sort';
  356. $data[$view_base_id][$field_name]['field']['click sortable'] = TRUE;
  357. }
  358. // Is the field searchable?
  359. if (array_key_exists('searchable', $element_details) and $element_details['searchable']) {
  360. $filter_handler = 'tripal_views_handler_filter_element_string';
  361. if (array_key_exists('type', $element_details) and $element_details['type'] == 'numeric') {
  362. $filter_handler = 'tripal_views_handler_filter_numeric';
  363. }
  364. $data[$view_base_id][$field_name]['filter'] = array(
  365. 'handler' => $filter_handler,
  366. );
  367. }
  368. // Recusrively add any entries for child elements.
  369. if (array_key_exists('elements', $element_details)) {
  370. $elements = $element_details['elements'];
  371. foreach ($elements as $element_name => $element_details) {
  372. $this->_addViewsDataElement($data, $view_base_id, $field_name, $element_name, $element_details);
  373. }
  374. }
  375. }
  376. // --------------------------------------------------------------------------
  377. // OVERRIDEABLE FUNCTIONS
  378. // --------------------------------------------------------------------------
  379. /**
  380. * Perform validation of the field regardless how it is updated.
  381. *
  382. * Any errors encountered should be indicated by adding a value to the
  383. * $errors array according to the instructions below.
  384. *
  385. * @param $entity_type
  386. * The type of $entity.
  387. * @param $entity
  388. * The entity for the operation.
  389. * @param $langcode
  390. * The language associated with $items.
  391. * @param $items
  392. * $entity->{$field['field_name']}[$langcode], or an empty array if unset.
  393. * @param $errors
  394. * The array of errors (keyed by field name, language code, and delta) that
  395. * have already been reported for the entity. The function should add its
  396. * errors to this array. Each error is an associative array with the
  397. * following keys and values:
  398. * - error: An error code (should be a string prefixed with the
  399. * module name).
  400. * - message: The human readable message to be displayed.
  401. *
  402. */
  403. public function validate($entity_type, $entity, $langcode, $items, &$errors) {
  404. }
  405. /**
  406. * Loads the field values from the underlying data store.
  407. *
  408. * @param $entity
  409. *
  410. * @return
  411. * An array of the following format:
  412. * $entity->{$field_name}['und'][0]['value'] = $value;
  413. * where:
  414. * - $entity is the entity object to which this field is attached.
  415. * - $field_name is the name of this field
  416. * - 'und' is the language code (in this case 'und' == undefined)
  417. * - 0 is the cardinality. Increment by 1 when more than one item is
  418. * available.
  419. * - 'value' is the key indicating the value of this field. It should
  420. * always be set. The value of the 'value' key will be the contents
  421. * used for web services and for downloadable content. The value
  422. * should be of the follow format types: 1) A single value (text,
  423. * numeric, etc.) 2) An array of key value pair. 3) If multiple entries
  424. * then cardinality should incremented and format types 1 and 2 should
  425. * be used for each item.
  426. * The array may contain as many other keys at the same level as 'value'
  427. * but those keys are for internal field use and are not considered the
  428. * value of the field.
  429. *
  430. *
  431. */
  432. public function load($entity) {
  433. }
  434. /**
  435. * Provides the list of elements returned by the 'value' of the field.
  436. *
  437. * The elements provided by this function are used to integrate with
  438. * Drupal Views and Web services. The return value is an associative array
  439. * that contains all of the elements that will be returned by the
  440. * 'value' of this field. If the value field returns an element which
  441. * is not defined here a warning will be generated.
  442. *
  443. * The array structure should contain at the top-level a key of the form
  444. * {db}:{accession}. This represents the term that this field belongs to.
  445. * The value of this top-level key is an array with the following keys:
  446. * -name: this key is not actually used but is availble to improve
  447. * readability of the array. Because the key is a vocabulary term
  448. * conaining only the accession it's not always clear what it means.
  449. * Providing a 'name' key helps other's know what the term is.
  450. * -searchable: TRUE if the element can be used for filtering the content
  451. * type to which tis field is attached. FALSE if not.
  452. * -operations: an array of filtering operations that can be used for this
  453. * field. These include: 'eq', 'ne', 'contains', 'starts', 'gt', 'lt',
  454. * 'gte', 'lte'. These opertaions are applicable to strings: 'eq', 'ne',
  455. * 'contains', and 'starts'. These operations are applicable for numeric
  456. * values: 'gt', 'lt', 'gte', 'lte'.
  457. * -label: The label (if applicable) to appear for the elmeent. The default
  458. * is to use the term's name.
  459. * -help: Help text (if applicable) to appear for the element. The default
  460. * is to use the term's definition.
  461. * -type: The data type: e.g. 'string' or 'numeric'. Default is 'string'.
  462. * -sortable: TRUE if the element can be sorted. FALSE if not.
  463. * -elements: If this field value is a simple scalar (i.e. string or
  464. * number) then this key is not needed. But, if the 'value' of the
  465. * field is an array with sub keys then those subkeys must be defined
  466. * using this key. The members of the element array follows the same
  467. * format as the top-level key and the above subkeys can be used as well.
  468. *
  469. * The following code provides an example for describing the value elements
  470. * of this field. The Tripal Chado module provides an obi__organism field
  471. * that attaches organism details to content types such as genes, mRNA,
  472. * stocks, etc. It provides a label containing the full scientific name of
  473. * the organism as well as the genus, species, infraspecific name,
  474. * and infraspecific type. If the organism to which the field belong is
  475. * published then an entity ID is provided. The following array describes
  476. * all of these.
  477. * @code
  478. $field_term = $this->getFieldTermID();
  479. return array(
  480. $field_term => array(
  481. 'operations' => array('eq', 'contains', 'starts'),
  482. 'sortable' => TRUE,
  483. 'searchable' => TRUE,
  484. 'elements' => array(
  485. 'rdfs:label' => array(
  486. 'searchable' => TRUE,
  487. 'name' => 'scientific_name',
  488. 'operations' => array('eq', 'ne', 'contains', 'starts'),
  489. 'sortable' => TRUE,
  490. ),
  491. 'TAXRANK:0000005' => array(
  492. 'searchable' => TRUE,
  493. 'name' => 'genus',
  494. 'operations' => array('eq', 'ne', 'contains', 'starts'),
  495. 'sortable' => TRUE,
  496. ),
  497. 'TAXRANK:0000006' => array(
  498. 'searchable' => TRUE,
  499. 'name' => 'species',
  500. 'operations' => array('eq', 'ne', 'contains', 'starts'),
  501. 'sortable' => TRUE,
  502. ),
  503. 'TAXRANK:0000045' => array(
  504. 'searchable' => TRUE,
  505. 'name' => 'infraspecies',
  506. 'operations' => array('eq', 'ne', 'contains', 'starts'),
  507. 'sortable' => TRUE,
  508. ),
  509. 'local:infraspecific_type' => array(
  510. 'searchable' => TRUE,
  511. 'name' => 'infraspecific_type',
  512. 'operations' => array('eq', 'ne', 'contains', 'starts'),
  513. 'sortable' => TRUE,
  514. ),
  515. 'entity' => array(
  516. 'searchable' => FALSE,
  517. ),
  518. ),
  519. )
  520. );
  521. * @endcode
  522. *
  523. * If a field does not have a complex nested set of values, but simply returns
  524. * a scalar then the default elementInfo provides default string-based
  525. * searchabilty.
  526. *
  527. * @return
  528. * An associative array of the value elements provided by this field.
  529. */
  530. public function elementInfo() {
  531. $field_term = $this->getFieldTermID();
  532. return array(
  533. $field_term => array(
  534. 'operations' => array('eq', 'ne', 'contains', 'starts'),
  535. 'sortable' => TRUE,
  536. 'searchable' => TRUE,
  537. ),
  538. );
  539. }
  540. /**
  541. * Provides a form for the 'Field Settings' of the field management page.
  542. *
  543. * This is an optional hook function and is similar to the
  544. * hook_field_settings_form function().
  545. *
  546. * @param $has_data
  547. * TRUE if the field already has data, FALSE if not.
  548. */
  549. public function settingsForm($has_data) {
  550. $settings = $this->field['settings'];
  551. $element = array();
  552. $element['#field'] = $this->field;
  553. $element['#instance'] = $this->instance;
  554. $element['#element_validate'][] = 'tripal_field_settings_form_validate';
  555. return $element;
  556. }
  557. /**
  558. *
  559. * @param $form
  560. * @param $form_state
  561. */
  562. public function settingsFormValidate($form, &$form_state) {
  563. }
  564. /**
  565. * Provides a form for the 'Field Settings' of an instance of this field.
  566. *
  567. * This function corresponds to the hook_field_instance_settings_form()
  568. * function of the Drupal Field API.
  569. *
  570. * Validation of the instance settings form is not supported by Drupal, but
  571. * the TripalField class does provide a mechanism for supporting validation.
  572. * To allow for validation of your setting form you must call the parent
  573. * in your child class:
  574. *
  575. * @code
  576. * $element = parent::instanceSettingsForm();
  577. * @endcode
  578. *
  579. * Please note, the form generated with this function does not easily
  580. * support AJAX calls in the same way that other Drupal forms do. If you
  581. * need to use AJAX you must manually alter the $form in your ajax call.
  582. * The typical way to handle updating the form via an AJAX call is to make
  583. * the changes in the form function itself but that doesn't work here.
  584. */
  585. public function instanceSettingsForm() {
  586. $settings = $this->instance['settings'];
  587. $element = array();
  588. $element['#field'] = $this->field;
  589. $element['#instance'] = $this->instance;
  590. $element['#element_validate'][] = 'tripal_field_instance_settings_form_validate';
  591. return $element;
  592. }
  593. /**
  594. * Provides validation of the instance settings form.
  595. *
  596. * There is no equivalent function in the Drupal Field API. Validation
  597. * of instance settings forms in Drupal is not supported. However, the
  598. * TripalField provides this function to fill the gap. See the
  599. * documentation for the instanceSettingsForm() function for instructions
  600. * to support use of this function.
  601. *
  602. * @param $form
  603. * @param $form_state
  604. */
  605. public function instanceSettingsFormValidate($form, &$form_state) {
  606. }
  607. /**
  608. * After a field instance is created the following function is run.
  609. *
  610. * This function is equivalent to the hook_field_create_field() hook of
  611. * the Drupal Field API. This function is invoked after a new field
  612. * instance is created.
  613. */
  614. public function createInstance() {
  615. }
  616. /**
  617. * Used to filter records that match a given condition.
  618. *
  619. * Records that belong to a content type can be filtered using the fields.
  620. * This function should be implemented if the field supports filtering as
  621. * specified in the elementInfo() function. With this function, the query
  622. * object appropriate for the storage back-end is passed into the function.
  623. *
  624. * The condition array passesd in will have three values:
  625. * - column: the key indicating how the filter should occur.
  626. * - op: the operation to perform (e.g. equals, contains, starts with etc.
  627. * - value: the value for filtering.
  628. *
  629. * The column used for filtering will be a comma-speperated list of
  630. * controlled vocabulary IDs. This comma-separate list corresponds directly
  631. * to the heirarchy of elements provided by the elementInfo() function.
  632. * For example, if a field provides organism information then it may use
  633. * the OBI:0100026 term for the field, and the term TAXRANK:0000005 for the
  634. * term to indicate the 'Genus'. If these fields are properly organized in
  635. * the elementInfo() function then the "column" of the condition when
  636. * a user wants to search by genus will be: OBI:0100026,TAXRANK:0000005.
  637. *
  638. * @param $query
  639. * A query object appropriate for the data storage backend. For example,
  640. * The Tripal Chado module will provide a SelectQuery object.
  641. * @param $condition
  642. * The field specific condition as set in the TripalFieldQuery object.
  643. */
  644. public function query($query, $condition) {
  645. }
  646. /**
  647. * Used to sort records that have been filtered.
  648. *
  649. * @param $query
  650. * A query object appropriate for the data storage backend. For example,
  651. * The Tripal Chado module will provide a SelectQuery object.
  652. * @param $order
  653. * The field ordering as set in the TripalFieldQuery object. This function
  654. * should handle the ordering request as specified by this object.
  655. */
  656. public function queryOrder($query, $order) {
  657. }
  658. }