Tripal Field Overview
=======================
Field Classes
---------------
Anyone who wants to implement a new field in Drupal must implement three
different classes:
- `FieldItemBase `_:
the class that defines a new field. This class interacts directly with the
data storage plugin to load and save the data managed by this field.
- `WidgetBase `_:
the class that defines the form elements (widgets) provided to the end-user
to supply or change the data managed by this field.
- `FormatterBase `_:
the class that defines how the field is rendered on the page.
These classes were extended by Tripal to provide additional
functionality that allows Tripal-based fields to communicate with additional
data stores housing biological data. There is support for a number of
types of datastores (e.g. MySQL, PostgreSQL, SQLite) in core Drupal but you are
required to choose a single data store for your site. The extension to support
multiple data stores provided by Tripal allows you to keep your biological data
separate from the website and still available to scientific analysis and
visualization tools.
Chado is the default data store implemented within Tripal as it offers flexible
support for a wide breadth of biological data types, ontology-focused metadata,
and robust data integrity. The following documentation will demonstrate how to
develop custom fields with data stored in Chado. However, the Tripal data storage
plugin and Tripal Fields are designed to work with additional data stores and
documentation showing how to take advantage of this will be written in the future.
Custom module developers who wish to add new fields to Tripal whose data are
stored in Chado should implement the following three classes for every new field:
- **ChadoFieldItemBase**: extends the Tripal class `TripalFieldItemBase`
which extends the Drupal class `FieldItemBase`. The `TripalFieldItemBase`
must be used for all fields attached to Tripal content types, and the
`ChadoFieldItemBase` adds Chado-specific support.
- **ChadoWidgetBase**: extends the Tripal class `TripalWidgetBase`
which extends the Drupal class `WidgetBase`.
- **ChadoFormatterBase**: extends the Tripal class `TripalFormatterBase`
which extends the Drupal class `FormatterBase`.
Directory Setup
-----------------
Drupal manages fields using its `Plugin API `_.
This means that as long as new field classes are placed in the correct directory
and have the correct "annotations" in the class comments, then Drupal will find them
and make the field available. All new fields must be placed in the custom
extension module inside of the `src/Plugin/Field` directory. There are three
subdirectories, one each for the three elements of a field:
`FieldType`, `FieldWidget`, `FieldFormatter`. For a new field named `MyField`
the directory structure would look like the following:
.. code::
mymodule
├── config
├── src
│ └── Plugin
│ └── Field
│ ├── FieldFormatter
| | └── MyFieldFormatter.php
│ ├── FieldType
| | └── MyFieldType.php
│ └── FieldWidget
| └── MyFieldWidget.php
|
├── tests
└── templates
Note that the file name must match the class name.
Naming conventions
-------------------
The filename for your new field should adhere to the following schema. Please
note the casing used. In addition, for fields that will be included in Tripal
Core, note the 'Default' designation, any fields added by extension modules
should **not** use 'Default':
.. table:: Tripal Core modules:
+------------------+-----------------------------+
| File | Filename |
+==================+=============================+
| Type | MyFieldTypeDefault.php |
+------------------+-----------------------------+
| Formatter | MyFieldFormatterDefault.php |
+------------------+-----------------------------+
| Widget | MyFieldWidgetDefault.php |
+------------------+-----------------------------+
.. table:: Extension modules:
+------------------+-----------------------------+
| File | Filename |
+==================+=============================+
| Type | MyFieldType.php |
+------------------+-----------------------------+
| Formatter | MyFieldFormatter.php |
+------------------+-----------------------------+
| Widget | MyFieldWidget.php |
+------------------+-----------------------------+
Within the individual files, in the annotation section, the ID also has to follow
a specific format, and would look like the following:
.. table:: Tripal Core modules:
+------------------+----------------------------+
| File | ID within annotation |
+==================+============================+
| Type | my_field_type_default |
+------------------+----------------------------+
| Formatter | my_field_formatter_default |
+------------------+----------------------------+
| Widget | my_field_widget_default |
+------------------+----------------------------+
.. table:: Extension modules:
+------------------+----------------------------+
| File | ID within annotation |
+==================+============================+
| Type | my_field_type |
+------------------+----------------------------+
| Formatter | my_field_formatter |
+------------------+----------------------------+
| Widget | my_field_widget |
+------------------+----------------------------+
About the Storage Backend
--------------------------
Default Drupal Behavior
^^^^^^^^^^^^^^^^^^^^^^^^^
By default, all built-in fields provided by Drupal store their data in the
Drupal database. This is provided by Drupal's
`SqlContentEntityStorage `_
storage plugin. This storage plugin will create a database table for every field.
For example, if you explore the Drupal database tables you will see the
following for the body field attached to the node content type:
.. code::
Table "public.node__body"
Column | Type | Collation | Nullable | Default
--------------+------------------------+-----------+----------+-----------------------
bundle | character varying(128) | | not null | ''::character varying
deleted | smallint | | not null | 0
entity_id | bigint | | not null |
revision_id | bigint | | not null |
langcode | character varying(32) | | not null | ''::character varying
delta | bigint | | not null |
body_value | text | | not null |
body_summary | text | | |
body_format | character varying(255) | | |
Indexes:
"node__body____pkey" PRIMARY KEY, btree (entity_id, deleted, delta, langcode)
"node__body__body_format__idx" btree (body_format)
"node__body__bundle__idx" btree (bundle)
"node__body__revision_id__idx" btree (revision_id)
Check constraints:
"node__body_delta_check" CHECK (delta >= 0)
"node__body_entity_id_check" CHECK (entity_id >= 0)
"node__body_revision_id_check" CHECK (revision_id >= 0)
The values provided by the user for the body of a node type are housed in this
table. The following describes the columns of the table.
These columns are present for all fields
- `bundle`: the machine name of the content type (e.g. node)
- `deleted`: a value of 1 indicates the field is marked for deletion
- `entity_id`: the unique ID of the node that this field belongs to.
- `revision_id`: the node revision ID.
- `langcode`: for fields that are translatable, this indicates the language
of the saved value.
- `delta`: for fields that support multiple values, this is the index (starting
at zero) for the order of the values.
These columns are specific to the field:
- `body_value`: stores the value for the body
- `body_summary`: stores the body summary
- `body_format`: instructions for how the body should be rendered (e.g. plain
text, HTML, etc.)
Support for Chado
^^^^^^^^^^^^^^^^^^
For fields storing biological data in something other than Drupal tables,
Tripal provides its own plugin named `TripalStorage`. If a custom module wants to
store data in a data backend other than in Drupal tables, it must create an implementation
of this plugin. By default, Tripal provides the `ChadoStorage` implementation
that allows a field to interact with a Chado database.
The `ChadoStorage` backend extends the `SqlContentEntityStorage` and
will create a table in the Drupal schema for every Tripal field that is
added to a content type. The table columns will include the same default
columns as a Drupal field, and will also include a set of additional columns
for every property the field wants to manage.
The `ChadoStorage` backend is different from `SqlContentEntityStorage`
in that it will not store the values of the properties in the table. This is
because those values need to be stored in Chado--we do not want to duplicate
the data in the Drupal schema and the Chado schema. The `ChadoStorage`
backend is also different in that it requires a set of property settings that
help it control how properties of a field are stored, edited and loaded from
Chado. Instructions for working with properties and storing data in Chado are
described in the following sections.
.. note::
The `ChadoStorage` backend will not store biological data in the Drupal
tables--only in the Chado tables. The only exceptions are record IDs that
associate the field with data in Chado.
See the next section :ref:`Field Types` to learn how to define the
properties for a new field.