Version 1
[yaffs-website] / web / core / modules / responsive_image / src / Entity / ResponsiveImageStyle.php
diff --git a/web/core/modules/responsive_image/src/Entity/ResponsiveImageStyle.php b/web/core/modules/responsive_image/src/Entity/ResponsiveImageStyle.php
new file mode 100644 (file)
index 0000000..5ad9d95
--- /dev/null
@@ -0,0 +1,268 @@
+<?php
+
+namespace Drupal\responsive_image\Entity;
+
+use Drupal\Core\Config\Entity\ConfigEntityBase;
+use Drupal\image\Entity\ImageStyle;
+use Drupal\responsive_image\ResponsiveImageStyleInterface;
+
+/**
+ * Defines the responsive image style entity.
+ *
+ * @ConfigEntityType(
+ *   id = "responsive_image_style",
+ *   label = @Translation("Responsive image style"),
+ *   handlers = {
+ *     "list_builder" = "Drupal\responsive_image\ResponsiveImageStyleListBuilder",
+ *     "form" = {
+ *       "edit" = "Drupal\responsive_image\ResponsiveImageStyleForm",
+ *       "add" = "Drupal\responsive_image\ResponsiveImageStyleForm",
+ *       "delete" = "Drupal\Core\Entity\EntityDeleteForm",
+ *       "duplicate" = "Drupal\responsive_image\ResponsiveImageStyleForm"
+ *     }
+ *   },
+ *   admin_permission = "administer responsive images",
+ *   config_prefix = "styles",
+ *   entity_keys = {
+ *     "id" = "id",
+ *     "label" = "label"
+ *   },
+ *   links = {
+ *     "edit-form" = "/admin/config/media/responsive-image-style/{responsive_image_style}",
+ *     "duplicate-form" = "/admin/config/media/responsive-image-style/{responsive_image_style}/duplicate",
+ *     "delete-form" = "/admin/config/media/responsive-image-style/{responsive_image_style}/delete",
+ *     "collection" = "/admin/config/media/responsive-image-style",
+ *   }
+ * )
+ */
+class ResponsiveImageStyle extends ConfigEntityBase implements ResponsiveImageStyleInterface {
+
+  /**
+   * The responsive image ID (machine name).
+   *
+   * @var string
+   */
+  protected $id;
+
+  /**
+   * The responsive image label.
+   *
+   * @var string
+   */
+  protected $label;
+
+  /**
+   * The image style mappings.
+   *
+   * Each image style mapping array contains the following keys:
+   *   - image_mapping_type: Either 'image_style' or 'sizes'.
+   *   - image_mapping:
+   *     - If image_mapping_type is 'image_style', the image style ID (a
+   *       string).
+   *     - If image_mapping_type is 'sizes', an array with following keys:
+   *       - sizes: The value for the 'sizes' attribute.
+   *       - sizes_image_styles: The image styles to use for the 'srcset'
+   *         attribute.
+   *   - breakpoint_id: The breakpoint ID for this image style mapping.
+   *   - multiplier: The multiplier for this image style mapping.
+   *
+   * @var array
+   */
+  protected $image_style_mappings = [];
+
+  /**
+   * @var array
+   */
+  protected $keyedImageStyleMappings;
+
+  /**
+   * The responsive image breakpoint group.
+   *
+   * @var string
+   */
+  protected $breakpoint_group = '';
+
+  /**
+   * The fallback image style.
+   *
+   * @var string
+   */
+  protected $fallback_image_style = '';
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(array $values, $entity_type_id = 'responsive_image_style') {
+    parent::__construct($values, $entity_type_id);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function addImageStyleMapping($breakpoint_id, $multiplier, array $image_style_mapping) {
+    // If there is an existing mapping, overwrite it.
+    foreach ($this->image_style_mappings as &$mapping) {
+      if ($mapping['breakpoint_id'] === $breakpoint_id && $mapping['multiplier'] === $multiplier) {
+        $mapping = [
+          'breakpoint_id' => $breakpoint_id,
+          'multiplier' => $multiplier,
+        ] + $image_style_mapping;
+        $this->keyedImageStyleMappings = NULL;
+        return $this;
+      }
+    }
+    $this->image_style_mappings[] = [
+      'breakpoint_id' => $breakpoint_id,
+      'multiplier' => $multiplier,
+    ] + $image_style_mapping;
+    $this->keyedImageStyleMappings = NULL;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function hasImageStyleMappings() {
+    $mappings = $this->getKeyedImageStyleMappings();
+    return !empty($mappings);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getKeyedImageStyleMappings() {
+    if (!$this->keyedImageStyleMappings) {
+      $this->keyedImageStyleMappings = [];
+      foreach ($this->image_style_mappings as $mapping) {
+        if (!static::isEmptyImageStyleMapping($mapping)) {
+          $this->keyedImageStyleMappings[$mapping['breakpoint_id']][$mapping['multiplier']] = $mapping;
+        }
+      }
+    }
+    return $this->keyedImageStyleMappings;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getImageStyleMappings() {
+    return $this->image_style_mappings;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setBreakpointGroup($breakpoint_group) {
+    // If the breakpoint group is changed then the image style mappings are
+    // invalid.
+    if ($breakpoint_group !== $this->breakpoint_group) {
+      $this->removeImageStyleMappings();
+    }
+    $this->breakpoint_group = $breakpoint_group;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getBreakpointGroup() {
+    return $this->breakpoint_group;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setFallbackImageStyle($fallback_image_style) {
+    $this->fallback_image_style = $fallback_image_style;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFallbackImageStyle() {
+    return $this->fallback_image_style;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function removeImageStyleMappings() {
+    $this->image_style_mappings = [];
+    $this->keyedImageStyleMappings = NULL;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function calculateDependencies() {
+    parent::calculateDependencies();
+    $providers = \Drupal::service('breakpoint.manager')->getGroupProviders($this->breakpoint_group);
+    foreach ($providers as $provider => $type) {
+      $this->addDependency($type, $provider);
+    }
+    // Extract all the styles from the image style mappings.
+    $styles = ImageStyle::loadMultiple($this->getImageStyleIds());
+    array_walk($styles, function ($style) {
+      $this->addDependency('config', $style->getConfigDependencyName());
+    });
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function isEmptyImageStyleMapping(array $image_style_mapping) {
+    if (!empty($image_style_mapping)) {
+      switch ($image_style_mapping['image_mapping_type']) {
+        case 'sizes':
+          // The image style mapping must have a sizes attribute defined and one
+          // or more image styles selected.
+          if ($image_style_mapping['image_mapping']['sizes'] && $image_style_mapping['image_mapping']['sizes_image_styles']) {
+            return FALSE;
+          }
+          break;
+        case 'image_style':
+          // The image style mapping must have an image style selected.
+          if ($image_style_mapping['image_mapping']) {
+            return FALSE;
+          }
+          break;
+      }
+    }
+    return TRUE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getImageStyleMapping($breakpoint_id, $multiplier) {
+    $map = $this->getKeyedImageStyleMappings();
+    if (isset($map[$breakpoint_id][$multiplier])) {
+      return $map[$breakpoint_id][$multiplier];
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getImageStyleIds() {
+    $image_styles = [$this->getFallbackImageStyle()];
+    foreach ($this->getImageStyleMappings() as $image_style_mapping) {
+      // Only image styles of non-empty mappings should be loaded.
+      if (!$this::isEmptyImageStyleMapping($image_style_mapping)) {
+        switch ($image_style_mapping['image_mapping_type']) {
+          case 'image_style':
+            $image_styles[] = $image_style_mapping['image_mapping'];
+            break;
+          case 'sizes':
+            $image_styles = array_merge($image_styles, $image_style_mapping['image_mapping']['sizes_image_styles']);
+            break;
+        }
+      }
+    }
+    return array_values(array_filter(array_unique($image_styles)));
+  }
+
+}