Updated to Drupal 8.5. Core Media not yet in use.
[yaffs-website] / web / modules / contrib / metatag / src / Plugin / metatag / Tag / MetaNameBase.php
index 2220dd4bcb24196690a7459af8cfd9707454e719..5eafb805a04b37e02ea237b7f451cf13f86519c6 100644 (file)
@@ -1,15 +1,14 @@
 <?php
 
-/**
- * Each meta tag will extend this base.
- */
-
 namespace Drupal\metatag\Plugin\metatag\Tag;
 
 use Drupal\Component\Plugin\PluginBase;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
 
+/**
+ * Each meta tag will extend this base.
+ */
 abstract class MetaNameBase extends PluginBase {
 
   use StringTranslationTrait;
@@ -63,17 +62,31 @@ abstract class MetaNameBase extends PluginBase {
   /**
    * True if URL must use HTTPS.
    *
-   * @var boolean
+   * @var bool
    */
   protected $secure;
 
   /**
    * True if more than one is allowed.
    *
-   * @var boolean
+   * @var bool
    */
   protected $multiple;
 
+  /**
+   * True if the URL value(s) must be absolute.
+   *
+   * @var bool
+   */
+  protected $absoluteUrl;
+
+  /**
+   * Retrieves the currently active request object.
+   *
+   * @var \Symfony\Component\HttpFoundation\Request
+   */
+  protected $request;
+
   /**
    * The value of the metatag in this instance.
    *
@@ -81,6 +94,13 @@ abstract class MetaNameBase extends PluginBase {
    */
   protected $value;
 
+  /**
+   * The attribute this tag uses for the name.
+   *
+   * @var string
+   */
+  protected $nameAttribute = 'name';
+
   /**
    * {@inheritdoc}
    */
@@ -88,7 +108,7 @@ abstract class MetaNameBase extends PluginBase {
     parent::__construct($configuration, $plugin_id, $plugin_definition);
 
     // Set the properties from the annotation.
-    // @TODO: Should we have setProperty() methods for each of these?
+    // @todo Should we have setProperty() methods for each of these?
     $this->id = $plugin_definition['id'];
     $this->name = $plugin_definition['name'];
     $this->label = $plugin_definition['label'];
@@ -98,37 +118,113 @@ abstract class MetaNameBase extends PluginBase {
     $this->type = $plugin_definition['type'];
     $this->secure = $plugin_definition['secure'];
     $this->multiple = $plugin_definition['multiple'];
+    $this->absoluteUrl = !empty($plugin_definition['absolute_url']);
+    $this->request = \Drupal::request();
   }
 
+  /**
+   * Obtain the meta tag's internal ID.
+   *
+   * @return string
+   *   This meta tag's internal ID.
+   */
   public function id() {
     return $this->id;
   }
+
+  /**
+   * This meta tag's label.
+   *
+   * @return string
+   *   The label.
+   */
   public function label() {
     return $this->label;
   }
+
+  /**
+   * The meta tag's description.
+   *
+   * @return bool
+   *   This meta tag's description.
+   */
   public function description() {
     return $this->description;
   }
+
+  /**
+   * The meta tag's machine name.
+   *
+   * @return string
+   *   This meta tag's machine name.
+   */
   public function name() {
     return $this->name;
   }
+
+  /**
+   * The meta tag group this meta tag belongs to.
+   *
+   * @return string
+   *   The meta tag's group name.
+   */
   public function group() {
     return $this->group;
   }
+
+  /**
+   * This meta tag's form field's weight.
+   *
+   * @return int|float
+   *   The form API weight for this. May be any number supported by Form API.
+   */
   public function weight() {
     return $this->weight;
   }
+
+  /**
+   * Obtain this meta tag's type.
+   *
+   * @return string
+   *   This meta tag's type.
+   */
   public function type() {
     return $this->type;
   }
+
+  /**
+   * Whether or not this meta tag must output secure (HTTPS) URLs.
+   *
+   * @return bool
+   *   Whether or not this meta tag must output secure (HTTPS) URLs.
+   */
   public function secure() {
     return $this->secure;
   }
+
+  /**
+   * Whether or not this meta tag supports multiple values.
+   *
+   * @return bool
+   *   Whether or not this meta tag supports multiple values.
+   */
   public function multiple() {
     return $this->multiple;
   }
 
   /**
+   * Whether or not this meta tag must output required absolute URLs.
+   *
+   * @return bool
+   *   Whether or not this meta tag must output required absolute URLs.
+   */
+  public function requiresAbsoluteUrl() {
+    return $this->absoluteUrl;
+  }
+
+  /**
+   * Whether or not this meta tag is active.
+   *
    * @return bool
    *   Whether this meta tag has been enabled.
    */
@@ -138,6 +234,12 @@ abstract class MetaNameBase extends PluginBase {
 
   /**
    * Generate a form element for this meta tag.
+   *
+   * @param array $element
+   *   The existing form element to attach to.
+   *
+   * @return array
+   *   The completed form element.
    */
   public function form(array $element = []) {
     $form = [
@@ -160,6 +262,10 @@ abstract class MetaNameBase extends PluginBase {
       $form['#description'] .= ' ' . $this->t('This will be able to extract the URL from an image field.');
     }
 
+    if (!empty($this->absolute_url)) {
+      $form['#description'] .= ' ' . $this->t('Any relative or protocol-relative URLs will be converted to absolute URLs.');
+    }
+
     // Optional handling for secure paths.
     if (!empty($this->secure)) {
       $form['#description'] .= ' ' . $this->t('Any links containing http:// will be converted to https://');
@@ -168,28 +274,65 @@ abstract class MetaNameBase extends PluginBase {
     return $form;
   }
 
+  /**
+   * Obtain the current meta tag's raw value.
+   *
+   * @return string
+   *   The current raw meta tag value.
+   */
   public function value() {
     return $this->value;
   }
 
+  /**
+   * Assign the current meta tag a value.
+   *
+   * @param string $value
+   *   The value to assign this meta tag.
+   */
   public function setValue($value) {
     $this->value = $value;
   }
 
+  /**
+   * Make the string presentable.
+   *
+   * @param string $value
+   *   The raw string to process.
+   *
+   * @return string
+   *   The meta tag value after processing.
+   */
   private function tidy($value) {
     return trim($value);
   }
 
+  /**
+   * Generate the HTML tag output for a meta tag.
+   *
+   * @return array|string
+   *   A render array or an empty string.
+   */
   public function output() {
-    if (empty($this->value)) {
+    // Parse out the image URL, if needed.
+    $value = $this->parseImageUrl();
+    $value = $this->tidy($value);
+
+    if (empty($value)) {
       // If there is no value, we don't want a tag output.
       $element = '';
     }
     else {
-      // Parse out the image URL, if needed.
-      $value = $this->parseImageURL();
-
-      $value = $this->tidy($value);
+      if ($this->requiresAbsoluteUrl()) {
+        // Relative URL.
+        if (parse_url($value, PHP_URL_HOST) == NULL) {
+          $value = $this->request->getSchemeAndHttpHost() . $value;
+        }
+        // Protocol-relative URL.
+        elseif (substr($value, 0, 2) === '//') {
+          $value = $this->request->getScheme() . ':' . $value;
+        }
+      }
 
       // If tag must be secure, convert all http:// to https://.
       if ($this->secure() && strpos($value, 'http://') !== FALSE) {
@@ -199,9 +342,9 @@ abstract class MetaNameBase extends PluginBase {
       $element = [
         '#tag' => 'meta',
         '#attributes' => [
-          'name' => $this->name,
+          $this->nameAttribute => $this->name,
           'content' => $value,
-        ]
+        ],
       ];
     }
 
@@ -217,7 +360,8 @@ abstract class MetaNameBase extends PluginBase {
    *   The form state.
    */
   public static function validateTag(array &$element, FormStateInterface $form_state) {
-    //@TODO: If there is some common validation, put it here. Otherwise, make it abstract?
+    // @todo If there is some common validation, put it here. Otherwise, make
+    // it abstract?
   }
 
   /**
@@ -227,39 +371,38 @@ abstract class MetaNameBase extends PluginBase {
    *   A comma separated list of any image URLs found in the meta tag's value,
    *   or the original string if no images were identified.
    */
-  protected function parseImageURL() {
+  protected function parseImageUrl() {
     $value = $this->value();
 
     // If this contains embedded image tags, extract the image URLs.
     if ($this->type() === 'image') {
       // If image tag src is relative (starts with /), convert to an absolute
-      // link.
+      // link; ignore protocol-relative URLs.
       global $base_root;
-      if (strpos($value, '<img src="/') !== FALSE) {
+      if (strpos($value, '<img src="/') !== FALSE && strpos($value, '<img src="//') === FALSE) {
         $value = str_replace('<img src="/', '<img src="' . $base_root . '/', $value);
       }
 
-      if (strip_tags($value) != $value) {
-        if ($this->multiple()) {
-          $values = explode(',', $value);
-        }
-        else {
-          $values = [$value];
-        }
+      if ($this->multiple()) {
+        // Split the string into an array, remove empty items.
+        $values = array_filter(explode(',', $value));
+      }
+      else {
+        $values = [$value];
+      }
 
-        // Check through the value(s) to see if there are any image tags.
-        foreach ($values as $key => $val) {
-          $matches = [];
-          preg_match('/src="([^"]*)"/', $val, $matches);
-          if (!empty($matches[1])) {
-            $values[$key] = $matches[1];
-          }
+      // Check through the value(s) to see if there are any image tags.
+      foreach ($values as $key => $val) {
+        $matches = [];
+        preg_match('/src="([^"]*)"/', $val, $matches);
+        if (!empty($matches[1])) {
+          $values[$key] = $matches[1];
         }
-        $value = implode(',', $values);
-
-        // Remove any HTML tags that might remain.
-        $value = strip_tags($value);
       }
+      $value = implode(',', $values);
+
+      // Remove any HTML tags that might remain.
+      $value = strip_tags($value);
     }
 
     return $value;