Part of meta-issue
In Drupal 7 we were using PHP print statements in field.tpl.php to add our RDFa attributes around each field formatter. We typically had these attribute variables:
$item_attributes in node.tpl.php, field.tpl.php, etc. The latter
$item_attributes was used to wrap each field item with the appropriate attributes in field.tpl.php. Here is the example of a text field output:
<div class="field field-name-body field-type-text-with-summary field-label-hidden">
<div class="field-item even" property="schema:text">
<!-- field formatter output is inserted here, without any way to add RDFa attributes. -->
Drupal 7's limitations
Placing the attributes on the item wrapper element worked for some core fields in D7, those which were outputting simple one value items (text or number). We started to feel the limit of this approach for fields like file or image where we were forced to duplicate the URL value on the item wrapper because it was not possible to inject the RDFa markup inside the field formatter in the same element as the file link. See for example this image field output (note how the file URL is repeated):
<div class="field-item even" property="og:image" resource="http://openspring.net/sites/openspring.net/files/styles/medium/public/8553992227_c90f23718a.jpg">
<a href="/week-ecuador-viva-drupal-latino"><img alt="" src="http://openspring.net/sites/openspring.net/files/styles/medium/public/8553992227_c90f23718a.jpg" /></a>
In an ideal situation, the RDFa attribute 'property' would be placed on the img element where the image URL is, but because D7 didn't have any way to achieve that, we had to resort to duplicating the image URL in the wrapping element. This markup is suboptimal. The ideal markup for D8 is to simply add one RDFa attribute (property="..") to the img element inside the field formatter:
<div class="field-item even">
<a href="/week-ecuador-viva-drupal-latino"><img alt="" property="og:image" src="http://openspring.net/sites/openspring.net/files/styles/medium/public/8553992227_c90f23718a.jpg" /></a>
Besides requiring duplicate values in the wrapping element, D7's suboptimal method of placing RDFa markup in the wrapping element failed when it came the time to RDFa-ize compound fields from contrib which have multiple elements inside each item, for example addressfield (street, locality, country, zip code) or fivestar (rating, number of votes). There is only so much structured data you can cram into a single HTML element.
Lesson learned: do not solely rely on in the item wrapper to place RDFa attributes, it's not a generic, scalable solution.
As more field types like date and link are moved to core, it becomes crucial to find a solution to this problem, and be able to inject attributes in the HTML elements closer to the actual values inside the field formatters. For date.module, we want to be able to take advantage of the HTML5 time element and inject the RDFa property attribute in the time element, and for link, we want to be able to annotate both the URL and the link text. We can't achieve this without being able to inject RDFa attributes inside the field formatters.
Pass the RDFa attributes to the field formatter and give it a chance to place the attributes at the right place in HTML markup it generates. If the field formatter does not use these attributes and leave them set in the field item, the field template will inject them in the usual location (like it currently does in Drupal 7).
This issue focuses on the fields which were part of Drupal 7 and are currently tested in the RDF module: text, taxonomy_term, file, image. Other fields are covered in. Compound fields are covered in . Note that this issue does not cover data like post date, etc., as those items are not provided by fields.
User interface changes
API changes (most of them are API additions)
- The logic for loading the mappings and generating the attributes in hook implementations rdf_preprocess_field() and rdf_field_attach_view_alter() is removed and replaced by a single rdf_entity_prepare_view() which generates the RDFa attributes for each field items about to be displayed.
- Field items have a new property 'html_data_attributes' (
$item->html_data_attributes) which contains the attributes to be placed in the HTML output by the field formatters or the field template.
- Field formatters have the ability to inject RDFa attributes inside the HTML markup they generate. The RDFa attributes are generated by the RDF module in rdf_entity_prepare_view(), and placed in the new field item property
html_data_attributes, which the field formatters can then inject at the right place in their HTML output. If a field formatter leaves
html_data_attributes intact, these attributes will be inserted in the field template as it is currently the case in Drupal 7. If a field formatters makes use of the HTML data attributes, it should unset them so that they are not added in the field template.
- theme_file_link() accepts a new parameter 'attributes', which contains attributes to be placed in the a element (necessary for optimal RDFa markup for file field link.)
- The mapping type
mapping_type: 'rel' no longer needs to be specified in the RDF mapping definitions. These were necessary in Drupal 7 in order to generate a different set of attributes for the field wrapper depending on the type of object contained in the field wrapper.
mapping_type: 'rel' was used when the object in the field output was another resource (with a URI) such as a file, as opposed to a string/literal (e.g. text field). This is no longer necessary because we can now inject the attributes directly in the field formatter.
ab showed some small performance gain in some situations, see details in #52. Additionally, this patch also reduces the markup size in the case of file and image fields, since the URL does not need to be processed on the backend and repeated in the final HTML output.
Steps for reviewing the intended results of this patch
Here is a quick outline for patch reviewers. Viewing the intended effects is relatively simple, despite the far-reaching changes to code.
- On a fresh installation of Drupal 8, create an entity with contents in one or all of the following fields: text, taxonomy term, file, image.
- View the entity and save the source for these fields for later.
- Apply the most recent patch
- Reload the entity and compare the source to that from before the patch
PASSED: [[SimpleTest]]: [MySQL] 58,677 pass(es).
PASSED: [[SimpleTest]]: [MySQL] 58,322 pass(es).
PASSED: [[SimpleTest]]: [MySQL] 58,819 pass(es).
PASSED: [[SimpleTest]]: [MySQL] 58,857 pass(es).