Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/base/imagetransforms/EagerImageTransformerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,12 @@ interface EagerImageTransformerInterface
* @param Asset[] $assets
*/
public function eagerLoadTransforms(array $transforms, array $assets): void;

/**
* Eager-loads all the transforms for the given assets.
*
* @param Asset[] $assets
* @since 5.9.0
*/
public function eagerLoadAllTransforms(array $assets): void;
}
34 changes: 31 additions & 3 deletions src/elements/Asset.php
Original file line number Diff line number Diff line change
Expand Up @@ -1884,13 +1884,15 @@ public function getImg(mixed $transform = null, ?array $sizes = null): ?Markup
*
* @param string[] $sizes
* @param ImageTransform|string|array|null $transform A transform handle or configuration that should be applied to the image
* @param bool $preload Whether all requested transforms should be preloaded
* @return string|false The `srcset` attribute value, or `false` if it can’t be determined
* @throws InvalidArgumentException
* @since 5.9.0 Added $preload param
* @since 3.5.0
*/
public function getSrcset(array $sizes, mixed $transform = null): string|false
public function getSrcset(array $sizes, mixed $transform = null, bool $preload = false): string|false
{
$urls = array_filter($this->getUrlsBySize($sizes, $transform));
$urls = array_filter($this->getUrlsBySize($sizes, $transform, $preload));

if (empty($urls)) {
return false;
Expand Down Expand Up @@ -1933,10 +1935,12 @@ public function getSrcset(array $sizes, mixed $transform = null): string|false
*
* @param string[] $sizes
* @param ImageTransform|string|array|null $transform A transform handle or configuration that should be applied to the image
* @param bool $preload Whether all requested transforms should be preloaded
* @return array
* @since 5.9.0 Added $preload param
* @since 3.7.16
*/
public function getUrlsBySize(array $sizes, mixed $transform = null): array
public function getUrlsBySize(array $sizes, mixed $transform = null, bool $preload = false): array
{
if ($this->kind !== self::KIND_IMAGE) {
return [];
Expand All @@ -1963,6 +1967,30 @@ public function getUrlsBySize(array $sizes, mixed $transform = null): array
return [];
}

// eager load transforms
if ($preload) {
$baseTransform = [];
if ($transform) {
$baseTransform['width'] = $transform->width;
$baseTransform['height'] = $transform->height;
$baseTransform['mode'] = $transform->mode;
$baseTransform['position'] = $transform->position;
$baseTransform['quality'] = $transform->quality;
} else {
// if we don't have a transform, only use the width
$baseTransform['width'] = $currentWidth;
}

$transforms[] = $baseTransform;

foreach ($sizes as $size) {
[$value, $unit] = Assets::parseSrcsetSize($size);
$transforms[] = $value . $unit;
}

Craft::$app->getImageTransforms()->eagerLoadTransforms([$this], $transforms);
}

foreach ($sizes as $size) {
if ($size === '1x') {
$urls[$size] = $this->getUrl($transform);
Expand Down
18 changes: 11 additions & 7 deletions src/elements/db/AssetQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -848,11 +848,11 @@ public function folderPath(mixed $value): static
* ->all();
* ```
*
* @param string|array|null $value The transforms to include.
* @param string|array|null|bool $value The transforms to include.
* @return static The query object itself
* @uses $withTransforms
*/
public function withTransforms(string|array|null $value = null): static
public function withTransforms(string|array|null|bool $value = null): static
{
$this->withTransforms = $value;
return $this;
Expand All @@ -868,12 +868,16 @@ public function afterPopulate(array $elements): array

// Eager-load transforms?
if ($this->withTransforms && !$this->asArray) {
$transforms = $this->withTransforms;
if (!is_array($transforms)) {
$transforms = is_string($transforms) ? StringHelper::split($transforms) : [$transforms];
}
if ($this->withTransforms === true) {
Craft::$app->getImageTransforms()->eagerLoadAllTransforms($elements);
} else {
$transforms = $this->withTransforms;
if (!is_array($transforms)) {
$transforms = is_string($transforms) ? StringHelper::split($transforms) : [$transforms];
}

Craft::$app->getImageTransforms()->eagerLoadTransforms($elements, $transforms);
Craft::$app->getImageTransforms()->eagerLoadTransforms($elements, $transforms);
}
}

return $elements;
Expand Down
26 changes: 26 additions & 0 deletions src/imagetransforms/ImageTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,32 @@ public function eagerLoadTransforms(array $transforms, array $assets): void
}
}

/**
* @inheritdoc
*/
public function eagerLoadAllTransforms(array $assets): void
{
// Index the assets by ID
$assetsById = ArrayHelper::index($assets, 'id');

// Query for the indexes
$results = $this->_createTransformIndexQuery()
->where(['assetId' => array_keys($assetsById)])
->all();

foreach ($results as $result) {
// Get the transform's fingerprint
$transformFingerprint = $result['transformString'];

if ($result['format']) {
$transformFingerprint .= ':' . $result['format'];
}

$indexFingerprint = $result['assetId'] . ':' . $transformFingerprint;
$this->eagerLoadedTransformIndexes[$indexFingerprint] = $result;
}
}

// Protected methods
// =============================================================

Expand Down
20 changes: 20 additions & 0 deletions src/services/ImageTransforms.php
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,26 @@ public function eagerLoadTransforms(array $assets, array $transforms): void
}
}

/**
* Eager-loads all transform indexes for the given list of assets.
*
* @param array $assets
* @return void
* @throws InvalidConfigException
* @since 5.9.0
*/
public function eagerLoadAllTransforms(array $assets): void
{
if (empty($assets)) {
return;
}

$transformer = $this->getImageTransformer(ImageTransformer::class);
if ($transformer instanceof EagerImageTransformerInterface) {
$transformer->eagerLoadAllTransforms($assets);
}
}

/**
* @template T of ImageTransformerInterface
* @param class-string<T> $type
Expand Down
Loading