Updated all the contrib modules to their latest versions.
[yaffs-website] / web / modules / contrib / metatag / src / Plugin / metatag / Tag / MetaNameBase.php
1 <?php
2
3 namespace Drupal\metatag\Plugin\metatag\Tag;
4
5 use Drupal\Component\Plugin\PluginBase;
6 use Drupal\Core\Form\FormStateInterface;
7 use Drupal\Core\StringTranslation\StringTranslationTrait;
8
9 /**
10  * Each meta tag will extend this base.
11  */
12 abstract class MetaNameBase extends PluginBase {
13
14   use StringTranslationTrait;
15
16   /**
17    * Machine name of the meta tag plugin.
18    *
19    * @var string
20    */
21   protected $id;
22
23   /**
24    * Official metatag name.
25    *
26    * @var string
27    */
28   protected $name;
29
30   /**
31    * The title of the plugin.
32    *
33    * @var \Drupal\Core\Annotation\Translation
34    *
35    * @ingroup plugin_translatable
36    */
37   protected $label;
38
39   /**
40    * A longer explanation of what the field is for.
41    *
42    * @var \Drupal\Core\Annotation\Translation
43    *
44    * @ingroup plugin_translatable
45    */
46   protected $description;
47
48   /**
49    * The category this meta tag fits in.
50    *
51    * @var string
52    */
53   protected $group;
54
55   /**
56    * Type of the value being stored.
57    *
58    * @var string
59    */
60   protected $type;
61
62   /**
63    * True if URL must use HTTPS.
64    *
65    * @var bool
66    */
67   protected $secure;
68
69   /**
70    * True if more than one is allowed.
71    *
72    * @var bool
73    */
74   protected $multiple;
75
76   /**
77    * True if the URL value(s) must be absolute.
78    *
79    * @var bool
80    */
81   protected $absoluteUrl;
82
83   /**
84    * Retrieves the currently active request object.
85    *
86    * @var \Symfony\Component\HttpFoundation\Request
87    */
88   protected $request;
89
90   /**
91    * The value of the metatag in this instance.
92    *
93    * @var mixed
94    */
95   protected $value;
96
97   /**
98    * The attribute this tag uses for the name.
99    *
100    * @var string
101    */
102   protected $nameAttribute = 'name';
103
104   /**
105    * {@inheritdoc}
106    */
107   public function __construct(array $configuration, $plugin_id, array $plugin_definition) {
108     parent::__construct($configuration, $plugin_id, $plugin_definition);
109
110     // Set the properties from the annotation.
111     // @todo Should we have setProperty() methods for each of these?
112     $this->id = $plugin_definition['id'];
113     $this->name = $plugin_definition['name'];
114     $this->label = $plugin_definition['label'];
115     $this->description = $plugin_definition['description'];
116     $this->group = $plugin_definition['group'];
117     $this->weight = $plugin_definition['weight'];
118     $this->type = $plugin_definition['type'];
119     $this->secure = $plugin_definition['secure'];
120     $this->multiple = $plugin_definition['multiple'];
121     $this->absoluteUrl = !empty($plugin_definition['absolute_url']);
122     $this->request = \Drupal::request();
123   }
124
125   /**
126    * Obtain the meta tag's internal ID.
127    *
128    * @return string
129    *   This meta tag's internal ID.
130    */
131   public function id() {
132     return $this->id;
133   }
134
135   /**
136    * This meta tag's label.
137    *
138    * @return string
139    *   The label.
140    */
141   public function label() {
142     return $this->label;
143   }
144
145   /**
146    * The meta tag's description.
147    *
148    * @return bool
149    *   This meta tag's description.
150    */
151   public function description() {
152     return $this->description;
153   }
154
155   /**
156    * The meta tag's machine name.
157    *
158    * @return string
159    *   This meta tag's machine name.
160    */
161   public function name() {
162     return $this->name;
163   }
164
165   /**
166    * The meta tag group this meta tag belongs to.
167    *
168    * @return string
169    *   The meta tag's group name.
170    */
171   public function group() {
172     return $this->group;
173   }
174
175   /**
176    * This meta tag's form field's weight.
177    *
178    * @return int|float
179    *   The form API weight for this. May be any number supported by Form API.
180    */
181   public function weight() {
182     return $this->weight;
183   }
184
185   /**
186    * Obtain this meta tag's type.
187    *
188    * @return string
189    *   This meta tag's type.
190    */
191   public function type() {
192     return $this->type;
193   }
194
195   /**
196    * Whether or not this meta tag must output secure (HTTPS) URLs.
197    *
198    * @return bool
199    *   Whether or not this meta tag must output secure (HTTPS) URLs.
200    */
201   public function secure() {
202     return $this->secure;
203   }
204
205   /**
206    * Whether or not this meta tag supports multiple values.
207    *
208    * @return bool
209    *   Whether or not this meta tag supports multiple values.
210    */
211   public function multiple() {
212     return $this->multiple;
213   }
214
215   /**
216    * Whether or not this meta tag must output required absolute URLs.
217    *
218    * @return bool
219    *   Whether or not this meta tag must output required absolute URLs.
220    */
221   public function requiresAbsoluteUrl() {
222     return $this->absoluteUrl;
223   }
224
225   /**
226    * Whether or not this meta tag is active.
227    *
228    * @return bool
229    *   Whether this meta tag has been enabled.
230    */
231   public function isActive() {
232     return TRUE;
233   }
234
235   /**
236    * Generate a form element for this meta tag.
237    *
238    * @param array $element
239    *   The existing form element to attach to.
240    *
241    * @return array
242    *   The completed form element.
243    */
244   public function form(array $element = []) {
245     $form = [
246       '#type' => 'textfield',
247       '#title' => $this->label(),
248       '#default_value' => $this->value(),
249       '#maxlength' => 255,
250       '#required' => isset($element['#required']) ? $element['#required'] : FALSE,
251       '#description' => $this->description(),
252       '#element_validate' => [[get_class($this), 'validateTag']],
253     ];
254
255     // Optional handling for items that allow multiple values.
256     if (!empty($this->multiple)) {
257       $form['#description'] .= ' ' . $this->t('Multiple values may be used, separated by a comma. Note: Tokens that return multiple values will be handled automatically.');
258     }
259
260     // Optional handling for images.
261     if ((!empty($this->type())) && ($this->type() === 'image')) {
262       $form['#description'] .= ' ' . $this->t('This will be able to extract the URL from an image field.');
263     }
264
265     if (!empty($this->absolute_url)) {
266       $form['#description'] .= ' ' . $this->t('Any relative or protocol-relative URLs will be converted to absolute URLs.');
267     }
268
269     // Optional handling for secure paths.
270     if (!empty($this->secure)) {
271       $form['#description'] .= ' ' . $this->t('Any links containing http:// will be converted to https://');
272     }
273
274     return $form;
275   }
276
277   /**
278    * Obtain the current meta tag's raw value.
279    *
280    * @return string
281    *   The current raw meta tag value.
282    */
283   public function value() {
284     return $this->value;
285   }
286
287   /**
288    * Assign the current meta tag a value.
289    *
290    * @param string $value
291    *   The value to assign this meta tag.
292    */
293   public function setValue($value) {
294     $this->value = $value;
295   }
296
297   /**
298    * Make the string presentable.
299    *
300    * @param string $value
301    *   The raw string to process.
302    *
303    * @return string
304    *   The meta tag value after processing.
305    */
306   private function tidy($value) {
307     return trim($value);
308   }
309
310   /**
311    * Generate the HTML tag output for a meta tag.
312    *
313    * @return array|string
314    *   A render array or an empty string.
315    */
316   public function output() {
317     if (empty($this->value)) {
318       // If there is no value, we don't want a tag output.
319       return $this->multiple() ? [] : '';
320     }
321
322     // Parse out the image URL, if needed.
323     $value = $this->parseImageUrl();
324     $values = $this->multiple() ? explode(',', $value) : [$value];
325     $elements = [];
326     foreach ($values as $value) {
327       $value = $this->tidy($value);
328       if ($this->requiresAbsoluteUrl()) {
329         // Relative URL.
330         if (parse_url($value, PHP_URL_HOST) == NULL) {
331           $value = $this->request->getSchemeAndHttpHost() . $value;
332         }
333         // Protocol-relative URL.
334         elseif (substr($value, 0, 2) === '//') {
335           $value = $this->request->getScheme() . ':' . $value;
336         }
337       }
338
339       // If tag must be secure, convert all http:// to https://.
340       if ($this->secure() && strpos($value, 'http://') !== FALSE) {
341         $value = str_replace('http://', 'https://', $value);
342       }
343
344       $elements[] = [
345         '#tag' => 'meta',
346         '#attributes' => [
347           $this->nameAttribute => $this->name,
348           'content' => $value,
349         ],
350       ];
351     }
352
353     return $this->multiple() ? $elements : reset($elements);
354   }
355
356   /**
357    * Validates the metatag data.
358    *
359    * @param array $element
360    *   The form element to process.
361    * @param \Drupal\Core\Form\FormStateInterface $form_state
362    *   The form state.
363    */
364   public static function validateTag(array &$element, FormStateInterface $form_state) {
365     // @todo If there is some common validation, put it here. Otherwise, make
366     // it abstract?
367   }
368
369   /**
370    * Extract any image URLs that might be found in a meta tag.
371    *
372    * @return string
373    *   A comma separated list of any image URLs found in the meta tag's value,
374    *   or the original string if no images were identified.
375    */
376   protected function parseImageUrl() {
377     $value = $this->value();
378
379     // If this contains embedded image tags, extract the image URLs.
380     if ($this->type() === 'image') {
381       // If image tag src is relative (starts with /), convert to an absolute
382       // link; ignore protocol-relative URLs.
383       global $base_root;
384       if (strpos($value, '<img src="/') !== FALSE && strpos($value, '<img src="//') === FALSE) {
385         $value = str_replace('<img src="/', '<img src="' . $base_root . '/', $value);
386       }
387
388       if ($this->multiple()) {
389         // Split the string into an array, remove empty items.
390         $values = array_filter(explode(',', $value));
391       }
392       else {
393         $values = [$value];
394       }
395
396       // Check through the value(s) to see if there are any image tags.
397       foreach ($values as $key => $val) {
398         $matches = [];
399         preg_match('/src="([^"]*)"/', $val, $matches);
400         if (!empty($matches[1])) {
401           $values[$key] = $matches[1];
402         }
403       }
404       $value = implode(',', $values);
405
406       // Remove any HTML tags that might remain.
407       $value = strip_tags($value);
408     }
409
410     return $value;
411   }
412
413 }