Skip to content

Commit

Permalink
Merge pull request #7 from pboivin/imageset-sources
Browse files Browse the repository at this point in the history
enh(imageset): Refactor ImageSet configuration format
  • Loading branch information
pboivin authored Sep 1, 2022
2 parents 9d70232 + f02fbda commit 311b6fa
Show file tree
Hide file tree
Showing 9 changed files with 744 additions and 368 deletions.
80 changes: 42 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -467,8 +467,8 @@ echo $imageSet
/images/cache/01.jpg/1eac615f1a50f20c434e5944225bdd4f.jpg 1300w,
/images/cache/01.jpg/b8648e93b40b56d5c5a78acc7a23e3d9.jpg 1700w"
data-sizes="(max-width: 500px) 100vw, 50vw"
width="3840"
height="2160"
width="1700"
height="956"
>
```
</details>
Expand All @@ -489,17 +489,17 @@ With a tweak in configuration, `imageSet()` can handle multiple source images:

```php
$imageSet = $flou->imageSet([
'sources' => [
[
'image' => 'portrait.jpg',
'width' => '1023',
'media' => '(max-width: 1023px)',
],
[
'image' => 'landscape.jpg',
'width' => '1024',
'media' => '(min-width: 1024px)',
],
[
'image' => 'portrait.jpg',
'media' => '(max-width: 1023px)',
'sizes' => '100vw',
'widths' => [400, 800, 1200],
],
[
'image' => 'landscape.jpg',
'media' => '(min-width: 1024px)',
'sizes' => '66vw',
'widths' => [800, 1200, 1600],
],
]);
```
Expand All @@ -509,7 +509,6 @@ Then, the `picture()` method is used to render a `picture` element:
```php
echo $imageSet
->render()
->useAspectRatio()
->picture(['class' => 'my-image', 'alt' => 'Lorem ipsum']);
```

Expand All @@ -518,22 +517,27 @@ echo $imageSet

```html
<picture>
<source
media="(max-width: 1023px)"
data-srcset="/images/cache/portrait.jpg/1422c06dea2257858f6437b9675fba1c.jpg"
<source
media="(max-width: 1023px)"
data-sizes="100vw"
data-srcset="/images/cache/portrait.jpg/a50df0a8c8a84cfc6a77cf74b414d020.jpg 400w,
/images/cache/portrait.jpg/1422c06dea2257858f6437b9675fba1c.jpg 800w,
/images/cache/portrait.jpg/de828e8798017be816f79e131e41dcc9.jpg 1200w"
>
<source
media="(min-width: 1024px)"
data-srcset="/images/cache/landscape.jpg/1e147b93856eef676f00989ba28365f1.jpg"
data-sizes="66vw"
data-srcset="/images/cache/landscape.jpg/c6f9c52bea237b64cc98fc9f5f3f15c6.jpg 800w,
/images/cache/landscape.jpg/fcc882305b523e823c7a24df05045c5a.jpg 1200w,
/images/cache/landscape.jpg/a50df0a8c8a84cfc6a77cf74b414d020.jpg 1600w"
>
<img
class="lazyload my-image"
alt="Lorem ipsum"
style="aspect-ratio: 1.77777778; object-fit: cover; object-position: center;"
src="/images/cache/landscape.jpg/23a733056cc32e360e9cdef3e0be8fb4.jpg"
data-src="/images/cache/landscape.jpg/1e147b93856eef676f00989ba28365f1.jpg"
width="1024"
height="576"
<img
class="lazyload my-image"
alt="Lorem ipsum"
src="/images/cache/landscape.jpg/66d1d4a938d99f2b0234e08008af09a8.gif"
data-src="/images/cache/landscape.jpg/a50df0a8c8a84cfc6a77cf74b414d020.jpg"
width="1600"
height="900"
>
</picture>
```
Expand Down Expand Up @@ -618,7 +622,6 @@ See also: [Art-directed `picture` element example](#art-directed-picture-element
```html
<style>
.my-image {
max-width: 1024px;
width: 100%;
height: auto;
aspect-ratio: calc(3 / 4);
Expand All @@ -628,6 +631,7 @@ See also: [Art-directed `picture` element example](#art-directed-picture-element
@media screen and (min-width: 1024px) {
.my-image {
max-width: 66vw;
aspect-ratio: calc(16 / 9);
}
}
Expand All @@ -638,17 +642,17 @@ See also: [Art-directed `picture` element example](#art-directed-picture-element

```php
<?= $flou->imageSet([
'sources' => [
[
'image' => 'portrait.jpg',
'width' => '1023',
'media' => '(max-width: 1023px)',
],
[
'image' => 'landscape.jpg',
'width' => '1024',
'media' => '(min-width: 1024px)',
],
[
'image' => 'portrait.jpg',
'media' => '(max-width: 1023px)',
'sizes' => '100vw',
'widths' => [400, 800, 1200],
],
[
'image' => 'landscape.jpg',
'media' => '(min-width: 1024px)',
'sizes' => '66vw',
'widths' => [800, 1200, 1600],
],
])
->render()
Expand Down
102 changes: 8 additions & 94 deletions src/ImageSet.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

namespace Pboivin\Flou;

use InvalidArgumentException;

class ImageSet
{
public const DEFAULT_SIZES_VALUE = '100vw';
Expand All @@ -12,112 +10,28 @@ class ImageSet

protected $renderOptions = [];

protected $image;

protected $sizes;

protected $sources;

protected $data;

public function __construct(protected array $config, protected ImageFactory $factory)
{
$this->acceptConfig($config);

if (!$this->sources) {
throw new InvalidArgumentException("'sources' is not set.");
}

$this->prepareData();
}

protected function acceptConfig(array $config): void
{
foreach ($config as $key => $value) {
if (method_exists($this, $method = "set{$key}")) {
$this->$method($value);
} else {
throw new InvalidArgumentException("Invalid option '$key'.");
}
}
}

protected function prepareData()
{
$sizes = $this->sizes ?: static::DEFAULT_SIZES_VALUE;
$srcset = [];
$sourceImage = '';

foreach ($this->sources as $source) {
if (!isset($source['width'])) {
throw new InvalidArgumentException("Source is missing required 'width' option.");
}

if (!isset($source['image']) && !$this->image) {
throw new InvalidArgumentException(
"Missing required 'image' option on source or imageset."
);
}
$preparedConfig = (new ImageSetConfig($config))->get();

$sourceImage = $source['image'] ?? $this->image;

$srcset[] = [
'image' => $this->factory->image($sourceImage, [
'w' => $source['width'],
]),
'width' => "{$source['width']}",
];
}

$this->data = [
'sizes' => $sizes,
'srcset' => $srcset,
'lqip' => $this->factory->image($sourceImage),
];
}

protected function setImage(string $sourceFileName): self
{
$this->image = $sourceFileName;

return $this;
}

protected function setSizes(string $sizes): self
{
$this->sizes = $sizes;

return $this;
}

protected function setSources(array $sources): self
{
$this->sources = $sources;

return $this;
}

protected function setWidths(array $widths): self
{
$this->sources = array_map(fn ($i) => ['width' => (int) $i], $widths);

return $this;
$this->sources = new ImageSetSources($preparedConfig, $factory);
}

public function data(): array
{
return $this->data;
return [
'sources' => $this->sources->get(),
'lqip' => $this->sources->lqip(),
];
}

public function toArray(): array
{
return [
'sizes' => $this->data['sizes'],
'srcset' => array_map(function ($item) {
$item['image'] = $item['image']->toArray();
return $item;
}, $this->data['srcset']),
'lqip' => $this->data['lqip']->toArray(),
'sources' => $this->sources->toArray(),
'lqip' => $this->sources->lqip()->toArray(),
];
}

Expand Down
76 changes: 76 additions & 0 deletions src/ImageSetConfig.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php

namespace Pboivin\Flou;

use InvalidArgumentException;

class ImageSetConfig
{
protected $preparedConfig = [];

public function __construct(protected array $config)
{
if (isset($config['sources'])) {
$this->preparedConfig = $this->acceptLegacyConfig($config);
} else {
$this->preparedConfig = $this->acceptConfig($config);
}
}

protected function acceptLegacyConfig(array $config): array
{
if (isset($config['image'])) {
return $this->acceptConfig([
'image' => $config['image'],
'widths' => array_map(fn ($i) => (int) $i['width'], $config['sources']),
]);
}

return $this->acceptConfig(
array_map(function ($i) {
$i['widths'] = [$i['width']];
unset($i['width']);
return $i;
}, $config['sources'])
);
}

protected function acceptConfig(array $config): array
{
if (isset($config['image'])) {
return $this->validateItems([$config]);
}

$first = array_values($config)[0] ?? null;

if (is_array($first)) {
return $this->validateItems($config);
}

throw new InvalidArgumentException('Invalid ImageSet configuration — missing image.');
}

protected function validateItems(array $items): array
{
foreach ($items as $item) {
if (!isset($item['widths'])) {
throw new InvalidArgumentException(
"Missing required 'widths' argument for single image."
);
}

if (count($items) > 1 && !isset($item['media'])) {
throw new InvalidArgumentException(
"Missing required 'media' argument for multiple images."
);
}
}

return $items;
}

public function get(): array
{
return $this->preparedConfig;
}
}
Loading

0 comments on commit 311b6fa

Please sign in to comment.