TripalField.inc 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608
  1. <?php
  2. /**
  3. * A base for fields attached Tripal Entities.
  4. *
  5. * This class is intended to simplify development of fields for Tripal Entities.
  6. * The Drupal Field API can still be used if desired, but the hope for this
  7. * class it to put the necessary functions in one place so that other Tripal
  8. * developers do not need to suffer the pain of navigating and learning the
  9. * Drupal Field API.
  10. *
  11. * To create a new field that can be attached to a Tripal Entity follow these
  12. * steps:
  13. * # Create a new class that inherits from TripalField
  14. * # Copy the editable constant variables (default_desription, default_label,
  15. * default_settings and default_storage) to your class and edit as needed.
  16. * Be sure not to rename these variables and be sure to keep the 'static'
  17. * qualifier on them.
  18. * # Copy the functions you want to override. You will not need to copy the
  19. * constructor, the static info() functions, or the getters and setters. In
  20. * short you'll typically only need to override the Settingsform funtions,
  21. * their validators and submitters, the load() function, and the widgetForm
  22. * with it's validator and submitter.
  23. * # In your custom module implement the function hook_create_tripalfields()
  24. * This function will be called anytime a new TripalEntity is created. It
  25. * allows your module to create the new fields. See the documentation for
  26. * this function for creating the fields. A field is usually only ever
  27. * created once and can be reused on multiple entities. So, even though
  28. * this function is called everytime a new TripalEntity is created the fields
  29. * will only be created once.
  30. * # In your custom module implement the function
  31. * hook_create_tripalfield_instance(). This function is called anytime a
  32. * new TripalEntity is created. It allows you to specify which fields are
  33. * attached to an entity. See the documentation for this hook function for
  34. * more information.
  35. *
  36. */
  37. class TripalField {
  38. // --------------------------------------------------------------------------
  39. // EDITABLE STATIC CONSTANTS
  40. //
  41. // The following constants SHOULD be set for each descendent class. They are
  42. // used by the static functions to provide information to Drupal about
  43. // the field and it's default widget and formatter.
  44. // --------------------------------------------------------------------------
  45. // The default lable for this field.
  46. public static $default_label = 'Tripal Field.';
  47. // The default description for this field.
  48. public static $default_description = 'The generic base class for all
  49. Tripal Fields. Replace this text as appropriate for the child implementation.';
  50. // Provide a list of global settings. These can be accessed witihn the
  51. // globalSettingsForm. When the globalSettingsForm is submitted then
  52. // Drupal will automatically change these settings for all fields.
  53. public static $default_settings = array();
  54. // Provide a list of instance specific settings. These can be access within
  55. // the instanceSettingsForm. When the instanceSettingsForm is submitted
  56. // then Drupal with automatically change these settings for the instnace.
  57. // It is recommended to put settings at the instance level whenever possible.
  58. public static $default_instance_settings = array();
  59. // Set this to the name of the storage backend that by default will support
  60. // this field.
  61. public static $default_storage = 'tripal_no_storage';
  62. // --------------------------------------------------------------------------
  63. // PROTECTED CLASS MEMBERS -- DO NOT OVERRIDE
  64. // --------------------------------------------------------------------------
  65. // An array containing details about the field. The format of this array
  66. // is the same as that returned by field_info_fields()
  67. protected $field;
  68. // An array containing details about an instance of the field. A field does
  69. // not have to have an instance. But if dealing with an instance (such as
  70. // when using the widgetForm, formatterSettingsForm, etc.) it should be set.
  71. protected $instance;
  72. // --------------------------------------------------------------------------
  73. // CONSTRUCTORS -- DO NOT OVERRIDE
  74. // --------------------------------------------------------------------------
  75. /**
  76. * Instantiates a new TripalField object.
  77. *
  78. * @param $field
  79. * An array containing the field data as returned by field_info_field()
  80. * @param $instance
  81. * (Optional). Set the instance of this field when one is available. This
  82. * is necessary when working with instance specific functions such as the
  83. * formatterSettingsForm, widgetForm, etc.
  84. */
  85. public function __construct($field, $instance = NULL) {
  86. $this->field = $field;
  87. $this->instance = $instance;
  88. }
  89. // --------------------------------------------------------------------------
  90. // STATIC INFO FUNCTIONS -- DO NOT OVERRIDE
  91. // --------------------------------------------------------------------------
  92. /**
  93. * Provides default information about this field type
  94. *
  95. * This function corresponds to the hook_field_info() function of
  96. * the Drupal Field API.
  97. *
  98. * @return
  99. * An array whose keys are field type names and whose values are arrays
  100. * describing the field type. The keys are the same as for the
  101. * hook_field_info() function.
  102. */
  103. public static function globalInfo() {
  104. $field_type = get_called_class();
  105. return array(
  106. 'label' => $field_type::$default_label,
  107. 'description' => $field_type::$default_description,
  108. 'default_widget' => $field_type . '_widget',
  109. 'default_formatter' => $field_type . '_formatter',
  110. 'settings' => $field_type::$default_settings,
  111. 'instance_settings' => $field_type::$default_instance_settings,
  112. 'storage' => array(
  113. 'type' => $field_type::$default_storage,
  114. 'module' => 'tripal',
  115. 'active' => TRUE
  116. ),
  117. );
  118. }
  119. /**
  120. * Provides information about the widgets provided by this field.
  121. *
  122. * This function corresponds to the hook_field_widget_info() function of
  123. * the Drupal Field API.
  124. *
  125. * This is a static function as it provides default values for all of the
  126. * widgets for this field type, and thus we don't need an instantiated
  127. * object to provide this information.
  128. *
  129. * @return
  130. * An associative array with key/value pairs compatible with those from the
  131. * hook_field_widget_info() function of the Drupal Field API.
  132. */
  133. public static function widgetInfo() {
  134. $field_type = get_called_class();
  135. return array(
  136. $field_type . '_widget' => array(
  137. 'label' => $field_type::$default_label,
  138. 'field types' => array($field_type)
  139. ),
  140. );
  141. }
  142. /**
  143. * Provides information about the formatter for this field.
  144. *
  145. * This function corresponds to the hook_field_formatter_info() function of
  146. * the Drupal Field API.
  147. *
  148. * This is a static function as it provides default values for all of the
  149. * formatters for this field type, and thus we don't need an instantiated
  150. * object to provide this information.
  151. *
  152. * @return
  153. * An associative array with key/value paris compatible with those from the
  154. * hook_field_formatter_info() function of the Drupal Field API.
  155. *
  156. */
  157. public static function formatterInfo() {
  158. $field_type = get_called_class();
  159. return array(
  160. $field_type . '_formatter' => array(
  161. 'label' => $field_type::$default_label,
  162. 'field types' => array($field_type),
  163. 'settings' => array(),
  164. ),
  165. );
  166. }
  167. // --------------------------------------------------------------------------
  168. // GETTERS AND SETTERS -- DO NOT OVERRIDE
  169. // --------------------------------------------------------------------------
  170. /**
  171. * Retrives the name of this field.
  172. *
  173. * @return
  174. * This field's name.
  175. */
  176. public function getFieldName() {
  177. return $this->field['field_name'];
  178. }
  179. public function getField() {
  180. return $this->field;
  181. }
  182. public function getInstance() {
  183. return $this->instance;
  184. }
  185. // --------------------------------------------------------------------------
  186. // OVERRIDEABLE FUNCTIONS
  187. // --------------------------------------------------------------------------
  188. /**
  189. * Provides a summary of the formatter settings.
  190. *
  191. * This function corresponds to the hook_field_formatter_settings_summary()
  192. * function of the Drupal Field API.
  193. *
  194. * On the 'Manage Display' page of the content type administration page,
  195. * fields are allowed to provide a settings form. This settings form can
  196. * be used to allow the site admin to define how the field should be
  197. * formatted. The settings are then available for the formatter()
  198. * function of this class. This function provides a text-based description
  199. * of the settings for the site developer to see. It appears on the manage
  200. * display page inline with the field. A field must always return a
  201. * value in this function if the settings form gear button is to appear.
  202. *
  203. * See the hook_field_formatter_settings_summary() function for more
  204. * information.
  205. *
  206. * @param $field
  207. * @param $instance
  208. * @param $view_mode
  209. *
  210. * @return string
  211. * A string that provides a very brief summary of the field settings
  212. * to the user.
  213. *
  214. */
  215. public function formatterSettingsSummary($view_mode) {
  216. }
  217. /**
  218. * Provides the field's setting form.
  219. *
  220. * This function corresponds to the hook_field_formatter_settings_form()
  221. * function of the Drupal Field API.
  222. *
  223. * The settings form appears on the 'Manage Display' page of the content
  224. * type administration page. This function provides the form that will
  225. * appear on that page.
  226. *
  227. * To add a validate function, please create a static function in the
  228. * implementing class, and indicate that this function should be used
  229. * in the form array that is returned by this function.
  230. *
  231. * This form will not be displayed if the formatter_settings_summary()
  232. * function does not return anything.
  233. *
  234. * @param $field
  235. * @param $instance
  236. * @param $view_mode
  237. * @param $form
  238. * @param $form_state
  239. *
  240. * @return
  241. * A Drupal Form array containing the settings form for this field.
  242. */
  243. public function formatterSettingsForm($view_mode, $form, &$form_state) {
  244. }
  245. /**
  246. * Provides the display for a field
  247. *
  248. * This function corresponds to the hook_field_formatter_view()
  249. * function of the Drupal Field API.
  250. *
  251. * This function provides the display for a field when it is viewed on
  252. * the web page. The content returned by the formatter should only include
  253. * what is present in the $items[$delta]['values] array. This way, the
  254. * contents that are displayed on the page, via webservices and downloaded
  255. * into a CSV file will always be identical. The view need not show all
  256. * of the data in the 'values' array.
  257. *
  258. * @param $element
  259. * @param $entity_type
  260. * @param $entity
  261. * @param $langcode
  262. * @param $items
  263. * @param $display
  264. *
  265. * @return
  266. * An element array compatible with that returned by the
  267. * hook_field_formatter_view() function.
  268. */
  269. public function formatterView(&$element, $entity_type, $entity, $langcode, $items, $display) {
  270. foreach($items as $delta => $item) {
  271. $element[$delta] = array(
  272. '#type' => 'markup',
  273. '#markup' => $item['value'],
  274. );
  275. }
  276. }
  277. /**
  278. * Provides the form for editing of this field.
  279. *
  280. * This function corresponds to the hook_field_widget_form()
  281. * function of the Drupal Field API.
  282. *
  283. * This form is diplayed when the user creates a new entity or edits an
  284. * existing entity. If the field is attached to the entity then the form
  285. * provided by this function will be displayed.
  286. *
  287. * At a minimum, the form must have a 'value' element. For Tripal, the
  288. * 'value' element of a field always corresponds to the value that is
  289. * presented to the end-user either directly on the page (with formatting)
  290. * or via web services, or some other mechanism. However, the 'value' is
  291. * sometimes not enough for a field. For example, the Tripal Chado module
  292. * maps fields to table columns and sometimes those columns are foreign keys
  293. * therefore, the Tripal Chado modules does not just use the 'value' but adds
  294. * additional elements to help link records via FKs. But even in this case
  295. * the 'value' element must always be present in the return form and in such
  296. * cases it's value should be set equal to that added in the 'load' function.
  297. *
  298. * @param $widget
  299. * @param $form
  300. * The form structure where widgets are being attached to. This might be a
  301. * full form structure, or a sub-element of a larger form.
  302. * @param $form_state
  303. * An associative array containing the current state of the form.
  304. * @param $langcode
  305. * The language associated with $items.
  306. * @param $items
  307. * Array of default values for this field.
  308. * @param $delta
  309. * The order of this item in the array of subelements (0, 1, 2, etc).
  310. * @param $element
  311. * A form element array containing basic properties for the widget:
  312. * - #entity_type: The name of the entity the field is attached to.
  313. * - #bundle: The name of the field bundle the field is contained in.
  314. * - #field_name: The name of the field.
  315. * - #language: The language the field is being edited in.
  316. * - #field_parents: The 'parents' space for the field in the form. Most
  317. * widgets can simply overlook this property. This identifies the location
  318. * where the field values are placed within $form_state['values'], and is
  319. * used to access processing information for the field through the
  320. * field_form_get_state() and field_form_set_state() functions.
  321. * - #columns: A list of field storage columns of the field.
  322. * - #title: The sanitized element label for the field instance, ready for
  323. * output.
  324. * - #description: The sanitized element description for the field instance,
  325. * ready for output.
  326. * - #required: A Boolean indicating whether the element value is required;
  327. * for required multiple value fields, only the first widget's values are
  328. * required.
  329. * - #delta: The order of this item in the array of subelements; see
  330. * $delta above
  331. */
  332. public function widgetForm(&$widget, &$form, &$form_state, $langcode, $items, $delta, $element) {
  333. $widget['value'] = array(
  334. '#type' => 'value',
  335. '#value' => array_key_exists($delta, $items) ? $items[$delta]['value'] : '',
  336. );
  337. $widget['#field'] = $this->field;
  338. $widget['#instance'] = $this->instance;
  339. $widget['#element_validate'] = array('tripal_field_widget_form_validate');
  340. }
  341. /**
  342. * Performs validation of the widgetForm.
  343. *
  344. * Use this validate to ensure that form values are entered correctly. Note
  345. * this is different from the validate() function which ensures that the
  346. * field data meets expectations.
  347. *
  348. * @param $form
  349. * @param $form_state
  350. */
  351. public function widgetFormValidate($form, &$form_state, $entity_type, $entity, $langcode, $delta) {
  352. }
  353. /**
  354. * Perform validation of the field regardless how it is updated.
  355. *
  356. * Any errors encountered should be indicatd by adding a value to the $errors
  357. * array according to the instructions below.
  358. *
  359. * @param $entity_type
  360. * The type of $entity.
  361. * @param $entity
  362. * The entity for the operation.
  363. * @param $field
  364. * The field structure for the operation.
  365. * @param $instance
  366. * The instance structure for $field on $entity's bundle.
  367. * @param $langcode
  368. * The language associated with $items.
  369. * @param $items
  370. * $entity->{$field['field_name']}[$langcode], or an empty array if unset.
  371. * @param $errors
  372. * The array of errors (keyed by field name, language code, and delta) that
  373. * have already been reported for the entity. The function should add its
  374. * errors to this array. Each error is an associative array with the
  375. * following keys and values:
  376. * - error: An error code (should be a string prefixed with the
  377. * module name).
  378. * - message: The human readable message to be displayed.
  379. *
  380. */
  381. public function validate($entity_type, $entity, $field, $items, &$errors) {
  382. }
  383. /**
  384. * Performs extra commands when the entity form is submitted.
  385. *
  386. * Drupal typically does not provide a submit hook for fields. The
  387. * TripalField provides one to allow for behind-the-scenes actions to
  388. * occur. This function should never be used for updates, deletes or
  389. * inserts for the Chado table associated with the field. Rather, the
  390. * storage backend should be allowed to handle inserts, updates deletes.
  391. * However, it is permissible to perform inserts, updates or deletions within
  392. * Chado using this function. Those operations can be performed if needed but
  393. * on other tables not directly associated with the field.
  394. *
  395. * An example is the chado.feature_synonym table. The chado_linker__synonym
  396. * field allows the user to provide a brand new synonynm and it must add it
  397. * to the chado.synonym table prior to the record in the
  398. * chado.feature_synonym table. This insert occurs in the widgetFormSubmit
  399. * function.
  400. *
  401. * @param $entity_type
  402. * The type of $entity.
  403. * @param $entity
  404. * The entity for the operation.
  405. * @param $field
  406. * The field structure for the operation.
  407. * @param $instance
  408. * The instance structure for $field on $entity's bundle.
  409. * @param $langcode
  410. * The language associated with $items.
  411. * @param $items
  412. * $entity->{$field['field_name']}[$langcode], or an empty array if unset.
  413. * @param $form
  414. * The submitted form array.
  415. * @param $form_state.
  416. * The form state array.
  417. */
  418. public function widgetFormSubmit($form, &$form_state, $entity_type, $entity, $langcode, $delta) {
  419. }
  420. /**
  421. * Loads the field values from the underlying data store.
  422. *
  423. * @param $entity
  424. * @param $details
  425. *
  426. * @return
  427. * An array of the following format:
  428. * $entity->{$field_name}['und'][0]['value'] = $value;
  429. * where:
  430. * - $entity is the enity object to which this field is attached.
  431. * - $field_name is the name of this field
  432. * - 'und' is the language code (in this case 'und' == undefined)
  433. * - 0 is the cardinality. Increment by 1 when more than one item is
  434. * available.
  435. * - 'value' is the key indicating the value of this field. It should
  436. * always be set. The value of the 'value' key will be the contents
  437. * used for web services and for downloadable content. The value
  438. * should be of the follow format types: 1) A single value (text,
  439. * numeric, etc.) 2) An array of key value pair. 3) If multiple entries
  440. * then cardinality should incremented and format types 1 and 2 should
  441. * be used for each item.
  442. * The array may contain as many other keys at the same level as 'value'
  443. * but those keys are for internal field use and are not considered the
  444. * value of the field.
  445. *
  446. *
  447. */
  448. public function load($entity, $details = array()) {
  449. }
  450. /**
  451. * Provides a form for the 'Field Settings' of an instance of this field.
  452. *
  453. * This function corresponds to the hook_field_instance_settings_form()
  454. * function of the Drupal Field API.
  455. *
  456. * Validation of the instance settings form is not supported by Drupal, but
  457. * the TripalField class does provide a mechanism for supporting validation.
  458. * To allow for validation of your setting form you must call the parent
  459. * in your child class:
  460. *
  461. * @code
  462. * $element = parent::instanceSettingsForm();
  463. * @endcode
  464. *
  465. * Please note, the form generated with this function does not easily
  466. * support AJAX calls in the same way that other Drupal forms do. If you
  467. * need to use AJAX you must manually alter the $form in your ajax call.
  468. * The typical way to handle updating the form via an AJAX call is to make
  469. * the changes in the form function itself but that doesn't work here.
  470. */
  471. public function instanceSettingsForm() {
  472. $settings = $this->instance['settings'];
  473. $element = array();
  474. // $element['semantic_web'] = array(
  475. // '#type' => 'textfield',
  476. // '#title' => 'Semantic Web',
  477. // '#description' => t('Each field must be associated with a term
  478. // from a controlled vocabulary. This allows computer programs to understand
  479. // the data provided on this site. Please be cautions changing these
  480. // values. Defaults are set by Tripal and sites that use the same
  481. // terms can exchange information.'),
  482. // '#collapsed' => TRUE,
  483. // '#collapsible' => TRUE,
  484. // '#tree' => TRUE,
  485. // );
  486. $element['#field'] = $this->field;
  487. $element['#instance'] = $this->instance;
  488. $element['#element_validate'][] = 'tripal_field_instance_settings_form_validate';
  489. return $element;
  490. }
  491. /**
  492. * Provides validation of the instance settings form.
  493. *
  494. * There is no equivalent function in the Drupal Field API. Validation
  495. * of instance settings forms in Drupal is not supported. However, the
  496. * TripalField provides this function to fill the gap. See the
  497. * documentation for the instanceSettingsForm() function for instructions
  498. * to support use of this function.
  499. *
  500. * @param $form
  501. * @param $form_state
  502. */
  503. public function instanceSettingsFormValidate($form, &$form_state) {
  504. }
  505. /**
  506. * Provides a form for the 'Field Settings' of the field management page.
  507. *
  508. * This is an optional hook function and is similar to the
  509. * hook_field_settings_form function().
  510. *
  511. * @param $field
  512. * The field structure being configured.
  513. * @param $instance
  514. * The instance structure being configured.
  515. * @param $has_data
  516. * TRUE if the field already has data, FALSE if not.
  517. */
  518. public function globalSettingsForm($has_data) {
  519. $settings = $this->field['settings'];
  520. $element = array();
  521. // $element['semantic_web'] = array(
  522. // '#type' => 'textfield',
  523. // '#title' => 'Semantic Web',
  524. // '#description' => t('Each field must be associated with a term
  525. // from a controlled vocabulary. This allows computer programs to understand
  526. // the data provided on this site. Please be cautions changing these
  527. // values. Defaults are set by Tripal and sites that use the same
  528. // terms can exchange information.'),
  529. // '#collapsed' => TRUE,
  530. // '#collapsible' => TRUE,
  531. // '#tree' => TRUE,
  532. // );
  533. $element['#field'] = $this->field;
  534. $element['#instance'] = $this->instance;
  535. $element['#element_validate'][] = 'tripal_field_settings_form_validate';
  536. return $element;
  537. }
  538. /**
  539. *
  540. * @param unknown $form
  541. * @param unknown $form_state
  542. */
  543. public function globalSettingsFormValidate($form, &$form_state) {
  544. }
  545. /**
  546. * Describes this fields "data tables" to Views.
  547. *
  548. * This function is the equivalent of the hook_views_data() function of
  549. * the Drupal Views API. It provides the necessary details to allow
  550. * Views to integrate the field.
  551. *
  552. * @return
  553. * An associative array describing the data structure of the field.
  554. */
  555. public function viewsDataAlter(&$data, $entity_info) {
  556. }
  557. }