e4c3d9171e2ecf7655c7f07293fda33a5bbb5443
[yaffs-website] / web / core / lib / Drupal / Core / Field / Plugin / Field / FieldFormatter / TimestampAgoFormatter.php
1 <?php
2
3 namespace Drupal\Core\Field\Plugin\Field\FieldFormatter;
4
5 use Drupal\Component\Render\FormattableMarkup;
6 use Drupal\Core\Cache\CacheableMetadata;
7 use Drupal\Core\Datetime\DateFormatterInterface;
8 use Drupal\Core\Datetime\DrupalDateTime;
9 use Drupal\Core\Field\FieldDefinitionInterface;
10 use Drupal\Core\Field\FieldItemListInterface;
11 use Drupal\Core\Field\FormatterBase;
12 use Drupal\Core\Form\FormStateInterface;
13 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
14 use Symfony\Component\DependencyInjection\ContainerInterface;
15 use Symfony\Component\HttpFoundation\Request;
16
17 /**
18  * Plugin implementation of the 'timestamp' formatter as time ago.
19  *
20  * @FieldFormatter(
21  *   id = "timestamp_ago",
22  *   label = @Translation("Time ago"),
23  *   field_types = {
24  *     "timestamp",
25  *     "created",
26  *     "changed",
27  *   }
28  * )
29  */
30 class TimestampAgoFormatter extends FormatterBase implements ContainerFactoryPluginInterface {
31
32   /**
33    * The date formatter service.
34    *
35    * @var \Drupal\Core\Datetime\DateFormatterInterface
36    */
37   protected $dateFormatter;
38
39   /**
40    * The current Request object.
41    *
42    * @var \Symfony\Component\HttpFoundation\Request
43    */
44   protected $request;
45
46   /**
47    * Constructs a TimestampAgoFormatter object.
48    *
49    * @param string $plugin_id
50    *   The plugin_id for the formatter.
51    * @param mixed $plugin_definition
52    *   The plugin implementation definition.
53    * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
54    *   The definition of the field to which the formatter is associated.
55    * @param array $settings
56    *   The formatter settings.
57    * @param string $label
58    *   The formatter label display setting.
59    * @param string $view_mode
60    *   The view mode.
61    * @param array $third_party_settings
62    *   Any third party settings.
63    * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
64    *   The date formatter service.
65    * @param \Symfony\Component\HttpFoundation\Request $request
66    *   The current request.
67    */
68   public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, DateFormatterInterface $date_formatter, Request $request) {
69     parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings);
70
71     $this->dateFormatter = $date_formatter;
72     $this->request = $request;
73   }
74
75   /**
76    * {@inheritdoc}
77    */
78   public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
79     // @see \Drupal\Core\Field\FormatterPluginManager::createInstance().
80     return new static(
81       $plugin_id,
82       $plugin_definition,
83       $configuration['field_definition'],
84       $configuration['settings'],
85       $configuration['label'],
86       $configuration['view_mode'],
87       $configuration['third_party_settings'],
88       $container->get('date.formatter'),
89       $container->get('request_stack')->getCurrentRequest()
90     );
91   }
92
93   /**
94    * {@inheritdoc}
95    */
96   public static function defaultSettings() {
97     return [
98       'future_format' => '@interval hence',
99       'past_format' => '@interval ago',
100       'granularity' => 2,
101     ] + parent::defaultSettings();
102   }
103
104   /**
105    * {@inheritdoc}
106    */
107   public function settingsForm(array $form, FormStateInterface $form_state) {
108     $form = parent::settingsForm($form, $form_state);
109
110     $form['future_format'] = [
111       '#type' => 'textfield',
112       '#title' => $this->t('Future format'),
113       '#default_value' => $this->getSetting('future_format'),
114       '#description' => $this->t('Use <em>@interval</em> where you want the formatted interval text to appear.'),
115     ];
116
117     $form['past_format'] = [
118       '#type' => 'textfield',
119       '#title' => $this->t('Past format'),
120       '#default_value' => $this->getSetting('past_format'),
121       '#description' => $this->t('Use <em>@interval</em> where you want the formatted interval text to appear.'),
122     ];
123
124     $form['granularity'] = [
125       '#type' => 'number',
126       '#title' => $this->t('Granularity'),
127       '#description' => $this->t('How many time interval units should be shown in the formatted output.'),
128       '#default_value' => $this->getSetting('granularity') ?: 2,
129       '#min' => 1,
130       '#max' => 6,
131     ];
132
133     return $form;
134   }
135
136   /**
137    * {@inheritdoc}
138    */
139   public function settingsSummary() {
140     $summary = parent::settingsSummary();
141
142     $future_date = new DrupalDateTime('1 year 1 month 1 week 1 day 1 hour 1 minute');
143     $past_date = new DrupalDateTime('-1 year -1 month -1 week -1 day -1 hour -1 minute');
144     $granularity = $this->getSetting('granularity');
145     $options = [
146       'granularity' => $granularity,
147       'return_as_object' => FALSE,
148     ];
149
150     $future_date_interval = new FormattableMarkup($this->getSetting('future_format'), ['@interval' => $this->dateFormatter->formatTimeDiffUntil($future_date->getTimestamp(), $options)]);
151     $past_date_interval = new FormattableMarkup($this->getSetting('past_format'), ['@interval' => $this->dateFormatter->formatTimeDiffSince($past_date->getTimestamp(), $options)]);
152
153     $summary[] = $this->t('Future date: %display', ['%display' => $future_date_interval]);
154     $summary[] = $this->t('Past date: %display', ['%display' => $past_date_interval]);
155
156     return $summary;
157   }
158
159   /**
160    * {@inheritdoc}
161    */
162   public function viewElements(FieldItemListInterface $items, $langcode) {
163     $elements = [];
164
165     foreach ($items as $delta => $item) {
166       if ($item->value) {
167         $updated = $this->formatTimestamp($item->value);
168       }
169       else {
170         $updated = [
171           '#markup' => $this->t('never'),
172         ];
173       }
174
175       $elements[$delta] = $updated;
176     }
177
178     return $elements;
179   }
180
181   /**
182    * Formats a timestamp.
183    *
184    * @param int $timestamp
185    *   A UNIX timestamp to format.
186    *
187    * @return array
188    *   The formatted timestamp string using the past or future format setting.
189    */
190   protected function formatTimestamp($timestamp) {
191     $granularity = $this->getSetting('granularity');
192     $options = [
193       'granularity' => $granularity,
194       'return_as_object' => TRUE,
195     ];
196
197     if ($this->request->server->get('REQUEST_TIME') > $timestamp) {
198       $result = $this->dateFormatter->formatTimeDiffSince($timestamp, $options);
199       $build = [
200         '#markup' => new FormattableMarkup($this->getSetting('past_format'), ['@interval' => $result->getString()]),
201       ];
202     }
203     else {
204       $result = $this->dateFormatter->formatTimeDiffUntil($timestamp, $options);
205       $build = [
206         '#markup' => new FormattableMarkup($this->getSetting('future_format'), ['@interval' => $result->getString()]),
207       ];
208     }
209     CacheableMetadata::createFromObject($result)->applyTo($build);
210     return $build;
211   }
212
213 }