--- /dev/null
+<?php
+
+namespace Drupal\{{ machine_name }}\Plugin\Field\FieldFormatter;
+
+{% sort %}
+ {% if datetime %}
+use Drupal\Core\Datetime\DrupalDateTime;
+ {% endif %}
+use Drupal\Core\Field\FieldItemListInterface;
+use Drupal\Core\Field\FormatterBase;
+ {% if formatter_settings %}
+use Drupal\Core\Form\FormStateInterface;
+ {% endif %}
+ {% if link %}
+use Drupal\Core\Url;
+ {% endif %}
+ {% if list %}
+use Drupal\{{ machine_name }}\Plugin\Field\FieldType\{{ type_class }};
+ {% endif %}
+{% endsort %}
+
+/**
+ * Plugin implementation of the '{{ field_id }}_default' formatter.
+ *
+ * @FieldFormatter(
+ * id = "{{ field_id }}_default",
+ * label = @Translation("Default"),
+ * field_types = {"{{ field_id }}"}
+ * )
+ */
+class {{ formatter_class }} extends FormatterBase {
+
+{% if formatter_settings %}
+ /**
+ * {@inheritdoc}
+ */
+ public static function defaultSettings() {
+ return ['foo' => 'bar'] + parent::defaultSettings();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function settingsForm(array $form, FormStateInterface $form_state) {
+ $settings = $this->getSettings();
+ $element['foo'] = [
+ '#type' => 'textfield',
+ '#title' => $this->t('Foo'),
+ '#default_value' => $settings['foo'],
+ ];
+ return $element;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function settingsSummary() {
+ $settings = $this->getSettings();
+ $summary[] = $this->t('Foo: @foo', ['@foo' => $settings['foo']]);
+ return $summary;
+ }
+
+{% endif %}
+ /**
+ * {@inheritdoc}
+ */
+ public function viewElements(FieldItemListInterface $items, $langcode) {
+ $element = [];
+
+ foreach ($items as $delta => $item) {
+
+{% for subfield in subfields %}
+ {% if subfield.type == 'boolean' %}
+ $element[$delta]['{{ subfield.machine_name }}'] = [
+ '#type' => 'item',
+ '#title' => $this->t('{{ subfield.name }}'),
+ '#markup' => $item->{{ subfield.machine_name }} ? $this->t('Yes') : $this->t('No'),
+ ];
+
+ {% else %}
+ if ($item->{{ subfield.machine_name }}) {
+ {% if subfield.list %}
+ $allowed_values = {{ type_class }}::{{ subfield.allowed_values_method }}();
+ {% endif %}
+ {% set item_value %}
+ {% if subfield.list %}$allowed_values[$item->{{ subfield.machine_name }}]{% else %}$item->{{ subfield.machine_name }}{% endif %}
+ {% endset %}
+ {% if subfield.type == 'datetime' %}
+ $date = DrupalDateTime::createFromFormat('{{ subfield.date_storage_format }}', $item->{{ subfield.machine_name }});
+ // @DCG: Consider injecting the date formatter service.
+ // @codingStandardsIgnoreStart
+ $date_formatter = \Drupal::service('date.formatter');
+ // @codingStandardsIgnoreStart
+ $timestamp = $date->getTimestamp();
+ {% if subfield.list %}
+ $formatted_date = {{ item_value }};
+ {% else %}
+ $formatted_date = $date_formatter->format($timestamp, 'long');
+ {% endif %}
+ $iso_date = $date_formatter->format($timestamp, 'custom', 'Y-m-d\TH:i:s') . 'Z';
+ $element[$delta]['{{ subfield.machine_name }}'] = [
+ '#type' => 'item',
+ '#title' => $this->t('{{ subfield.name }}'),
+ 'content' => [
+ '#theme' => 'time',
+ '#text' => $formatted_date,
+ '#html' => FALSE,
+ '#attributes' => [
+ 'datetime' => $iso_date,
+ ],
+ '#cache' => [
+ 'contexts' => [
+ 'timezone',
+ ],
+ ],
+ ],
+ ];
+ {% else %}
+ $element[$delta]['{{ subfield.machine_name }}'] = [
+ '#type' => 'item',
+ '#title' => $this->t('{{ subfield.name }}'),
+ {% if subfield.link %}
+ 'content' => [
+ '#type' => 'link',
+ '#title' => {{ item_value }},
+ {% if subfield.type == 'email' %}
+ '#url' => Url::fromUri('mailto:' . $item->{{ subfield.machine_name }}),
+ {% elseif subfield.type == 'telephone' %}
+ '#url' => Url::fromUri('tel:' . rawurlencode(preg_replace('/\s+/', '', $item->{{ subfield.machine_name }}))),
+ {% elseif subfield.type == 'uri' %}
+ '#url' => Url::fromUri($item->{{ subfield.machine_name }}),
+ {% endif %}
+ ],
+ {% else %}
+ '#markup' => {{ item_value }},
+ {% endif %}
+ ];
+ {% endif %}
+ }
+
+ {% endif %}
+{% endfor %}
+ }
+
+ return $element;
+ }
+
+}